# **자바 리플렉션(Reflection) 쉽게 배우기** ## **1. 리플렉션이란?** 리플렉션(Reflection)이란 **실행 중에 클래스의 정보를 조회하고, 필드·메서드·생성자를 동적으로 조작하는 기능**이다. 즉, **컴파일 시점이 아니라 런타임(실행 중)에 클래스 내부를 들여다보고 조작할 수 있다.** --- ## **2. 주요 클래스 및 메서드 정리** ### **(1) `Class` 클래스 (클래스 정보 조회)** | 메서드 | 설명 | |-----|---| | `Class.forName("클래스명")` | 클래스 객체 가져오기 (정적 로드) | | `Object.getClass()` | 인스턴스로부터 클래스 객체 얻기 | | `getName()` | 클래스 전체 이름 (`패키지.클래스명`) 반환 | | `getSimpleName()` | 클래스 단순 이름 반환 | | `getDeclaredFields()` | 선언된 모든 필드(`Field[]`) 조회 | | `getDeclaredMethods()` | 선언된 모든 메서드(`Method[]`) 조회 | | `getDeclaredConstructors()` | 선언된 모든 생성자(`Constructor[]`) 조회 | **예제 코드 (클래스 정보 출력)** ```java Class clazz = Class.forName("java.util.ArrayList"); System.out.println("클래스 이름: " + clazz.getName()); System.out.println("간단한 이름: " + clazz.getSimpleName()); System.out.println("패키지: " + clazz.getPackage().getName()); ``` ✅ **클래스의 이름과 패키지 정보를 확인할 수 있다!** --- ### **(2) `Field` 클래스 (필드 정보 조회 및 수정)** | 메서드 | 설명 | |-----|---| | `getName()` | 필드 이름 가져오기 | | `getType()` | 필드 타입 가져오기 | | `getModifiers()` | 접근 제어자 가져오기 | | `setAccessible(true)` | private 필드 접근 가능하게 설정 | | `get(Object obj)` | 특정 객체의 필드 값 가져오기 | | `set(Object obj, Object value)` | 특정 객체의 필드 값 변경 | **예제 코드 (필드 조회 및 값 변경)** ```java import java.lang.reflect.*; class Person { private String name = "John"; } public class ReflectionExample { public static void main(String[] args) throws Exception { Person person = new Person(); Class clazz = person.getClass(); Field field = clazz.getDeclaredField("name"); field.setAccessible(true); // private 접근 허용 System.out.println("기존 값: " + field.get(person)); field.set(person, "Alice"); // 값 변경 System.out.println("변경된 값: " + field.get(person)); } } ``` ✅ **private 필드도 강제로 조작할 수 있다!** --- ### **(3) `Method` 클래스 (메서드 정보 조회 및 호출)** | 메서드 | 설명 | |-----|---| | `getName()` | 메서드 이름 가져오기 | | `getParameterTypes()` | 메서드 매개변수 타입 가져오기 | | `getReturnType()` | 반환 타입 가져오기 | | `invoke(Object obj, Object... args)` | 메서드 실행 | **예제 코드 (메서드 실행)** ```java import java.lang.reflect.*; class Calculator { private int add(int a, int b) { return a + b; } } public class ReflectionExample { public static void main(String[] args) throws Exception { Calculator calc = new Calculator(); Class clazz = calc.getClass(); Method method = clazz.getDeclaredMethod("add", int.class, int.class); method.setAccessible(true); // private 접근 허용 int result = (int) method.invoke(calc, 5, 10); // 메서드 실행 System.out.println("결과: " + result); } } ``` ✅ **private 메서드도 실행할 수 있다!** --- ### **(4) `Constructor` 클래스 (생성자 정보 조회 및 인스턴스 생성)** | 메서드 | 설명 | |-----|---| | `getParameterTypes()` | 생성자 매개변수 타입 가져오기 | | `newInstance(Object... initargs)` | 새로운 인스턴스 생성 | **예제 코드 (객체 동적 생성)** ```java import java.lang.reflect.*; class Person { private String name; public Person(String name) { this.name = name; } public String getName() { return name; } } public class ReflectionExample { public static void main(String[] args) throws Exception { Class clazz = Person.class; Constructor constructor = clazz.getConstructor(String.class); Object person = constructor.newInstance("Charlie"); // 동적 생성 Method method = clazz.getMethod("getName"); System.out.println("이름: " + method.invoke(person)); // Charlie 출력 } } ``` ✅ **리플렉션을 이용해 생성자를 실행하고 객체를 만들 수 있다!** --- ### **(5) `Modifier` 클래스 (접근 제어자 확인)** | 메서드 | 설명 | |-----|---| | `isPublic(int mod)` | public 여부 확인 | | `isPrivate(int mod)` | private 여부 확인 | | `isStatic(int mod)` | static 여부 확인 | **예제 코드 (필드 접근 제어자 확인)** ```java import java.lang.reflect.*; class Sample { private int num; public static String text; } public class ReflectionExample { public static void main(String[] args) throws Exception { Field field = Sample.class.getDeclaredField("text"); int modifiers = field.getModifiers(); System.out.println("static인가? " + Modifier.isStatic(modifiers)); // true System.out.println("public인가? " + Modifier.isPublic(modifiers)); // true } } ``` ✅ **필드나 메서드가 `public`, `private`, `static`인지 확인할 수 있다!** --- ## **3. 리플렉션의 활용 예시** ✔ **DI(의존성 주입) 프레임워크(Spring)** → 리플렉션으로 객체를 생성하고 자동 주입 ✔ **JUnit 테스트 프레임워크** → `@Test` 붙은 메서드 자동 실행 ✔ **JSON 라이브러리(Jackson, Gson)** → 객체를 JSON으로 변환할 때 필드 조회 ✔ **프록시 패턴(AOP, 동적 프록시)** → 런타임에 동적 메서드 실행 --- ## **4. 리플렉션의 단점과 주의점** ❌ **성능 저하** → 리플렉션은 일반 메서드 호출보다 느리다. 자주 사용하면 성능 문제가 생길 수 있다. ❌ **보안 문제** → `setAccessible(true)`로 private 필드/메서드에 접근할 수 있어 보안 위험이 있다. ❌ **컴파일 타임 체크 불가능** → 오타나 잘못된 메서드 호출은 실행 시점에서야 오류가 발생한다. ✅ **따라서, 꼭 필요한 경우에만 사용하고 남용하지 않는 것이 좋다!** --- ## **5. 정리** ✅ **리플렉션은 실행 중 클래스 정보를 조회하고 조작할 수 있는 기능이다!** ✅ **`Class`, `Field`, `Method`, `Constructor` 클래스를 활용하면 필드 값 변경, 메서드 실행, 객체 생성 등이 가능하다!** ✅ **Spring, JSON 파싱, 테스트 프레임워크 등에서 널리 사용된다!** ✅ **하지만 성능 저하와 보안 문제를 고려하여 신중히 사용해야 한다!** ✔ **리플렉션을 잘 활용하면, 자바 프로그램을 더 유연하게 만들 수 있다!**