Java

간단 예제로 이해하는 Java 리플렉션

녹녹1 2025. 4. 20. 19:12

 

현장에서 설계 단계가  거의 끝나가며 이제 개발을 시작하고 있습니다. 공통 부분의 경우 부장님께서 만드신 코드를 함께 사용하기에 코드를 보던 중 낯선 방식의 코드가 보여 검색해 보니 ‘리플렉션(Reflection)’이라는 개념임을 알게 되었습니다.
그래서 이번 글에서는 리플렉션이 무엇인지 정리하고, 간단한 예제를 통해 그 동작 원리를 살펴보려 합니다.


1. 리플렉션(Reflection)이란 무엇인가?

  • 리플렉션은 컴파일 시점에 알 수 없는 클래스·메서드·필드 정보를 런타임에 꺼내와 조작할 수 있는 기능입니다 
  • 동적 유연성: 문자열로 전달된 클래스 이름만 알고 있어도 객체를 생성하거나, 메서드를 호출하거나, 필드를 읽고 쓸 수 있습니다.
  • 활용 예: 프레임워크(예: Spring, Hibernate)는 리플렉션으로 객체 의존성 주입(DI), 매핑, AOP 등 다양한 동적 기능을 구현합니다. 

2. 주요 메서드와 역할

기능 메서드 설명

클래스 로드 Class.forName("com.pkg.MyClass") 문자열 클래스명을 사용해 Class<?> 객체로 로드
생성자 조회 clazz.getDeclaredConstructor(ParamType.class,…) 지정 파라미터 시그니처를 갖는 생성자를 반환
객체 생성 ctor.newInstance(arg1,…) 조회한 Constructor로 실제 인스턴스를 생성
메서드 호출 clazz.getMethod("methodName", ParamType.class…) + invoke() 런타임에 메서드 정보를 가져와, 해당 인스턴스에서 호출
필드 접근·수정 clazz.getDeclaredField("fieldName") + setAccessible(true) + get()/set() private 필드도 포함해 값을 읽거나 쓸 수 있음

 


3. 리플렉션의 장·단점

장점

  • 유연성: 컴파일 시점에 타입을 몰라도 동적 로딩·생성·호출이 가능 
  • 프레임워크 지원: 스프링의 DI, Hibernate의 ORM 매핑 등 많은 라이브러리가 리플렉션에 기반 

단점

  • 성능 오버헤드: 런타임에 검사·호출 과정이 추가되어 일반 코드보다 느려질 수 있습니다 .
  • 가독성 저하: 코드가 복잡해지고, 컴파일 타임 타입 체크가 불가능해 런타임 오류 위험이 높아집니다.

4. 예제

다음은 문자열로 클래스명을 알고 있을 때 리플렉션으로 객체를 생성하고, 메서드를 호출필드를 세팅·출력하는 예제입니다.

📁 ProductVO.java

public class ProductVO {
    private String name;
    private int price;

    public ProductVO() { /* 기본 생성자 */ }

    public void setName(String name) { this.name = name; }
    public void setPrice(int price) { this.price = price; }

    public void printInfo() {
        System.out.println("상품명: " + name + ", 가격: " + price + "원");
    }
}

📁 ReflectionExample.java

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class ReflectionExample {
    public static void main(String[] args) throws Exception {
        // 1) 클래스 이름으로 로드
        Class<?> clazz = Class.forName("ProductVO");
        
        // 2) 기본 생성자 조회
        Constructor<?> ctor = clazz.getConstructor();
        
        // 3) 객체 생성
        Object product = ctor.newInstance();
        
        // 4) 메서드 조회 및 호출
        Method setName   = clazz.getMethod("setName", String.class);
        Method setPrice  = clazz.getMethod("setPrice", int.class);
        Method printInfo = clazz.getMethod("printInfo");
        
        setName.invoke(product, "치킨");
        setPrice.invoke(product, 20000);
        
        // 5) 출력
        printInfo.invoke(product);
    }
}

 

 

코드 역할

Class.forName("ProductVO") 문자열로 클래스를 불러옴
getConstructor() 기본 생성자를 가져옴
newInstance() 객체 생성
getMethod() 메서드 정보 가져옴
invoke() 해당 메서드를 호출함

 

 

🔍 출력 결과

상품명: 치킨, 가격: 20000원