C#의 리플렉션은 런타임에 객체 타입을 검사하고 상호작용할 수 있는 강력한 기능입니다. 이를 통해 어셈블리, 모듈, 타입에 대한 정보를 얻고, 타입의 인스턴스를 동적으로 생성할 수 있습니다. 이 기능은 컴파일 시점에 구조를 알지 못하는 코드를 로드하고 실행해야 할 때 특히 유용합니다.
리플렉션의 기본 개념
리플렉션이란?
리플렉션은 실행 중에 어셈블리(컴파일된 코드 라이브러리), 모듈(어셈블리의 구성 요소), 타입(클래스, 인터페이스, 열거형)의 메타데이터를 검사할 수 있게 해줍니다.
리플렉션의 사용 사례
- 동적 타입 생성: 런타임에 결정된 타입 이름을 기반으로 객체를 생성하거나 메서드를 호출합니다.
- 속성 검사: 클래스나 메서드에 적용된 사용자 정의 속성을 검색합니다.
- 지연 바인딩: 런타임까지 타입이 알려지지 않은 객체의 메서드를 호출하거나 속성에 접근합니다.
어셈블리 동적 로딩
어셈블리를 동적으로 로드하면 컴파일 시 직접 참조하지 않고도 외부 라이브러리를 애플리케이션에 통합할 수 있습니다. 이는 구성 요소를 독립적으로 추가하거나 업데이트할 수 있는 유연한 애플리케이션을 만드는 데 도움이 됩니다.
어셈블리 로딩
System.Reflection 네임스페이스의 Assembly.Load 메서드를 사용하여 어셈블리를 로드할 수 있습니다:
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
// 어셈블리 이름으로 로드
Assembly myAssembly = Assembly.Load("MyLibrary");
// 로드된 어셈블리 세부 정보 표시
Console.WriteLine($"Loaded Assembly: {myAssembly.FullName}");
}
}
동적 인스턴스 생성
어셈블리가 로드되면, 해당 타입의 인스턴스를 생성할 수 있습니다:
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
// 어셈블리 동적 로드
Assembly myAssembly = Assembly.Load("MyLibrary");
// 로드된 어셈블리에서 타입 가져오기
Type myType = myAssembly.GetType("MyLibrary.MyClass");
if (myType != null)
{
// MyClass의 인스턴스를 동적으로 생성
object instance = Activator.CreateInstance(myType);
// 이 인스턴스에서 메서드 호출
MethodInfo methodInfo = myType.GetMethod("MyMethod");
methodInfo?.Invoke(instance, null);
}
}
}
멤버 접근
동적으로 생성된 인스턴스 내의 속성이나 필드에 접근할 수 있습니다:
PropertyInfo propertyInfo = myType.GetProperty("MyProperty");
if (propertyInfo != null)
{
var value = propertyInfo.GetValue(instance);
Console.WriteLine($"Property Value: {value}");
// 속성에 새 값 설정
propertyInfo.SetValue(instance, "New Value");
}
예외 처리
리플렉션과 동적 로딩을 사용할 때 FileNotFoundException, TargetInvocationException 등과 같은 예외가 발생할 수 있으므로 이를 처리하는 것이 중요합니다.
성능 고려사항
리플렉션은 큰 유연성을 제공하지만, 메타데이터 검사를 위한 추가 처리로 인해 직접 호출에 비해 성능 오버헤드가 발생할 수 있습니다.
실용적인 예제 시나리오
애플리케이션에 플러그인 시스템을 개발한다고 가정해 보겠습니다. 사용자는 별도의 DLL(어셈블리)을 통해 자신의 기능을 추가할 수 있습니다. 각 플러그인은 메인 애플리케이션에 정의된 공통 인터페이스를 구현하지만, 런타임까지는 다른 어셈블리에 존재합니다.
리플렉션이 어떻게 도움이 되는지 살펴보겠습니다:
- 메인 애플리케이션은 사용 가능한 플러그인을 찾기 위해 디렉토리를 스캔합니다.
- 각 플러그인의 어셈블리는 리플렉션을 사용하여 로드됩니다.
- 프로그램은 로드된 각 타입이 예상 인터페이스를 구현하는지 확인합니다.
- 그렇다면 인스턴스를 생성하고 해당 인터페이스에 정의된 특정 메서드를 호출하여 사용자의 플러그인이 소프트웨어에 원활하게 통합되도록 합니다. 이를 통해 변경 사항이 있을 때마다 애플리케이션을 다시 컴파일하지 않고도 플러그인을 추가할 수 있습니다.
결론적으로, 리플렉션을 이해하고 어셈블리를 동적으로 로드하는 방법을 알면 외부 콘텐츠에 따라 동작을 조정할 수 있는 유연한 애플리케이션을 만들 수 있으며, 플러그인이나 모듈과 같은 확장성 포인트와 핵심 기능 간의 분리를 유지할 수 있습니다.
'프로그래밍 > C#' 카테고리의 다른 글
| C#의 사전 정의된 속성: 코드에 메타데이터를 추가하는 강력한 도구 (0) | 2025.09.06 |
|---|---|
| C# 리플렉션: 동적 프로그래밍의 강력한 도구 (0) | 2025.09.06 |
| C# 리플렉션: 동적 프로그래밍의 강력한 도구 (0) | 2025.09.05 |
| C# 비동기 프로그래밍에서 취소 토큰의 중요성과 활용법 (0) | 2025.09.04 |
| 비동기 프로그래밍과 C#의 Task Parallel Library (TPL) 활용법 (0) | 2025.09.04 |