GPT Archiving

리플렉션

99duuk 2025. 1. 11. 01:35

스프링의 리플렉션(Reflection)을 쉽게 이해하려면, 리플렉션을 "비밀의 문을 열고 안을 들여다보는 열쇠"에 비유할 수 있어요.


비유: 비밀의 상자와 마스터 키

  1. 비밀의 상자(클래스)
    어떤 클래스는 내부에 어떤 내용(필드, 메서드, 생성자 등)을 가지고 있는지 잘 모를 수 있어요. 예를 들어, 친구가 만든 상자(클래스)가 있는데, 그 안에 뭐가 들었는지 알려주지 않았다고 상상해 보세요.

  2. 마스터 키(리플렉션)
    리플렉션은 이 비밀 상자의 내용을 몰라도, 상자 안을 열어보고, 필요한 것을 꺼내거나 사용할 수 있는 마스터 키와 같아요.
    즉, 우리가 클래스를 컴파일 시간에 몰라도, 실행 시간에 그 내용을 확인하고 사용할 수 있게 해주는 도구입니다.

  3. 예시 상황

    • 친구가 준 상자(Class)가 있는데, 그 안에 있는 물건(Method)을 꺼내야 해요.
    • 상자에 무슨 물건이 있는지 몰라도, 리플렉션(마스터 키)을 사용하면 상자 안을 열어서 물건의 이름을 확인하거나, 필요한 물건을 꺼내서 사용할 수 있어요.

리플렉션의 핵심 기능

  • 클래스 정보를 가져오기:
    상자(클래스)가 무엇인지 몰라도, 이름(ClassName)을 읽거나 안에 뭐가 있는지 확인할 수 있어요.
    Class.forName("com.example.MyClass") 같은 코드로 클래스 정보를 가져옴.

  • 필드/메서드 탐색 및 접근:
    상자(클래스) 안에 숨겨진 물건(필드, 메서드)을 꺼내볼 수 있어요.
    getDeclaredMethods()로 메서드 목록 가져오기, invoke()로 실행하기.

  • 인스턴스 생성:
    상자 안의 물건을 사용하려면 상자를 복사해야 할 수도 있죠.
    newInstance()로 객체를 생성할 수 있어요.


실제 코드와 비유 연결

// "비밀의 상자" 클래스
class SecretBox {
    private String secret = "비밀 메시지";
    public String open() {
        return "상자가 열렸습니다!";
    }
}

// 리플렉션으로 상자를 열어보기
Class<?> clazz = Class.forName("SecretBox"); // 비밀 상자 정보를 가져옴
Object box = clazz.getDeclaredConstructor().newInstance(); // 상자(인스턴스) 생성

// 비밀 내용(필드) 확인
Field secretField = clazz.getDeclaredField("secret");
secretField.setAccessible(true); // 마스터 키로 잠금 해제
String secret = (String) secretField.get(box); // 비밀 메시지 꺼내기

System.out.println("비밀 내용: " + secret); // 비밀 내용: 비밀 메시지

// 메서드 실행
Method openMethod = clazz.getMethod("open");
String result = (String) openMethod.invoke(box);
System.out.println(result); // 상자가 열렸습니다!

장점과 주의사항

  • 장점:
    리플렉션은 코드를 동적으로 다룰 수 있게 해줘서, 프레임워크 개발이나 동적 로직 처리에 유용해요.
    예를 들어, 스프링의 DI(의존성 주입)나 JPA의 엔티티 매핑은 리플렉션 없이는 불가능하죠.

  • 주의사항:

    • 리플렉션은 성능에 영향을 줄 수 있어요. (리플렉션은 실행 시간에 동작하므로 무거움)
    • 보안적으로 민감한 정보(예: private 필드)를 다룰 수 있기 때문에 남용하면 위험해요.

결론

리플렉션은 비밀의 상자 안에 있는 내용을 열어보고, 필요한 것을 꺼내 쓸 수 있는 만능 열쇠와 같아요.
하지만 너무 자주 사용하면 상자가 고장날 수도 있으니(성능 문제), 정말 필요한 곳에서만 신중히 사용하는 것이 좋아요! 😊



스프링의 동작이 리플렉션을 기반으로 싱글톤인 서비스와 컨트롤러의 메서드를 객체로 가져오는 방식으로 동작한다는 설명은 부분적으로만 맞습니다. 스프링의 작동 방식은 훨씬 더 복잡하고 다양한 기술이 조합되어 있지만, 핵심적으로 다음과 같은 개념이 포함됩니다.


1. 스프링 컨테이너와 빈 관리

  • 스프링 컨테이너(ApplicationContext)는 애플리케이션 실행 시점에 @Controller, @Service, @Repository, @Component 등으로 등록된 클래스들을 탐색해 빈(bean)으로 생성하고 관리합니다.
  • 싱글톤 스코프는 스프링의 기본 스코프로, 한 번 생성된 빈은 컨테이너에서 재사용됩니다.

스프링이 컨트롤러와 서비스를 싱글톤으로 관리하는 이유는 메모리와 성능 효율성을 위해서입니다. 한 번 생성된 객체를 여러 요청에서 재사용할 수 있도록 보장합니다.


2. 스프링이 리플렉션을 사용하는 부분

스프링은 리플렉션을 내부적으로 사용합니다. 주요 사용 사례는 다음과 같습니다:

(1) 클래스 탐색 및 빈 등록

스프링은 애플리케이션 실행 시 @ComponentScan이나 XML 설정을 기반으로 클래스 정보를 스캔합니다. 여기서 리플렉션을 사용해 해당 클래스의 메타데이터를 분석하고 빈으로 등록합니다.

@Controller
public class MyController {
    @Autowired
    private MyService myService;

    @GetMapping("/hello")
    public String hello() {
        return myService.getMessage();
    }
}
  • 스프링은 @Controller@Service 어노테이션을 기반으로 클래스 정보를 스캔합니다.
  • 이 과정에서 리플렉션으로 클래스 구조를 읽고 필요한 빈으로 등록합니다.

(2) DI(의존성 주입)

스프링은 @Autowired 또는 생성자 주입 등을 통해 의존성을 주입할 때도 리플렉션을 사용합니다. 런타임에 해당 필드나 생성자 정보를 읽고, 적절한 빈을 주입합니다.

@Autowired
private MyService myService;
  • 리플렉션으로 myService 필드의 타입을 확인한 뒤, 컨테이너에 있는 적합한 빈을 주입합니다.

(3) 핸들러 메서드 매핑

스프링 MVC는 요청 URL을 컨트롤러 메서드와 매핑할 때 리플렉션을 사용합니다.

@GetMapping("/hello")
public String hello() {
    return "Hello";
}
  • @GetMapping 어노테이션으로 지정된 URL(/hello)을 읽기 위해 리플렉션으로 해당 메서드의 정보를 탐색합니다.
  • 이후 HTTP 요청이 들어오면 해당 메서드를 호출하는 과정도 리플렉션으로 처리됩니다.

3. 싱글톤인 서비스와 컨트롤러의 동작

  • 싱글톤: 스프링은 기본적으로 @Controller, @Service 등을 싱글톤으로 관리합니다. 한 번 생성된 객체는 스프링 컨테이너에서 재사용됩니다.
  • 메서드 호출: 스프링은 리플렉션으로 메서드를 탐색하고 매핑을 설정한 뒤, HTTP 요청이 들어올 때 해당 메서드를 호출합니다.

4. 리플렉션만으로 모든 것을 처리하지 않는다

스프링은 리플렉션만으로 동작하지 않습니다. 리플렉션은 클래스 구조를 탐색하고 메서드나 필드에 접근하는 데 사용되지만, 이후에는 다음과 같은 최적화된 메커니즘이 작동합니다.

  1. 프록시 객체

    • AOP나 트랜잭션 관리에서는 프록시 패턴을 사용해 동작을 효율적으로 처리합니다.
    • 리플렉션은 초기 설정 단계에 주로 사용되고, 런타임에서는 생성된 프록시를 통해 메서드 호출을 최적화합니다.
  2. 빈 라이프사이클 관리

    • 객체를 생성하고 의존성을 주입한 뒤에는 싱글톤 컨테이너에서 관리하므로 리플렉션 없이도 빠르게 접근할 수 있습니다.
  3. 메서드 캐싱

    • 리플렉션은 상대적으로 느린 작업이므로, 스프링은 메서드 호출에 대한 정보를 캐싱해 성능을 향상시킵니다.

결론

  • 스프링의 동작: 리플렉션은 스프링의 핵심 기술 중 하나로, 클래스 탐색, 빈 등록, 메서드 매핑 등에 사용됩니다. 하지만 스프링은 리플렉션만으로 동작하지 않고 프록시 패턴, 캐싱 등 다양한 최적화 기법이 결합되어 동작합니다.
  • 싱글톤과 리플렉션: 컨트롤러와 서비스는 싱글톤으로 관리되며, 리플렉션은 초기 설정 단계에서 메타데이터를 읽거나 매핑을 설정할 때 주로 사용됩니다.
  • 리플렉션을 사용하는 이유는 유연성과 동적 처리를 가능하게 하기 위함입니다. 그러나 성능 저하를 방지하기 위해 필요한 부분에만 최소한으로 사용됩니다.

추가로 궁금한 점이 있다면 더 말씀해 주세요! 😊

'GPT Archiving' 카테고리의 다른 글

리플렉션 3  (0) 2025.01.11
리플렉션 2  (0) 2025.01.11
Java - CompletableFuture & addCallBack  (0) 2025.01.06
kafka - ProducerRecord  (0) 2025.01.06
kafka Sticky  (0) 2025.01.06