자바 리플렉션(Reflection), 마법처럼 클래스 속을 들여다보자!

석현·2025년 3월 12일

Insight

목록 보기
28/43
post-thumbnail

개발을 하다 보면 가끔 이런 생각이 들 수도 있습니다.

"이 객체, 어디서 왔지?"
"지금 내가 다루고 있는 클래스에 어떤 메서드가 있는 거야?"
"사용자가 입력한 클래스 이름을 동적으로 불러와 실행하고 싶은데 가능할까?"

이럴 때 필요한 것이 바로 자바 리플렉션(Reflection)!
리플렉션은 런타임에 클래스의 정보를 가져오고 조작할 수 있는 기능입니다.
쉽게 말해, 프로그램 실행 중에 내가 원하는 클래스, 메서드, 필드 등에 접근할 수 있게 해주는 마법 같은 기능이죠.


🤔 리플렉션을 왜 사용할까?

일반적으로 우리는 코드를 작성할 때 어떤 클래스에 어떤 메서드가 있는지 미리 알고 사용합니다.
예를 들어, 다음과 같이 Car 클래스의 drive() 메서드를 호출한다고 해볼까요?

Car myCar = new Car();
myCar.drive();

이렇게 하면 Car 클래스가 컴파일 시점에 정해져 있습니다.
즉, 코드를 실행하기 전부터 어떤 클래스인지, 어떤 메서드가 있는지 컴파일러가 다 알고 있어요.

그런데 만약, 어떤 클래스가 실행 중에 동적으로 결정된다면?
예를 들어, 사용자가 입력한 문자열을 바탕으로 클래스가 결정되는 경우를 생각해봅시다.

Scanner scanner = new Scanner(System.in);
System.out.print("사용할 클래스 이름을 입력하세요: ");
String className = scanner.nextLine();  // 사용자가 "Car" 입력

// 여기에 className에 해당하는 클래스의 객체를 동적으로 생성하려면?

이럴 때 리플렉션을 사용하면 런타임에 해당 클래스 정보를 가져와 객체를 만들고, 메서드를 실행할 수도 있습니다!


🚀 리플렉션의 기본 개념

자바 리플렉션을 이해하려면 Class 객체를 먼저 알아야 합니다.
자바에서 모든 클래스는 Class<?> 타입의 객체로 표현될 수 있어요.

📌 클래스 정보 가져오기

// 1. 클래스 리터럴 사용
Class<?> clazz1 = Car.class;

// 2. 문자열로 클래스 로딩
Class<?> clazz2 = Class.forName("com.example.Car");

// 3. 객체에서 클래스 정보 가져오기
Car myCar = new Car();
Class<?> clazz3 = myCar.getClass();

이렇게 가져온 Class<?> 객체를 사용하면 클래스의 메서드, 필드, 생성자 등의 정보를 가져올 수 있습니다.


🔥 리플렉션으로 동적 객체 생성 및 메서드 호출

자, 이제 본격적으로 동적으로 객체를 만들고 메서드를 실행하는 방법을 알아볼까요?

// 1. Class 객체 가져오기
Class<?> clazz = Class.forName("com.example.Car");

// 2. 기본 생성자로 객체 생성
Object obj = clazz.getDeclaredConstructor().newInstance();

// 3. 특정 메서드 가져오기
Method method = clazz.getMethod("drive");

// 4. 메서드 실행
method.invoke(obj);

이제 Car 클래스의 drive() 메서드가 실행됩니다!
즉, 우리는 Car 클래스를 직접 명시하지 않고도 런타임에 동적으로 메서드를 실행할 수 있게 된 것입니다.


🏗️ 리플렉션을 언제 사용할까?

✔ 1. 프레임워크 개발 (예: Spring, Hibernate)

Spring에서는 의존성 주입(Dependency Injection)을 할 때 리플렉션을 사용합니다.
예를 들어, @Autowired를 붙여놓으면 Spring이 알아서 객체를 주입해 주는데요,
이 과정에서 리플렉션을 사용해 적절한 클래스를 찾아 객체를 생성합니다.

✔ 2. JSON 변환 (예: Jackson, Gson)

JSON 데이터를 객체로 변환할 때도 리플렉션을 활용합니다.
예를 들어, { "name": "Alice", "age": 25 } 같은 JSON을 User 객체로 변환할 때,
필드 이름을 자동으로 매칭해서 값을 넣어주는 기능이 리플렉션 덕분에 가능합니다.

✔ 3. 테스트 프레임워크 (예: JUnit)

JUnit에서는 @Test가 붙은 메서드들을 자동으로 찾아 실행하는데,
이 과정에서도 리플렉션이 사용됩니다.

✔ 4. 플러그인 시스템

이클립스 같은 IDE에서는 사용자가 플러그인을 추가할 수 있는데,
어떤 플러그인이 로드될지는 미리 알 수 없으므로 리플렉션을 활용해 동적으로 로드합니다.


🚀 리플렉션 vs 다형성(Polymorphism)

근데 꼭 리플레이션이 좋을걸까요? 사실, 위처럼 리플렉션을 사용하지 않아도 다형성을 활용하면 같은 기능을 구현할 수 있습니다! (한국말은 끝까지 들어야합니다!)

✅ 다형성을 활용한 코드 (리플렉션 대체)

interface Vehicle {
    void drive();
}

class Car implements Vehicle {
    public void drive() {
        System.out.println("🚗 자동차가 달립니다!");
    }
}

class Bike implements Vehicle {
    public void drive() {
        System.out.println("🏍️ 오토바이가 달립니다!");
    }
}

public class PolymorphismExample {
    public static void main(String[] args) {
        Vehicle vehicle = getVehicle("Car");
        vehicle.drive();
    }

    public static Vehicle getVehicle(String type) {
        if (type.equals("Car")) return new Car();
        else if (type.equals("Bike")) return new Bike();
        return null;
    }
}

위 코드처럼 다형성을 이용하면 리플렉션 없이도 동일한 기능을 구현할 수 있습니다.


🏆 리플렉션 vs 다형성 비교 (장단점 정리)

비교 항목리플렉션(Reflection)다형성(Polymorphism)
유연성매우 높음 (런타임 동적 처리 가능)낮음 (컴파일 타임에 클래스 결정)
성능느림 (리플렉션 호출은 최적화 어려움)빠름 (JVM 최적화 가능)
안정성낮음 (런타임 오류 발생 가능)높음 (컴파일 타임에 체크됨)
사용 사례프레임워크(Spring), JSON 변환일반적인 객체 지향 프로그래밍
보안낮음 (private 접근 가능)높음 (캡슐화 유지)

결론적으로, 리플렉션은 꼭 필요한 경우가 아니면 사용을 피하는 것이 좋습니다.


🚀 마무리

리플렉션은 컴파일 시점에 알 수 없는 클래스나 메서드에 동적으로 접근할 수 있는 강력한 기능입니다.
하지만 무작정 사용하기보다는 다형성을 활용할 수 있는지 먼저 고려하는 것이 중요합니다.

프레임워크 개발 (Spring, Hibernate)
JSON 변환 (Jackson, Gson)
테스트 자동 실행 (JUnit)
플러그인 시스템

이런 곳에서 자주 활용되니, 기본 개념만 잘 이해하고 있어도 실무에서 큰 도움이 될 거예요!

🧐 여러분은 리플렉션을 어디에 사용해보고 싶으신가요?
댓글로 의견 남겨주시면 재미있게 이야기 나눠봐요! 🚀

profile
Learner

0개의 댓글