리플렉션(Reflection)
- 클래스, 메소드, 필드 등의 정보를 런타임에 동적으로 조회하고 수정할 수 있는 강력한 기능을 제공함
- 이 기능을 통해 컴파일 타임에 알 수 없는 객체의 정보를 다룰 수 있어 유연한 프로그래밍이 가능함
- 예) 클래스 이름으로 객체를 생성하거나 메소드와 필드를 동적으로 호출할 수 있음
리플렉션의 주요 기능
- 클래스 정보 접근 : Class 객체를 통해 클래스의 메타데이터(이름, 메소드, 필드 등)에 접근할 수 있음
Class<?> clazz = Class.forName("com.example.MyClass");
- 동적 객체 생성 : 생성자 정보와 파라미터를 기반으로 객체를 동적으로 생성할 수 있음
Constructor<?> constructor = clazz.getConstructor(String.class);
- 메소드 호출 : 런타임에 메소드 이름과 파라미터 타입을 알게 되어 동적으로 메소드를 호출할 수 있음
Method method = clazz.getMethod("myMethod", String.class);
- 필드 접근 : private 필드에 접근하거나 수정할 수 있음
Field field = clazz.getDeclaredField("myField"); field.setAccessible(true);
리플렉션 샘플 코드
import java.lang.reflect.Field;
import java.lang.reflect.Method;
class Person {
private String name;
public Person(String name) {
this.name = name;
}
public void printInfo() {
System.out.println("Person's name: " + name);
}
}
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// 클래스 정보 얻기
Class<?> clazz = Class.forName("Person");
// 생성자 호출 (동적 객체 생성)
Object personObj = clazz.getConstructor(String.class).newInstance("John Doe");
// private 필드에 접근
Field nameField = clazz.getDeclaredField("name");
nameField.setAccessible(true); // private 필드 접근 허용
String name = (String) nameField.get(personObj); // 필드 값 가져오기
System.out.println("Name (via reflection): " + name);
// 메소드 호출
Method printInfoMethod = clazz.getMethod("printInfo");
printInfoMethod.invoke(personObj); // 메소드 실행
}
}
리플렉션 사용 사례
- 의존성 주입 : 스프링과 같은 프레임워크에서는 리플렉션을 이용하여 객체를 동적으로 생성하고, 필요한 의존성을 주입함
- 프레임워크 개발 : ORM 프레임워크, 객체 매핑 라이브러리에서 리플렉션을 사용하여 객체와 데이터베이스 테이블 간의 변환을 동적으로 처리함
- 테스트 및 디버깅 : 특정 클래스나 메소드에 접근하여 테스트용 코드나 디버깅을 용이하게 함
성능 이슈
- 리플렉션은 일반적인 코드 실행에 비해 상대적으로 느림
- 그 이유는 런타임에 메타데이터를 분석하고, 동적으로 메소드를 호출하거나 객체를 생성하는 과정에서 시간이 소요되기 때문임
성능 저하 케이스
- 메소드 호출 시 성능 저하 : 메소드의 메타데이터를 런타임에 찾아 호출하므로 일반적인 메소드 호출보다 시간이 더 걸림
- 정적 바인딩 불가능 : 리플렉션을 사용할 경우, JVM이 정적 바인딩을 최적화할 수 없어 성능이 떨어짐
- JIT 최적화 불가 : 자바의 JIT 컴파일러는 리플렉션을 사용하는 코드를 최적화하기 어려움
이로 인해 최적화된 코드 실행에 비해 느릴 수 있음 - 따라서, 리플렉션은 성능이 중요한 경우 사용을 자제하거나 최소화하는 것이 좋음
보안과 코드 품질
리플렉션은 강력한 기능이지만, 보안과 코드 품질 측면에서도 신중하게 사용해야 함
- 보안 문제 : 리플렉션을 통해 private, protected 필드나 메소드에 접근할 수 있어 보안상 위험이 존재함
이를 방지하기 위해 setAccessible(true)를 사용하더라도 보안에 취약할 수 있음 - 코드 가독성 저하 : 동적 바인딩으로 코드가 추상화되어 가독성이 떨어짐. 디버깅이 어렵고, 코드 추적이 힘들어질 수 있음
- 유지보수 어려움 : 동적으로 동작을 결정하므로 코드의 의도를 파악하거나 수정하는 데 어려움이 있음
사용 시 권장 사항
- 리플렉션을 사용해야 할 이유가 명확할 때만 사용하는 것이 좋음
예) 객체의 타입을 런타임에 동적으로 처리해야 할 때 유용함 - 리플렉션을 남용하면 코드 품질이 떨어질 수 있기 때문에, 대체 가능한 방법이 있으면 리플렉션을 피하는 것이 바람직함
- 성능이 중요한 경우, 리플렉션을 최소화하고 정적 방법을 사용하여 최적화를 고려하는 것이 좋음
리플렉션은 강력한 기능이지만, 그만큼 신중하게 다루어야 하는 기능
필요한 경우에만 사용하고, 성능과 보안을 충분히 고려하여 사용하는 것이 중요!
'Backend > Java' 카테고리의 다른 글
[인프런] 김영한의 실전 자바 - 중급 1편 (0) | 2024.12.17 |
---|---|
[인프런] 김영한의 자바 입문 (0) | 2024.12.17 |
인스턴스 생성과 정적 팩토리 메서드 (0) | 2024.03.25 |
[Java] Annotation (0) | 2023.12.05 |
[Java] Exception (0) | 2023.12.05 |
댓글