Java 리플렉션(Reflection)은 실행 중(runtime)에 클래스, 인터페이스, 메서드, 필드 등에 대한 정보를 동적으로 조회하고 조작할 수 있는 기능입니다.
java.lang.reflect 패키지를 통해 제공됩니다.
- 클래스 이름만 알고 있을 때 동적으로 객체 생성
- 필드, 메서드, 생성자에 접근하여 값 읽기/쓰기
- 어노테이션 등 메타데이터 기반 프로그래밍
- 프레임워크(예: Spring, Jackson)에서 동적 바인딩, 객체 자동 주입, 직렬화 등에 활용
| 클래스 | 역할 |
|---|---|
Class<T> |
클래스 정보를 나타내는 핵심 클래스 |
Field |
클래스의 필드 정보 접근 |
Method |
메서드 정보 접근 및 실행 |
Constructor |
생성자 접근 및 호출 |
Class<?> clazz = Class.forName("com.example.MyClass");
System.out.println(clazz.getName());Field field = clazz.getDeclaredField("amount");
field.setAccessible(true);
Object value = field.get(obj); // obj의 amount 필드 값을 읽음Method method = clazz.getMethod("getAmount");
Object returnValue = method.invoke(obj); // obj.getAmount() 호출| 항목 | 설명 |
|---|---|
| 성능 저하 | 일반적인 호출보다 느림 (JVM 최적화 어려움) |
| 컴파일 타임 안정성 부족 | 문법 오류가 런타임 오류로 바뀔 수 있음 |
| 접근 제한 우회 | setAccessible(true)로 캡슐화 원칙 위배 |
- Spring Framework: 의존성 주입(DI), 프록시 기반 AOP
- Jackson/Gson: 객체 → JSON 직렬화/역직렬화
- JUnit/TestNG: 테스트 메서드 자동 실행
- Hibernate/JPA: 필드 및 관계 설정 기반 엔티티 매핑
넥사크로에서 백엔드로부터 받은 소수점 데이터(BigDecimal)가 다음과 같은 증상을 보임:
0.23423→0으로 표시됨123.45→123으로 표시됨- 넥사크로
Dataset에는 정상적으로BIGDECIMAL타입으로 설정되어 있음
📌 실제 문제는 넥사크로가 아닌 BFF(Backend for Frontend) 단에서 발생
BFF에서 객체 → Map 변환 시 Java 리플렉션 사용:
Map<String, Object> result = new HashMap<>();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
result.put(field.getName(), field.get(obj));
}이 때, BigDecimal도 Object로 들어가므로 내부 직렬화 시 타입 손실 발생 가능.
ObjectMapper또는 넥사크로 JSON 파서가BigDecimal을 정수로 간주- 특히
new BigDecimal("0.23423")도 내부에서longValue()등을 호출하면0이 됨
- 소수점 이하가 잘린 값이 들어오면 아무리
BIGDECIMAL,displayformat을 설정해도 무의미
if (value instanceof BigDecimal) {
map.put(field.getName(), ((BigDecimal) value).toPlainString());
} else {
map.put(field.getName(), value);
}toPlainString()을 쓰면"0.23423"처럼 정확한 표현 유지- 넥사크로에서 문자열로 받아도
BIGDECIMAL타입이면 정상 렌더링 가능
public class AmountDto {
public BigDecimal amount;
}- DTO 클래스 기반으로 JSON을 생성하면 리플렉션으로 인한 타입 손실 최소화
mapper.configure(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN, true);- Spring Boot 환경에서는
Jackson2ObjectMapperBuilderCustomizer로 전역 설정 가능