복잡한뇌구조마냥

[JAVA] 리플렉션(Reflection) 기초 본문

BE/JAVA

[JAVA] 리플렉션(Reflection) 기초

지금해냥 2025. 8. 13. 10:18

1. 리플렉션이란?

  • 런타임에 클래스, 메서드, 필드, 생성자 등에 접근할 수 있는 자바 API
  • 즉, 코드가 실행되는 도중에 객체의 타입을 확인하고 동적으로 동작을 바꿀 수 있음
  • java.lang.reflect 패키지에 포함

👉 컴파일 시점에 알 수 없는 클래스/메서드를 런타임에 다룰 수 있다


2. 왜 필요한가?

  • 프레임워크/라이브러리(예: Spring, JPA) 내부 동작
    • 객체 자동 주입, 어노테이션 기반 설정
  • 런타임 로딩
    • 설정 파일(XML/Properties)에 적힌 클래스명을 읽어 객체 생성
  • 테스트/디버깅
    • private 필드 접근, 동적 프록시 생성 등

3. 기본 사용법

클래스 정보 가져오기

 
// 3가지 방법
Class<?> clazz1 = Class.forName("com.example.Member");
Class<?> clazz2 = Member.class;
Member m = new Member();
Class<?> clazz3 = m.getClass();

메서드/필드 접근

 
Class<?> clazz = Class.forName("com.example.Member");

// 필드 접근
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // private 접근 허용
Member m = new Member();
field.set(m, "홍길동");
System.out.println(field.get(m)); // "홍길동"

// 메서드 호출
Method method = clazz.getDeclaredMethod("setName", String.class);
method.invoke(m, "임꺽정");

생성자 이용

Constructor<?> cons = clazz.getConstructor(String.class);
Member m2 = (Member) cons.newInstance("강감찬");

4. 실무 활용 예시

(1) 어노테이션 처리

 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Controller { }

@Controller
class MyController {}

public class ReflectionExample {
    public static void main(String[] args) {
        Class<?> clazz = MyController.class;
        if (clazz.isAnnotationPresent(Controller.class)) {
            System.out.println("컨트롤러 등록!");
        }
    }
}

(2) DI 컨테이너 흉내내기

 
class Service {}

class Container {
    public Object getBean(String className) throws Exception {
        Class<?> clazz = Class.forName(className);
        return clazz.getDeclaredConstructor().newInstance();
    }
}

public class Main {
    public static void main(String[] args) throws Exception {
        Container c = new Container();
        Service s = (Service) c.getBean("com.example.Service");
        System.out.println(s);
    }
}

 


5. 장단점

✅ 장점

  • 유연한 코드 작성 가능
  • 프레임워크 개발에 필수적 (Spring, Hibernate 등)

❌ 단점

  • 성능 저하: 일반 메서드 호출보다 느림
  • 안정성 문제: 컴파일 시점에 오류 검출 불가 → 런타임 오류 발생 가능
  • 캡슐화 위반: private 필드까지 접근 가능 → 설계 의도 깨질 수 있음

6. 마무리

Reflection은 프레임워크·라이브러리의 핵심 기술이지만, 일반 애플리케이션 코드에서는 남용하지 않는 것이 좋습니다.
학습용으로는 DI, AOP, JPA 내부 동작을 이해하는 데 큰 도움이 됩니다.

LIST