리플렉션(Reflection)은 자바에서 클래스, 메서드, 필드 등의 구조를 런타임에 동적으로 탐색하고 조작할 수 있게 해주는 기능이다. 즉, 컴파일 시점이 아닌 런타임에 객체의 정보에 접근하여 필드 값을 읽거나 쓰고, 메서드를 호출하거나, 객체를 생성할 수 있게 해 준다.
예를 들어, 특정 클래스의 객체를 생성할 때 일반적으로 new 클래스명()
같은 방법을 사용하지만, 리플렉션을 사용하면 클래스명을 문자열로 입력받아도 객체를 동적으로 생성할 수 있다. 이렇게 하면 프로그램이 동적으로 동작할 수 있는 유연성을 제공하게 된다.
private
접근 제어자가 있더라도 접근이 가능하다.Hibernate는 리플렉션 기능을 사용한다. 여기서 리플렉션을 사용하는 이유는 JPA 엔티티를 관리할 때, 개발자가 명시적으로 메서드를 호출하지 않아도 내부적으로 객체를 생성하고 필드를 설정할 수 있어야 하기 때문이다. 예를 들어, Hibernate는 데이터베이스에서 값을 가져올 때 엔티티 객체를 자동으로 생성하고, 그 객체의 필드 값을 설정해야 한다. 이때 리플렉션을 통해 기본 생성자를 호출하고 필드에 값을 주입하는 방식으로 작업을 처리한다.
Hibernate가 JPA 엔티티를 관리할 때, 다음과 같은 작업을 리플렉션을 통해 수행한다:
즉, 개발자가 직접 객체를 생성하지 않아도, Hibernate는 리플렉션을 통해 필요한 객체를 만들어 관리할 수 있다.
아래는 리플렉션을 사용한 예제 코드이다. 코드의 주요 부분마다 설명을 추가했으며, 보다 이해하기 쉽게 작성되었다.
import java.lang.reflect.*;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// 1. 클래스의 정보 조회
Class<?> clazz = Class.forName("com.example.MyClass");
// 2. 동적 객체 생성 (기본 생성자 호출)
Object obj = clazz.getDeclaredConstructor().newInstance();
// 3. 메서드 호출 (메서드 이름을 문자열로 받아서 실행)
Method method = clazz.getMethod("sayHello");
method.invoke(obj); // 동적으로 메서드 호출
// 4. 필드 값 읽고 쓰기
Field field = clazz.getDeclaredField("name");
field.setAccessible(true); // private 필드 접근 허용
field.set(obj, "New Name"); // 필드 값 설정
System.out.println("Updated Name: " + field.get(obj)); // 필드 값 출력
}
}
Class<?> clazz = Class.forName("com.example.MyClass");
MyClass
의 정보를 가져온다. clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("sayHello");
sayHello
라는 메서드를 가져와서 method.invoke(obj);
로 호출한다. Field field = clazz.getDeclaredField("name");
name
이라는 필드를 가져와 값 설정과 읽기가 가능하도록 한다.리플렉션은 매우 강력한 기능이지만, 성능에 약간의 부담이 생길 수 있고, 코드의 가독성이나 유지보수성을 떨어뜨릴 수 있으므로 필요할 때만 사용해야 한다.
+) getClass() -> 객체의 런타임 클래스를 나타내는 Class 객체를 반환함. 이 메서드는 리플렉션을 사용하여 런타임에 객체의 클래스 정보를 얻는 데 사용될 수 있으며, 객체의 클래스 타입을 확인할 때 유용하다.