반영 (컴퓨터 과학)

위키백과, 우리 모두의 백과사전.
이동: 둘러보기, 검색

컴퓨터 과학에서, 반영(Reflection)은 컴퓨터 프로그램에서 런타임 시점에 사용되는 자신의 구조와 행위를 관리(type introspection)하고 수정할 수 있는 프로세스를 의미한다. “type introspection”은 객체 지향 프로그램언어에서 런타임에 객체의 형(type)을 결정할 수 있는 능력을 의미한다.

많은 컴퓨터 아키텍처에서, 프로그램 명령은 데이터와 같이 메모리에 적재되므로, 명령과 데이터 사이의 구분은 단지 컴퓨터와 프로그램 언어에 의하여 어떻게 정보가 처리되느냐의 문제이다. 일반적으로, 명령은 실행되고, 데이터는 (명령의 자료로서) 처리된다. 그렇지만, 어떤 언어에서는, 프로그램은 명령 역시 데이터와 같은 방식으로 처리 할 수 있기 때문에, Reflective 수정이 가능하게 된다. 가장 일반적으로 반영은 스몰토크, 스크립트 언어와 같이 높은 수준의 가상 머신 프로그램 언어에서 주로 많이 사용되고, 자바, C 언어와 같이 선언적이거나 정적 형식의 프로그램 언어에서는 드물게 사용된다.

이용[편집]

반영은 런타임에 프로그램의 수행을 수정하고, 관찰하기 위하여 사용할 수 있다. 반영 지향적인 프로그램 구성 요소는 내부 코드의 실행을 감시할 수 있고, 구성 요소 자신의 궁극적인 목표에 맞도록 내부를 수정 할 수 있다. 이는 전형적으로 런타임에 프로그램 코드를 동적으로 할당하여 이루어진다.

반영은 프로그램을 서로 다른 상황에서 동적으로 사용할 수 있게 한다. 예를 들어, 비슷한 동작을 수행하는 서로 다른 클래스 ‘X’와 클래스 ‘Y’를 교체하여 사용하는 응용 프로그램을 고려해보자. 반영 지향적이 아닌 프로그램 개발에서는, 응용 프로그램은 클래스 ‘X’와 클래스 ‘Y’의 함수를 호출하기 위하여, 함수(이름)을 직접 코드로 작성해야 한다. 반면, 반영 지향적인 프로그램 패러다임에서, 응용 프로그램은 함수(이름)을 직접 코드로 작성하지 않고, 클래스 ‘X’와 클래스 ‘Y’의 함수를 호출하기 위하여, 반영을 이용하여 설계되고 작성될 수 있다. 반영 지향적인 프로그램은 보다 보편적인(Generic) 코드의 수행의 기능을 사용하기 위하여, 거의 언제나 추가적인 정보, 프레임워크, 연관 사상, 객체 관계 등을 필요로 한다. 반영 지향적인 프로그램 기술을 확장하면, 하드 코딩을 방지할 수 있다.

기능[편집]

반영이 지원되는 언어는, 낮은 수준의 언어의 처리와는 다른, 런타임에 사용할 수 있는 매우 모호한 몇 가지 특성을 제공한다. 이런 특성들은 다음과 같다.

  • 런타임에 First-Class 객체로서 소스 코드의 생성자(코드 블록, 메소드, 프로토콜, ……)를 인식하고 수정할 수 있다.
  • 참조 및, 호출되는 클래스 또는 함수와 일치하는 문자열을 클래스 또는 함수의 기호 이름으로 변환할 수 있다.
  • 런타임에 소스 코드 구문으로 구성된 문자열을 평가할 수 있다.
  • 프로그래밍 구성에 새로운 의미 또는 의도를 부여하여, 프로그램 언어의 바이트 코드에 대한 새로운 번역기를 생성할 수 있다.

컴파일 언어들은 소스 코드에 대한 정보를 제공하기 위하여, 자신들의 런타임 시스템에 의존한다. 예를 들어, 컴파일 된 오브젝티브 C 실행 모듈은, 프로그램 컴파일 과정을 통하여 소스 코드와 메소드가 상응하는 테이블을 제공하여, 실행 모듈의 블록 안에 모든 메소드의 이름을 기록한다. 커먼 리스프(Common Lisp) 언어와 같이, 함수의 런타임 생성을 지원하는 컴파일 언어는 런타임 환경은 컴파일 또는 인터프리터를 포함해야 한다.

반영은 자동화된 소스 코드 변환 체계를 정의한 프로그램 변환 시스템을 사용하여, 반영 기법이 내장되지 않은 언어에서 구현될 수 있다.

예제[편집]

다음은 여러 언어에서 구현된 반영의 사용 예를 표시한다.

C#:

Int32 i = 1234;
Console.WriteLine(String.Format("{0}", i.ToString("F")));
 
Type t = typeof(Int32);
// Reflection 1
Object res1
    = t.InvokeMember("ToString", 
        System.Reflection.BindingFlags.InvokeMethod, 
        null, 
        i, 
        new Object[]{"C", CultureInfo.CreateSpecificCulture("ko-KR")});
Console.WriteLine(String.Format("{0}", res1));
 
// Reflection 2
System.Reflection.MethodInfo method 
    = t.GetMethod("ToString", new Type[] { typeof(String) });
Object res2 = method.Invoke(i, new Object[] {"X"});
Console.WriteLine(String.Format("{0}", res2));

Objective-C

NSString* str = [[NSString alloc] initWithString:@"1234"];
NSLog(@"%d", (int)[str length]);
 
// Reflection
Class class = NSClassFromString(@"NSString");
id idOfClass = [[class alloc] initWithString:@"Reflection"];
SEL selector = NSSelectorFromString(@"length");
NSLog(@"%d", (int)[idOfClass performSelector:selector]);
 
[str release];
[idOfClass release];

Python:

>>> class MyClass:
...     def Hello(self, sText):
...             return 'Hello ' + sText
...
>>> MyClass().Hello('Peter')
'Hello Peter'
>>> 
>>> getattr(globals()['MyClass'](), 'Hello')('Peter')
'Hello Peter'
>>>