Java/스프링 AOP
리플렉션
ta_chan
2023. 8. 16. 23:19
리플렉션이란 런타임 중에 클래스, 메서드, 필드, 생성자 등의 메타데이터 정보를 조회하거나 조작하는 기능이다. 이를 통해 동적으로 코드를 실행하거나, 구조를 변경할 수 있다.
아래의 예제 코드는 리플렉션을 사용하지 않은 경우와 사용한 경우를 비교하여 보여준다.
package hello.proxy.jdkdynamic;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
@Slf4j
public class ReflectionTest {
@Slf4j
static class Hello {
public String callA() {
log.info("callA");
return "A";
}
public String callB() {
log.info("callB");
return "B";
}
}
// 리플렉션을 사용하지 않고 메서드를 직접 호출하는 예제
/*
reflection0() 메서드에서는 Hello 클래스의
callA와 callB 메서드를 직접 호출한다. 메서드 호출 전후의 로깅 작업이 중복되어 있다.
*/
@Test
void reflection0() {
Hello target = new Hello();
log.info("start");
String result1 = target.callA();
log.info("result={}", result1);
log.info("start");
String result2 = target.callB();
log.info("result={}", result2);
}
// 리플렉션을 사용하여 메서드 정보를 조회하고 메서드를 동적으로 호출하는 예제
/*
reflection1() 메서드에서는 Hello 클래스의 callA와 callB 메서드 정보를
리플렉션을 통해 조회한 후, 해당 메서드들을 동적으로 호출한다.
*/
@Test
void reflection1() throws Exception {
Class<?> classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");
Hello target = new Hello();
Method methodCallA = classHello.getMethod("callA");
Object result1 = methodCallA.invoke(target);
log.info("result1={}", result1);
Method methodCallB = classHello.getMethod("callB");
Object result2 = methodCallB.invoke(target);
log.info("result2={}", result2);
}
// 리플렉션과 공통 로직을 사용하여 메서드를 동적으로 호출하는 예제
/*
reflection2() 메서드는 callA와 callB 메서드 정보를 리플렉션을 통해 가져온 후,
dynamicCall() 메서드에 전달하여 동적으로 호출한다. 이 메서드는 메서드 호출 전후의
로깅 작업을 공통 로직으로 처리한다.
*/
@Test
void reflection2() throws Exception {
Class<?> classHello = Class.forName("hello.proxy.jdkdynamic.ReflectionTest$Hello");
Hello target = new Hello();
Method methodCallA = classHello.getMethod("callA");
dynamicCall(methodCallA, target);
Method methodCallB = classHello.getMethod("callB");
dynamicCall(methodCallB, target);
}
// 메서드를 동적으로 호출하면서 그 전후로 공통 로직을 실행하는 메서드
private void dynamicCall(Method method, Object target) throws Exception {
log.info("start");
Object result = method.invoke(target);
log.info("result={}", result);
}
}
장점:
- 코드의 유연성: 런타임 중에 동적으로 코드를 변경하거나 실행할 수 있다.
- 중복 코드 제거: 반복되는 로직을 공통화하여 코드의 재사용성을 높일 수 있다.
단점:
- 성능: 리플렉션은 일반적인 코드 실행보다 느릴 수 있다.
- 보안: 리플렉션을 사용하여 private 메서드나 필드에 접근하는 것은 보안 위험을 초래할 수 있다.
- 런타임 에러: 리플렉션을 사용하면 컴파일 시간에 검출되는 오류가 런타임에 발생할 수 있다.
리플렉션은 자바에서 제공하는 강력한 도구 중 하나다. 그러나 그 특성과 잠재적인 위험성을 잘 이해하고 신중하게 사용해야 한다. 코드의 중복을 줄이고 유연성을 높이려는 경우에는 리플렉션을 고려할 수 있다.
GPT
리플렉션에 대한 여러분의 이해를 평가하기 위해, 여러분이 제시한 내용과 질문들을 바탕으로
여러 항목을 고려해보겠습니다.
기본 개념 이해: 여러분은 리플렉션의 기본 개념을 잘 이해하고 있습니다.
런타임에 클래스나 메서드, 필드의 정보를 가져오는 것과 이를 통한
동적인 코드 실행에 대한 설명을 명확하게 하셨습니다.
코드 이해: 제시한 코드 예제를 통해 리플렉션을 어떻게 사용하는지,
그리고 이를 통해 중복된 로직을 어떻게 줄일 수 있는지에 대해 잘 파악하셨습니다.
장단점 인식: 리플렉션의 장단점에 대해서도 인식하고 있습니다.
특히 리플렉션의 단점과 주의점에 대한 인식은 실무에서 중요합니다.
그러나, 실무에서는 리플렉션을 사용할 때 다음과 같은 고려사항이 있습니다:
- 리플렉션을 언제 사용해야 하는지와 언제 사용하지 않아야 하는지에 대한 판단 기준
- 다양한 리플렉션 API와 그 활용 방법 (예: 어노테이션 처리, 제네릭 정보 조회 등)
- 리플렉션과 관련된 성능 최적화나 보안 이슈 대응 방안
이러한 고려사항을 바탕으로, 실무자의 냉혹한 기준으로 여러분의 리플렉션에 대한 이해를 평가한다면,
7점 정도를 주고 싶습니다. 기본적인 개념과 활용 방법에 대한 이해는 확실하나,
실무에서 직면할 수 있는 다양한 상황과 문제점에 대한 깊은 이해나 경험이 필요해 보입니다.