Reflection
📌 개념
👉 Java에서 Class, Interface, Fild, Method 등에 대한 정보를 Runtime에 동적으로 접근하고 조작할 수 있는 강력한 기능
- Reflection을 사용하면 프로그램이 자신의 구조에 대한 정보를 직접 조사하고, 실행 중에 객체의 Class를 알아내거나, Method와 Fild에 접근하고 Method를 호출하는 것이 가능하다 👉 이를 “각 Class의 Meta Data를 읽어온다” 라고 표현한다.
- 여기서 Meta Data를 가져온다는 것은 Class에 구현된 모든 Code, 또는 Method 내부에 구현된 모든 Code를 확인하는 것이 아니라, 특정 정보인 Meta Data를 조회할 수 있다는 의미
- Java의 Reflection API를 사용하여
Class
객체에서 다음과 같은 정보 (Meta Data)를 가져올 수 있다. - Class 이름
- Method 정보
- Fild 정보
- 생성자 정보
- 상위 Class 및 Interface 정보
- Annotation 정보
리플렉션의 단점
- 성능 저하 🚨
- 일반적인 코드보다 느림 (메서드 호출 시
invoke()
사용).
- 보안 문제 🔒
setAccessible(true)
로 private 필드/메서드에 접근 가능 → 보안 취약점이 생길 수 있음.
- 컴파일 타임 오류 발견 불가 ⏳
- 일반적인 코드에서는 컴파일러가 오류를 잡아주지만, Reflection을 사용하면 런타임 오류 발생 가능.
정리
✅ Reflection은 런타임에 클래스, 메서드, 필드 등의 정보를 조회하고 조작하는 기능
✅
getMethods()
, getFields()
, getConstructors()
등을 사용해 클래스 구조 탐색✅
setAccessible(true)
를 사용하면 private 필드/메서드에도 접근 가능✅
invoke()
로 동적으로 메서드 실행 가능✅ Spring, JSON 변환, AOP(Aspect-Oriented Programming) 등에 활용됨
✅ 대량의 Data를 작업할 시 Computer Resource를 많이 사용하게 되고, 속도 역시 느려질 수 밖에 없다
✅ ⚠️ 성능 저하와 보안 문제 때문에 남용하면 안 됨!
Situation
- A회사는 routing Program을 만들어서 B회사에 판매
- B회사는 동적 바인딩으로 method 구현
- But, B회사에 기능이 추가될 때마다 A회사에게 기능을 추가해 달라고 요청해야 하고 A회사는 B회사의 요청대로 Code를 수정해야 하는 번거로움 발생
package ex01;
import java.util.Scanner;
interface Controller {
void login();
void join();
void logout();
}
// 1. A회사
class Dispatcher {
Controller controller;
public Dispatcher(Controller controller) {
this.controller = controller;
}
public void routing(String path) {
if (path.equals("/login")) {
controller.login();
} else if (path.equals("/join")) {
controller.join();
} else if (path.equals("/logout")) {
controller.logout();
}
}
}
// 2. B회사 -> 구매할게 Controller 구현해서 만들어
class UserController implements Controller {
@Override
public void login() {
System.out.println("Login call");
}
@Override
public void join() {
System.out.println("Join call");
}
@Override
public void logout() {
System.out.println("Logout call");
}
}
public class App {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String path = sc.nextLine();
UserController uc = new UserController();
Dispatcher ds = new Dispatcher(uc);
ds.routing(path);
}
}
✅ 출력 결과
C:\workspace\tools\jdk-21\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.2.1\lib\idea_rt.jar=52444:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.2.1\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath C:\workspace\spring_lec\ref\out\production\ref ex01.App
/login
Login call
Process finished with exit code 0
C:\workspace\tools\jdk-21\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.2.1\lib\idea_rt.jar=52437:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.2.1\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath C:\workspace\spring_lec\ref\out\production\ref ex01.App
/join
Join call
Process finished with exit code 0
C:\workspace\tools\jdk-21\bin\java.exe "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.2.1\lib\idea_rt.jar=52297:C:\Program Files\JetBrains\IntelliJ IDEA 2024.3.2.1\bin" -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath C:\workspace\spring_lec\ref\out\production\ref ex01.App
/logout
Logout call
Process finished with exit code 0
Share article