프로그래밍/C#

C# 리플렉션: 런타임 객체 조작의 강력한 도구

shimdh 2025. 9. 15. 09:30
728x90

C#의 리플렉션은 프로그램이 런타임에 객체 타입을 검사하고 조작할 수 있게 해주는 강력한 기능입니다. 이 기능은 어셈블리, 모듈, 타입의 메타데이터에 대한 통찰력을 제공합니다. 특히 실행 시점까지 타입 정보가 알려지지 않는 동적 애플리케이션에서 매우 유용할 수 있습니다.

리플렉션 이해하기

리플렉션이란 무엇인가?

  • 어셈블리, 모듈, 타입 정보 획득: 리플렉션을 통해 로드된 어셈블리, 모듈, 타입에 대한 정보를 얻을 수 있습니다.
  • 객체 멤버 탐색: 객체의 속성, 메서드, 필드, 이벤트 및 기타 멤버를 동적으로 발견할 수 있습니다.

리플렉션을 사용하는 이유는?

  1. 동적 타입 생성: 컴파일 시점에 이름을 알지 못해도 런타임에 타입의 인스턴스를 생성할 수 있습니다.
  2. 어셈블리 검사: 특정 어셈블리에 어떤 클래스가 있는지 이해할 수 있습니다.
  3. 속성 검색: 클래스나 멤버에 적용된 사용자 정의 속성을 추가 메타데이터로 접근할 수 있습니다.

System.Reflection 네임스페이스의 주요 클래스

  • Assembly: 어셈블리(컴파일된 코드 라이브러리)를 나타냅니다.
  • Type: 타입 선언(클래스, 인터페이스)을 나타냅니다.
  • MethodInfo, PropertyInfo, FieldInfo: 각각 메서드, 속성, 필드에 대한 세부 정보를 제공합니다.
728x90

리플렉션 사용하기

어셈블리 로드하기

using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        // 어셈블리 로드
        Assembly assembly = Assembly.Load("mscorlib");

        // 어셈블리에 정의된 모든 타입 표시
        foreach (Type type in assembly.GetTypes())
        {
            Console.WriteLine(type.FullName);
        }
    }
}

이 예제에서는 mscorlib이라는 이름으로 .NET의 핵심 라이브러리를 로드하고, 그 어셈블리에 선언된 모든 타입을 반복하여 그들의 전체 이름을 출력합니다.

동적으로 인스턴스 생성하기

public class Person
{
    public string Name { get; set; }

    public void Greet()
    {
        Console.WriteLine($"Hello, my name is {Name}");
    }
}

class Program
{
    static void Main()
    {
        // Person 클래스의 타입 가져오기
        Type personType = typeof(Person);

        // 동적으로 인스턴스 생성
        object personInstance = Activator.CreateInstance(personType);

        // 리플렉션을 사용하여 속성 설정
        PropertyInfo nameProperty = personType.GetProperty("Name");
        nameProperty.SetValue(personInstance, "Alice");

        // 리플렉션을 사용하여 메서드 호출
        MethodInfo greetMethod = personType.GetMethod("Greet");
        greetMethod.Invoke(personInstance, null);
    }
}

이 예제에서는 속성과 메서드를 가진 간단한 Person 클래스를 정의하고, 리플렉션을 사용하여 Person의 인스턴스를 생성한 후 속성 값을 동적으로 설정하고 메서드를 호출합니다.

속성 접근하기

속성은 클래스나 멤버에 대한 추가 메타데이터를 제공합니다:

[Obsolete("This class is obsolete.")]
public class OldClass {}

class Program 
{
    static void Main() 
    {
       Type oldClassType = typeof(OldClass);
       var attributes = oldClassType.GetCustomAttributes(false);

       foreach (var attribute in attributes)
       {
           Console.WriteLine(attribute.ToString());
       }
     }
}

이 경우 OldClass는 사용자 정의 속성으로 구식으로 표시되었으며, 리플렉션을 사용하면 런타임 동안 관련 속성을 검색할 수 있습니다.

성능 고려사항

리플렉션은 큰 유연성을 제공하지만:

  • 직접 접근에 비해 늦은 바인딩으로 인해 성능 오버헤드를 초래할 수 있습니다.
  • 성능이 중요한 애플리케이션에서는 빈번한 사용을 최소화하거나 최적화해야 합니다.

결론

리플렉션은 개발자가 실행 중에 객체를 동적으로 검사할 수 있게 하여 메타데이터 탐색을 통해 프로그램 동작에 대한 귀중한 통찰력을 제공합니다. 그러나 성능과 유지보수성에 미치는 잠재적 영향을 고려하여 신중하게 사용해야 합니다. 이러한 개념을 이해하면 다양한 컨텍스트나 요구 사항에 따라 런타임에 적응할 수 있는 유연한 C# 애플리케이션을 작성하는 능력을 향상시킬 수 있습니다.

728x90