C#

C# 동적으로 메서드 호출하기: Reflection과 Type 활용

검은고양이개발자 2023. 12. 28. 11:01
반응형

Reflection 기본 설명 및 구조


종종 메서드의 이름이나 구조가 변경될 수 있는 환경에서 동적으로 메서드를 호출해야  때가 있습니다.

Reflection 은 프로그램이 실행 중에 자신의 구조를 검사하고 조작할 수 있는 기능을 제공하는데 예를 들어 특정 유형의 멤버를 찾거나 인스턴스를 동적으로 생성하는 데 사용될 수 있습니다.

 

Reflection 기능을 사용할 필요가 없는 경우는 다음과 같이 일반 객체를 생성해서 사용합니다.

BS2Event instance = new BS2Event();
object value = instance.FieldName;

 

 

리플렉션을 사용하는 경우는 다음과 같이 사용합니다.

Type structureType = typeof(BS2Event);
FieldInfo field = structureType.GetField("FieldName");
BS2Event instance = new BS2Event
{
	FieldName = "고양이"
};

object nameValue = field.GetValue(instance);

 

그렇다면 왜 굳이 이렇게 복잡한 과정을 거쳐서 Reflection 기능을 사용할까요

 

 

Reflection 의 장단점 및 사용하는 상황


Reflection은 실행 중에 코드를 조사하고 조작하는 기술입니다. 이를 통해 코드를 작성할 때 정확한 타입을 알지 못하거나 동적으로 다룰 필요가 있는 경우 사용됩니다. 또한 메서드의 이름이나 파라미터가 변경되더라도 코드를 수정하지 않고 사용할 수 있습니다. 하드 코딩을 피하고 동적으로 가져와서 사용할 수 있는 거죠.

 

다음은 예시 코드입니다.

// 메서드 이름을 동적으로 가져와서 호출
MethodInfo method = type.GetMethod("SomeMethod");
if (method != null)
{
    method.Invoke(instance, null);
}

 

만약 위 코드에서 method의 이름이 바뀐다 해도 아래와 같이 단순히 메서드의 이름만 변경해서 적용시킬 수 있습니다.

// 메서드 이름을 동적으로 가져와서 호출
MethodInfo method = type.GetMethod("NewMethodName");
if (method != null)
{
    method.Invoke(instance, null);
}

 

위와 같이 Reflection을 사용하는 건 코드를 유연하게 만들어 주지만, 다음과 같이 단점들도 존재합니다.

  1. 성능 저하 : Reflection은 실행 중에 타입 정보를 조사하기 때문에 성능에 영향을 미칠 수 있습니다. 특히, 많은 양의 Reflection을 사용하면 성능이 크게 저하될 수 있습니다.
  2. 컴파일 타임 검사 불가능 : Reflection을 사용하면 컴파일 타임에 코드를 검사할 수 없어서 잘못된 참조나 타입 사용으로 인한 오류를 런타임에만 확인할 수 있습니다.
  3. 가독성 감소 : Reflection 코드는 일반적으로 가독성이 떨어지며 디버깅이 어려울 수 있습니다. 코드를 이해하기 어려워지고 유지보수가 어려워질 수 있습니다.

따라서 Reflection을 사용하기 전에 필요한지 검토하고, 다른 대안이 없는 경우에만 사용하는 것이 좋습니다.

Reflection 없이도 충분히 타입 세이프하게 작성할 수 있다면, Reflection을 사용하지 않는 것이 바람직할 수 있습니다.

 

Reflection을 사용하는 상황


Reflection은 주로 다음과 같은 상황에서 사용될 수 있습니다.

  1. 동적 코드 생성 : Reflection을 사용하면 런타임에 타입을 알고 있는 경우에도 타입 정보를 사용하여 새로운 객체를 생성하거나 메서드를 호출할 수 있습니다. 특히, 코드를 컴파일할 때 알 수 없는 경우에 동적으로 코드를 생성할 때 활용할 수 있습니다.
  2. 다형성을 고려한 코드 작성 : 제네릭이나 다형성을 고려해야 할 때, Reflection을 사용하여 타입 정보를 동적으로 처리할 수 있습니다. 일반적으로 컴파일 타임에 알 수 없는 제네릭 타입을 처리하는 경우나 다형성을 활용하는 경우 Reflection이 도움이 될 수 있습니다.
  3. 외부 라이브러리나 API의 동적 호출 : 외부 라이브러리나 API를 사용할 때, Reflection을 통해 해당 라이브러리의 메서드나 속성 등을 동적으로 호출하는 경우가 있습니다. 이는 라이브러리의 버전이나 기능 변경에 대응하기 위한 유연성을 제공합니다.
  4. Attribute와 관련된 작업 : Reflection은 Attribute를 사용하여 코드에 메타데이터를 추가하고 이를 런타임에 동적으로 읽을 때 사용됩니다. 예를 들어, 특정 Attribute가 부여된 클래스를 찾아내거나, 속성의 Attribute를 확인하는 데 활용될 수 있습니다.
  5. 테스트 프레임워크나 DI(Dependency Injection) 컨테이너 : Reflection을 사용하여 테스트 케이스를 자동으로 찾거나, DI 컨테이너에서 객체를 생성 및 주입할 때 사용할 수 있습니다.

위와 같이 Reflection은 정적인 코드로는 처리하기 어려운 동적인 요구사항이나 런타임에 알 수 없는 정보를 다룰 때 유용합니다. 

 

저 같은 경우 특히 3번인 외부 라이브러리나 API 동적 호출 상황에서 사용하였는데 

라이브러리의 버전이나 기능이 변경될 경우 정적으로 코드를 작성하면 새로운 버전이나 변경된 기능에 대응하기 어렵기 때문에 Reflection을 사용하였습니다.

반응형