Java & Kotlin

[Spring] 빈 생명주기 콜백

Chunghyun Lee 2024. 7. 17. 15:57

Spring Framework를 사용하여 애플리케이션을 개발할 때, 빈의 생명주기를 관리하는 것은 매우 중요합니다. 빈이 생성되고 초기화되는 시점과, 애플리케이션이 종료되거나 빈이 소멸되는 시점을 제어하면 애플리케이션의 안정성을 높이고, 리소스를 효율적으로 관리할 수 있습니다. 이번 블로그 글에서는 빈 등록, 초기화, 소멸 메서드 지정 및 @PostConstruct, @PreDestroy 애노테이션에 대해 설명하겠습니다.

빈 생명주기 콜백이란?

Spring에서 빈 생명주기 콜백을 통해 빈이 생성되고 소멸되는 시점을 제어할 수 있습니다. 주요 방식으로는 다음과 같습니다:

  • 초기화 및 소멸 메서드 지정
  • @PostConstruct와 @PreDestroy 애노테이션 사용

초기화 및 소멸 메서드 지정

빈을 초기화하고 소멸시킬 때 호출할 메서드를 지정할 수 있습니다. 이는 XML 설정이나 자바 설정 클래스에서 initMethod와 destroyMethod 속성을 사용하여 지정할 수 있습니다.

@Bean(initMethod = "init", destroyMethod = "close")
public MyBean myBean() {
    return new MyBean();
}

@PostConstruct와 @PreDestroy 애노테이션

Java EE 5에서 도입된 이 두 애노테이션은 빈 초기화 및 소멸 메서드를 지정하는 데 사용됩니다. 스프링은 이 애노테이션을 지원하여 빈 라이프사이클 관리에 활용할 수 있습니다.

  • @PostConstruct: 빈이 생성된 후, 초기화 작업을 수행할 때 사용합니다.
  • @PreDestroy: 빈이 소멸되기 전에, 정리 작업을 수행할 때 사용합니다.

실제 예시

다음은 스프링 설정 클래스에서 빈 초기화 및 소멸 메서드를 지정하는 예제입니다.

PostConstruct 예시

@RequiredArgsConstructor
@Configuration
public class QuartzConfig {

    private final Scheduler scheduler;
    private final GlobalJobListener jobListener;

    /**
     * Quartz에 공통으로 적용할 설정들을 추가한다.
     * ex. Scheduler에 Job 수행 결과를 체크하기 위한 Listener를 등록한다.
     */
    @PostConstruct
    public void start() {
        try {
            scheduler.getListenerManager().addJobListener(jobListener);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

이 예제에서 QuartzConfig 클래스는 스프링의 @Configuration을 사용하여 설정 클래스로 정의되었습니다. @PostConstruct 애노테이션이 붙은 start 메서드는 빈이 생성된 후, Quartz 스케줄러에 글로벌 Job 리스너를 등록하는 초기화 작업을 수행합니다. 이를 통해 Quartz 스케줄러와 관련된 공통 설정을 초기화 시점에 적용할 수 있습니다.

초기화 및 소멸 메서드 지정 예시

@Slf4j
@Configuration
@EnableRedisRepositories(basePackages = "")
@RequiredArgsConstructor
public class RedisConfig {

    private final RedisProperties redisProperties;

    @Bean(name="redisson", destroyMethod="shutdown")
    public RedissonClient redisson() {
        Config redissonConfig = new Config();
        redissonConfig.setCodec(new JsonJacksonCodec());

        // Redis 설정
        if (redisProperties.getNodeType().equals("single")) {
            configureSingleServer(redissonConfig);
        } else if (redisProperties.getNodeType().equals("master-slave")) {
            configureMasterSlaveServer(redissonConfig);
        } else if (redisProperties.getNodeType().equals("sentinel")) {
            configureSentinelServer(redissonConfig);
        }

        return Redisson.create(redissonConfig);
    }
}

이 예제에서는 Redis 설정을 초기화하고 Redisson 클라이언트를 빈으로 등록합니다. @Bean 애노테이션의 destroyMethod 속성을 사용하여 Redisson 클라이언트를 소멸시킬 때 shutdown 메서드를 호출하도록 지정했습니다. 이는 애플리케이션이 종료될 때 Redisson 클라이언트의 자원을 적절히 해제하여 리소스 누수를 방지하는 데 유용합니다.

@PostConstruct와 @PreDestroy의 활용

  • @PostConstruct: 애플리케이션 시작 시, 필수적인 설정이나 리소스를 초기화할 때 유용합니다. 예를 들어, 데이터베이스 연결 설정, 파일 시스템 리소스 로드, 외부 API 초기화 등이 있습니다.
  • @PreDestroy: 애플리케이션 종료 시, 사용한 리소스를 해제하거나 정리 작업을 수행할 때 유용합니다. 예를 들어, 데이터베이스 연결 해제, 파일 시스템 리소스 정리, 외부 API 연결 종료 등이 있습니다.

이와 같이, Spring Framework의 빈 생명주기 콜백을 활용하면 애플리케이션의 초기화 및 종료 시 필요한 작업을 손쉽게 수행할 수 있습니다. 이를 통해 코드의 가독성을 높이고, 유지보수성을 향상시킬 수 있습니다.