BackEnd/Spring

[Spring] @Configuration 이란?

샤아이인 2022. 9. 12.

[Spring] @Configuration 이란?

 

이번 글에서는 @Configuration을 사용하는 이점에 대하여 정리해볼까 한다.

 

1. @Configuration 이란?

Spring에서 Bean을 수동으로 등록하기 위해서는, 설정 class위에 @Configuration을 추가하고, @Bean을 사용해 수동으로 빈을 등록할 수 있다.

이때 메서드 이름으로 빈의 이름이 결정된다. 그러므로 중복된 빈 이름이 존재하지 않도록 주의해야 한다.

 

예를 들면 다음과 같을 것이다.

@Configuration
public class SomeConfig {

    @Bean
    public ShineResource shine() {
        return new ShineResource();
    }

}

일반적으로 위와 같이 의존성 주입을 위해서 @Configuration을 사용하게 된다.

 

@Configuration 안에서 @Bean이 빈으로 등록되는 과정은 간단하다. 

스프링 컨테이너는 @Configuration이 붙어있는 클래스를 자동으로 빈으로 등록하게 된다.

[Spring] @Configuration 이란? - 				
    
    	1. @Configuration 이란?

@Configuration 내부를 보면 사실 @Component가 추가되어있다. 따라서 해당 Class 또한 Bean으로 등록된다.

이후 해당 클래스의 본문을 파싱 해서 @Bean이 붙어있는 메서드를 찾아서 빈을 생성해준다.

 

그럼 @Configuration은 Bean을 단순히 수동 등록하기 위한 애노테이션 일까?

 

당연히 단순히 Bean을 등록하기 위한 애노테이션이 아니다!

 

그럼 어떠한 이유로 사용하는 것 일까? 다음 단락에서 알아보자.

 

2. @Configuration의 역할

- Bean을 등록할 때 싱글톤(singleton)이 되도록 보장해준다.

- 스프링 컨테이너에서 Bean을 관리할 수 있게 됨.

 

우선 다음과 같은 class가 있다고 해보자.

public class MyBean {

    public MyBean() {
        System.out.println("MyBean instance created");
    }
}
public class MyBeanConsumer {

    public MyBeanConsumer(MyBean myBean) {
        System.out.println("MyBeanConsumer created");
        System.out.println("myBean hashcode = "+myBean.hashCode());
    }
}

 

또한 우리가 사용할 설정 파일은 다음과 같다.

@Configuration
public class AppConfig {

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
	
    @Bean
    public MyBeanConsumer myBeanConsumer() {
        return new MyBeanConsumer(myBean());
    }
}

 

위 파일들을 실행하면 "MyBean instance created"가 총 몇 번 호출될까?

우리의 Bean들은 싱글톤으로 등록되기 때문에, 다음과 같이 단 1번만 출력되는 것을 확인할 수 있다.

MyBean instance created
MyBeanConsumer created
myBean hashcode = 1647766367

또한 Consumer도 싱글톤 빈 이기 때문에 한 번만 등록된다.

 

@Configuration 애노테이션을 제거하면 다음과 같이 출력된다.

MyBean instance created
MyBean instance created
MyBeanConsumer created
myBean hashcode = 1647766367

myBean() 메서드가 호출될 때마다 new로 새로운 MyBean을 생성하기 때문에 "MyBean instance created"이 2번 호출되게 된다.

 

즉, @Bean만 사용해도 스프링 빈으로 등록은 되지만 싱글톤이 유지되지는 않는다.


다음 테스트 코드를 살펴보자.

@Test
void configurationDeep() {
    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    AppConfig bean = ac.getBean(AppConfig.class);
    System.out.println("bean = " + bean.getClass());
}

설정 파일로 넘긴 AppConfig.class 안에 있는 것들이 빈으로 등록된다. 또한 AppConfig자체도 빈으로 등록이 된다.

위의 테스트 결과를 출력하면 어떻게 나올까? 예상되는 결과는 class hello.core.AppConfig이다.이다.

[Spring] @Configuration 이란? - 				
    
    	2. @Configuration의 역할

위의 테스트 결과를 보면 예상했던 결과와는 달리 뒤에 클래스 명에 xxxCGLIB가 붙으면서 상당히 복잡해진 것을 볼 수 있다.

만든 클래스가 아니라 스프링이 CGLIB라는 바이트코드 조작 라이브러리를 사용해서 AppConfig 클래스를 상속받은 임의의 Proxy 클래스를 만들고, 그 다른 클래스를 스프링 빈으로 등록한 것이다!

 

그림으로 확인해 보자!

[Spring] @Configuration 이란? - 				
    
    	2. @Configuration의 역할
출처 - 인프런 김영한 스프링

원래의 AppConfig를 상속한 proxy AppConfig가 빈으로 등록되며, 싱글톤이 되도록 보장해 준다!

 

AppConfig@CGLIB 예상 코드는 다음과 같다.

@Bean
public MyBean myBean() {
    if (myBean이 이미 스프링 컨테이너에 등록되어 있으면?) { 
        return 스프링 컨테이너에서 찾아서 반환;
    } else { //스프링 컨테이너에 없으면 기존 로직을 호출해서 myBean을 생성하고 스프링 컨테이너에 등록 
        return 생성 후 반환
    } 
}

 

@Bean이 붙은 메서드마다 이미 스프링 빈이 존재하면 존재하는 빈을 반환하고, 스프링 빈이 없으면 생성해서 스프링 빈으로 등록하고 반환하는 코드가 동적으로 만들어진다. 덕분에 싱글톤이 보장되는 것이다.

 

 

3. 출처

https://www.digitalocean.com/community/tutorials/spring-configuration-annotation

 

Spring @Configuration Annotation | DigitalOcean

 ...

www.digitalocean.com

 

https://castleone.tistory.com/2

 

[Spring] @Configuration 개념과 장점

더보기 1. @Configuration 이란? : @Configuration이라고 하면 설정파일을 만들기 위한 애노테이션 or Bean을 등록하기 위한 애노테이션이다. 더보기 2. @Configuration을 사용하면 뭐가 좋은데? : @Configurat.....

castleone.tistory.com

 

댓글