동적으로 클래스 조작하기?! 리플렉션 완전 정복 💡
프로그래밍 하다 보면, 특정 클래스나 메서드의 정보를 실행 중에 가져와야 할 때가 있습니다.
예를 들어,
클래스 이름만 알고 있고 해당 클래스를 동적으로 생성해야 한다면?
또는 프라이빗(private) 필드 값을 강제로 가져와야 한다면?!
이때 필요한 게 바로 Java 리플렉션 API(Reflection API) 입니다! 🚀
오늘은 리플렉션이 뭔지, 왜 필요한지, 어떻게 쓰는지 차근차근 알려드릴게요.
예제 코드까지 준비했으니, 끝까지 읽고 한번 직접 실행해보세요! 🎯
📌 리플렉션(Reflection)이란?
리플렉션(Reflection)은 런타임(실행 중) 에 클래스, 메서드, 필드 등의 정보를 가져오거나 조작할 수 있는 기능입니다.
✔️ 실행 중에 클래스 정보를 가져올 수 있음
✔️ 객체 없이도 메서드를 실행할 수 있음
✔️ 접근 불가능한(private) 필드도 강제로 읽거나 수정 가능
🤯 즉, 컴파일 타임(코드 작성 시점) 에 정해지지 않은 클래스도 다룰 수 있다는 점이 핵심입니다.
📌 리플렉션이 필요한 이유? 🤔
"굳이 리플렉션을 써야 할까?" 싶을 수도 있지만,
실제로는 프레임워크, 라이브러리, 동적 객체 생성 같은 곳에서 필수적으로 사용됩니다.
💡 대표적인 활용 사례:
✔️ 스프링 프레임워크: DI(의존성 주입)에서 객체를 동적으로 생성
✔️ JUnit: 테스트 메서드를 실행할 때, 특정 어노테이션(@Test)을 가진 메서드만 실행
✔️ JSON 파싱 라이브러리(Gson, Jackson): 클래스 정보를 기반으로 객체 변환
즉, 리플렉션이 없었다면 개발이 훨씬 빡셌을 겁니다... 😵💫
📌 리플렉션 사용법, 코드로 확인해보자!
자, 말보단 코드가 중요하죠!
아래 예제를 직접 실행해보면서 리플렉션이 어떻게 동작하는지 감 잡아봅시다.
✅ 1. 클래스 정보 가져오기
import java.lang.reflect.*;
class Person {
private String name = "홍길동";
public void sayHello() {
System.out.println("안녕하세요! 저는 " + name + "입니다.");
}
}
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// 클래스 정보 가져오기
Class<?> clazz = Class.forName("Person");
// 객체 생성
Object obj = clazz.getDeclaredConstructor().newInstance();
// 메서드 실행
Method method = clazz.getMethod("sayHello");
method.invoke(obj);
}
}
💡 실행 결과:
안녕하세요! 저는 홍길동입니다.
🎯 Class.forName("Person") 을 이용해서 클래스 정보를 가져오고,
🎯 .newInstance() 를 통해 객체를 동적으로 생성한 후,
🎯 .invoke() 로 메서드를 실행하는 방식입니다.
✅ 2. private 필드 접근 (강제 접근 😈)
import java.lang.reflect.*;
class Secret {
private String secretMessage = "이건 비밀입니다! 🤫";
}
public class PrivateFieldAccess {
public static void main(String[] args) throws Exception {
Secret secret = new Secret();
// 클래스 정보 가져오기
Class<?> clazz = secret.getClass();
// private 필드 가져오기
Field field = clazz.getDeclaredField("secretMessage");
// 접근 허용
field.setAccessible(true);
// 필드 값 읽기
String value = (String) field.get(secret);
System.out.println("비밀 메시지: " + value);
}
}
💡 실행 결과:
비밀 메시지: 이건 비밀입니다! 🤫
😎 원래 private 필드는 직접 접근할 수 없지만,
setAccessible(true) 를 사용하면 강제로 열 수 있습니다!
(하지만 너무 남용하면 보안상 위험할 수도 있으니 주의! ⚠️)
✅ 3. 동적으로 메서드 실행
import java.lang.reflect.*;
class Calculator {
public int add(int a, int b) {
return a + b;
}
}
public class DynamicMethodCall {
public static void main(String[] args) throws Exception {
Class<?> clazz = Calculator.class;
Object obj = clazz.getDeclaredConstructor().newInstance();
Method method = clazz.getMethod("add", int.class, int.class);
int result = (int) method.invoke(obj, 10, 20);
System.out.println("결과: " + result);
}
}
💡 실행 결과:
결과: 30
🎯 method.invoke(obj, 10, 20) 이렇게 파라미터를 넘겨주면,
🎯 동적으로 메서드를 호출할 수 있습니다!
📌 리플렉션, 장점과 단점? 🤔
🟢 장점
✅ 동적으로 객체를 생성할 수 있어 유연함
✅ 외부 라이브러리 없이도 클래스 정보를 활용 가능
✅ 접근 제한(private) 필드도 조작 가능
🔴 단점
⚠️ 성능 오버헤드 (일반 메서드 호출보다 속도가 느림)
⚠️ 보안 이슈 (private 필드를 강제 변경할 수 있어 위험)
⚠️ 코드 가독성이 떨어짐 (리플렉션 코드가 많으면 유지보수가 어려움)
그러므로 필요할 때만 신중하게 사용하는 것이 중요합니다!
📌 마무리 🎯
오늘 Java 리플렉션 API 의 개념부터 활용법까지 쭉 살펴봤는데요!
이제 실행 중에 클래스 정보를 가져오고, 메서드를 실행하고, 필드까지 조작하는 방법 감 잡으셨죠?
✅ 클래스 정보 가져오기: Class.forName()
✅ 동적으로 객체 생성하기: .newInstance()
✅ private 필드 접근: setAccessible(true)
✅ 동적 메서드 실행: method.invoke()
리플렉션은 Spring, JUnit, JSON 파싱 등 다양한 곳에서 필수적으로 사용됩니다.
한 번 익혀두면 더 강력한 Java 개발자가 될 수 있으니 꼭 연습해보세요!
혹시 더 궁금한 점 있으면 댓글 달아주세요! ✨
'Programming > JAVA' 카테고리의 다른 글
✅ Java Try-with-Resources, 제대로 알고 쓰자! (1) | 2025.03.02 |
---|---|
🚀 ThreadLocal, 이거 모르고 멀티스레드 프로그래밍 한다고?! 🤯 (0) | 2025.03.02 |