개발기록

@Configuration은 어떻게 싱글톤 빈을 보장하는가? 본문

Spring

@Configuration은 어떻게 싱글톤 빈을 보장하는가?

Danuvibe 2024. 9. 10. 16:30

Spring Framework에서 @Configuration 어노테이션은 빈 설정 클래스임을 나타내는 중요한 어노테이션입니다. 이 어노테이션은 단순히 빈을 정의하는 것을 넘어서, 빈의 싱글톤 특성을 보장하는 특별한 메커니즘을 제공합니다. 오늘은 @Configuration이 어떻게 싱글톤 빈을 보장하는지 자세히 알아보겠습니다.

1. @Configuration의 기본 역할

@Configuration 어노테이션이 클래스에 붙으면, 해당 클래스는 빈 정의의 소스로 인식됩니다. 이 클래스 내부에 @Bean 어노테이션이 붙은 메서드들은 Spring 컨테이너에 의해 관리되는 빈을 생성합니다.

@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

2. CGLIB 기반 프록시 생성

Spring은 @Configuration 클래스에 대해 CGLIB(Code Generation Library)를 사용하여 프록시를 생성합니다. 이 프록시는 원본 @Configuration 클래스를 상속받아 만들어집니다.

public class AppConfig$$EnhancerBySpringCGLIB extends AppConfig {
    // CGLIB에 의해 생성된 메서드들
}

3. 메서드 인터셉션

프록시는 @Bean 메서드 호출을 인터셉트합니다. 이를 통해 같은 @Bean 메서드가 여러 번 호출되더라도 항상 같은 인스턴스를 반환하도록 보장합니다.

4. 캐싱 메커니즘

프록시는 @Bean 메서드가 처음 호출될 때 생성된 빈 인스턴스를 캐시합니다. 이후 같은 메서드가 호출되면 캐시된 인스턴스를 반환합니다.

public class AppConfig$$EnhancerBySpringCGLIB extends AppConfig {
    private MyService myServiceInstance;

    @Override
    public MyService myService() {
        if (myServiceInstance == null) {
            myServiceInstance = super.myService();
        }
        return myServiceInstance;
    }
}

5. 의존성 주입 시나리오

다른 @Bean 메서드 내에서 @Bean 메서드를 호출하는 경우에도, 프록시는 이를 인터셉트하여 이미 생성된 빈을 반환합니다. 이로써 의존성 주입 시에도 싱글톤이 보장됩니다.

@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }

    @Bean
    public MyController myController() {
        return new MyController(myService());  // 여기서도 같은 MyService 인스턴스가 사용됨
    }
}

6. @Configuration vs @Component

@Component로 등록된 클래스 자체는 기본적으로 싱글톤 스코프의 빈으로 등록됩니다. 즉, @Component가 붙은 클래스의 인스턴스는 애플리케이션 내에서 하나만 생성되어 공유됩니다.

그러나 @Component 클래스 내부에 @Bean 메서드가 있을 경우, 이 메서드들은 @Configuration에서와 같은 특별한 처리를 받지 않습니다. 따라서 @Bean 메서드가 여러 번 호출될 때 새로운 인스턴스가 생성될 수 있습니다.

예를 들어:

@Component
public class MyComponent {
    @Bean
    public MyBean myBean() {
        return new MyBean();  // 이 메서드가 호출될 때마다 새 인스턴스 생성 가능
    }
}

반면 @Configuration 클래스의 @Bean 메서드는 항상 같은 인스턴스를 반환하도록 보장됩니다:

@Configuration
public class MyConfiguration {
    @Bean
    public MyBean myBean() {
        return new MyBean();  // 항상 같은 인스턴스 반환
    }
}

주요 차이점:

  1. @Component와 @Configuration 클래스 자체는 모두 싱글톤 빈으로 등록됩니다.
  2. @Configuration 클래스의 @Bean 메서드는 항상 같은 인스턴스를 반환합니다.
  3. @Component 클래스의 @Bean 메서드는 메서드 호출마다 새 인스턴스를 생성할 수 있습니다.

결론

Spring의 @Configuration은 CGLIB 기반 프록시, 메서드 인터셉션, 그리고 캐싱 메커니즘을 통해 빈의 싱글톤 특성을 보장합니다. 이는 애플리케이션 전반에 걸쳐 일관된 상태와 동작을 유지하는 데 중요한 역할을 합니다. 개발자는 이러한 메커니즘을 이해하고 활용함으로써 더욱 안정적이고 예측 가능한 Spring 애플리케이션을 구축할 수 있습니다.

Comments