Programming/JAVA

Java 리플렉션 API, 써보셨나요? 🤔

철부지개발자 2025. 3. 2. 11:59
반응형

동적으로 클래스 조작하기?! 리플렉션 완전 정복 💡

프로그래밍 하다 보면, 특정 클래스나 메서드의 정보를 실행 중에 가져와야 할 때가 있습니다.


예를 들어,

클래스 이름만 알고 있고 해당 클래스를 동적으로 생성해야 한다면?
또는 프라이빗(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 개발자가 될 수 있으니 꼭 연습해보세요!

 

혹시 더 궁금한 점 있으면 댓글 달아주세요! ✨

반응형