개념공부

Reflection

Cadi 2026. 3. 26. 19:27

목차

    1. Reflection이란 ? 

    1) 개념 

    리플렉션(Reflection)은 '거울에 비친다'는 뜻을 담고 있다. 이를 코딩에서 적용하자면 프로그램이 실행중인 상황, 즉 런타임에 자신의 메타데이터를 거울로 보듯 들여다 본다는 뜻이다. 동적으로 객체 내부 구조를 검사하고, 조작할 수 있게 하는 개념이다. 

     

    2) 원리

    컴파일된 DC# 프로그램 (DLL 파일 등)에는 메타데이터가 기록되어 있다. 
    리플랙션은 System.Reflection 네임스페이스에 있는 클래스들 (FieldInfo, MethodInfo 등) 을 사용해 메타 데이터를 스캔한다.
    추가적으로 메타데이터를 기반으로 Private과 같은 변수/함수들도 값을 바꾸거나 특정 함수를 강제로 실행시킬 수 있다.

    아래는 간단한 예시다.

     

    Type targetType = typeof(Monster);
    
    // Monster 설계도 안에 있는 "Attack"이라는 이름의 함수 정보를 스캔해서 가져옵니다.
    MethodInfo attackMethod = targetType.GetMethod("Attack");

     

     

    2. Reflection의 기능

     

    https://learn.microsoft.com/ko-kr/dotnet/csharp/advanced-topics/reflection-and-attributes/

     

    특성 및 리플렉션 - C#

    특성을 사용하여 C#에서 메타데이터 또는 선언적 정보를 연결합니다. 어셈블리, 모듈 및 형식을 설명하는 리플렉션 API를 사용하여 런타임에 특성을 쿼리합니다.

    learn.microsoft.com

     

    아직 공부하지 않은 용어들이 많이 나와 차후에 작성 예정. 

    3. Unity에서의 Reflection 예시

     

    유니티에서 가장 많이 쓰이는 어트리뷰트인 [SerializeField]를 예시로 들어보자. 
    이 어트리뷰트는, Private이지만 인스펙터에서 조정가능하게 해달라는 메타 데이터를 닮고 있다. 

    유니티 에디터는 내부적으로 리플렉션을 사용해 인스펙터 창을 그린다.



    동작 과정을 간략화한 코드 예시이다.

    using System;
    using System.Reflection;
    
    public class Player 
    {
        // private이라서 원래는 외부에서 접근할 수 없다. 
        // SerialzieField라는 어트리뷰트를 붙여줘 인스펙터에 보이게 된다. 
        [SerializeField]
        private int _hp = 100; 
    }
    
    // 내부 리플렉션 과정(예시)
    public class UnityEditorMock
    {
        public void DrawInspector(object targetObject)
        {
            Type targetType = targetObject.GetType();
    
            // BindingFlags를 사용해 private(NonPublic) 변수까지 모두 스캔합니다.
            BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
            FieldInfo[] fields = targetType.GetFields(flags);
    
            foreach (FieldInfo field in fields)
            {
                // 해당 변수에 [SerializeField] 포스트잇이 붙어있는지 확인합니다.
                var attribute = field.GetCustomAttribute<SerializeField>();
                
                if (attribute != null)
                {
                    // 포스트잇이 있다면, 리플렉션을 이용해 private 변수임에도 현재 값을 읽어옵니다.
                    object currentValue = field.GetValue(targetObject);
                    Console.WriteLine($"인스펙터에 노출할 변수 발견: {field.Name}, 현재 값: {currentValue}");
                    
                    // 만약 유니티 인스펙터 창에서 사용자가 값을 200으로 수정했다면?
                    // SetValue를 통해 private 변수의 값을 강제로 변경합니다.
                    field.SetValue(targetObject, 200); 
                }
            }
        }
    }

     

    사실 실제로는

    namespace UnityEngine
    {
        [RequiredByNativeCode]
        public sealed partial class SerializeField : Attribute
        {
        }
    }

    다음과 같이 되어 있어 AI의 도움을 받았다. 

    4. Reflection의 장/단점

    장점

    • 유연성 : 이름만 알면 런타임에 제어가 가능하다. 
    • 확장성 및 자동화 : 유니티의 인스펙터 커스텀 에디터, 직렬화, 의존성 주입 등 강력한 프레임워크와 자동화 툴을 만드는데 필수적이다. 

      -> 물론 , 매 프레임 GetType을 사용해 이름으로 설계도를 찾는 것은 성능상 큰 문제겠지만 1초에 한 두 번이나 로딩, 초반부에 하는 것은 성능상 큰 문제가 발생하지 않는다. 

    단점

    • 성능 저하 : 일반적인 대입 연산은 주소를 바로 찾아가지만, 리플렉션은 매 번 설계도를 펼치고 문자열로 이름을 검색하고 찾아간다. 따라서 성능저하가 있다. 이를 방지하기 위해서는 한 번 찾은 정보를 변수에 저장해두고 쓰는 캐싱 과정이 필수이다.
    • 캡슐화 파괴 : 우리가 C#에서 중요하게 생각하는 것들 중 하나는 캡슐화이다. 다만 리플렉션을 무분별하게 사용하면 이를 해함.
    • 유지보수 위험성 : GetField("이름") 처럼 문자열에 의존하기 때문에, 유지보수가 어렵다. 

     

    '개념공부' 카테고리의 다른 글

    C# Type (0327 수정)  (0) 2026.03.26
    C# 프로퍼티(Property)  (0) 2026.03.14
    동기와 비동기  (0) 2026.03.12
    Delegate,Action,Event,UnityEvent  (0) 2026.03.04
    동적 계획법 (Dynamic Programming, DP)  (0) 2025.03.19