본문 바로가기
코딩log/Spring Framework

[Spring Framework]Spring Bean의 초기화와 종료

by 벨크 2023. 4. 20.
반응형

  어떤 인스턴스를 사용하다 보면 인스턴스 생성 시 생성자에서 처리해야 할 일들이 있고, 객체의 소멸(인스턴스 해제) 전에 처리해야 할 작업들이 있습니다. 예를 들면 네트워크 소켓이나 DB에 연결하는 객체들이 그렇습니다. 생성과 동시에 연결을 하고, 인스턴스가 해제되기 전에 연결을 끊어주는 작업을 하게 되죠.

 

  그렇다면 일반적인 객체가 아닌 Spring Bean을 사용할 경우에는 이런 상황의 처리를 어떻게 해야 할까요? 한 번 알아보겠습니다.


Spring Bean의 초기화와 종료

 

  일반적인 객체가 아닌 Spring Bean으로 객체를 관리할 때는 의존관계 주입을 할 때 생성자가 한 번 호출이 됩니다. 이때 인스턴스 생성 시 필요한 값이 없어서, 해당 생성자가 의도대로 동작하지 않을 수 있습니다. 그래서 Spring에서는 Bean을 초기화하고 종료하는 기능을 제공하여 의존관계 주입이 끝나면 Callback을 해주고, Bean을 소멸시키기 전에도 Callback을 해줍니다.

 

  그 방법을 소개하기 전에 객체의 초기화에 대한 이야기를 조금 하고자 합니다. 객체의 초기화는 객체의 생성과는 별개로 분리가 되어야 합니다. 초기화는 객체를 사용하는데 필요한 데이터가 모두 Setting 된 때를 말합니다. 필연적으로 객체를 생성시킨 후 Setter로 데이터를 세팅하는 경우가 발생할 수 있습니다. 이런 경우에는 객체의 생성과 초기화를 분명하게 분리시켜야 합니다. 예를 들자면 네트워크에 연결하는 객체의 경우에는 객체 생성되고, Setter로 URL을 입력받은 후 본격적인 로직이 실행됩니다.

 

Interface를 활용한 Bean의 초기화와 종료

 

  첫 번째 방법은 Spring Bean Factory에서 제공하는 InitializingBean과 DisposableBean이라는 클래스를 상속받아서 구현하는 것입니다.

 

public class Example implements InitializingBean, DisposableBean {

    @Override
    public void afterPropertiesSet() {
        //초기화 수행
    }
    
    @Override
    public void destroy() {
        //Bean 소멸 전 종료처리 진행
    }
}

  afterPropertiesSet()과 destroy()를 Override 하여 초기화와 종료처리를 구현합니다. 그러면 Spring에서 의존관계가 주입이 되고 나면 afterPropertiesSet 함수를 호출하여 초기화를 진행하고, 빈이 소멸되기 전에 destroy함수를 호출하여 종료처리를 진행합니다.

 

  Interface를 이용한 위 방법은 초기화와 종료처리 메서드명을 변경하지 못한다는 단점이 있습니다. 종료처리 메서드야 그렇다 치더라도, 초기화 메서드는 이름이 너무 길죠..? 그리고 메서드의 이름이 고정적으로 정해져 있기 때문에 외부 라이브러리를 이용하기 어렵다는 단점도 존재합니다.

 

Bean 정보에 초기화와 종료처리에 대한 정보를 등록

 

  Interface를 이용한 방법에 위와 같은 단점이 존재하기 때문에 Spring에서는 또 다른 방법을 제공합니다. 바로 Bean 정보에 초기화와 종료처리에 대한 함수명을 등록하는 것입니다. Bean에 등록된 정보를 읽어 의존관계 주입 후 해당 초기화 함수를 호출하고, Bean 소멸 전에 종료처리 함수를 호출해 줍니다.

@Bean(initMethod = "init", destroyMethod = "destroy")
public Example example {
    return new Example
}

  Bean 정보에 초기화, 종료처리 함수를 등록하여 사용하는 방법은 초기화, 종료처리 메서드의 이름을 자유롭게 사용할 수 있다는 장점이 있습니다. 위의 의존관계 주입이 끝나면, Spring은 해당 클래스의 init 메서드를 실행합니다. 마찬가지로 Bean이 소멸하기 전에 해당 클래스의 destroy 메서드를 실행합니다.

 

  Bean 정보에 초기화, 종료 메서드를 등록하여 사용하는 경우에는 외부 라이브러리 사용이 용이하다는 점입니다. Bean을 등록할 때, 외부 라이브러리의 초기화, 종료 함수명을 등록하면 되기 때문입니다.

 

  한 가지 참고 사항으로, destroyMethod에는 추론 기능이 제공됩니다. destroyMethod에 아무런 값을 입력하지 않으면, Spring이 Bean이 소멸하기 전에 해당 클래스에 close나 shutdown이라는 이름의 함수가 있는지 확인하고, 있으면 해당 함수를 실행시켜 주는 아주 편리한 기능입니다.

 

@PostConstruct, @PreDestroy Annotation을 이용한 초기화와 종료

 

  지금 소개할 Annotation을 이용한 초기화와 종료처리 방법이 가장 많이 사용하는 방법입니다. 이유는 코드 구현이 가장 간결하고 쉽기 때문입니다. 그냥 초기화 함수의 선언 위에 @PostConstruct Annotation을 붙이고, 종료처리 함수 선언 위에 @PreDestroy Annotation을 붙이면 끝입니다. 이 방법은 별도의 정보를 등록할 필요도 없고, JSR-250에서 발표한 JAVA 표준이기 때문에 Spring 코드가 아니라도 사용할 수 있는 장점을 가진 방법입니다.

public class Example {

    @PostConstruct
    public void init() {
      //초기화 코드 진행
    }
    
    @PreDestroy
    public void destroy() {
      //종료처리 코드 진행
    }
}

  이 방법은 아주 간편하지만, 한 가지 단점이 있습니다. 바로 외부 라이브러리를 사용할 때입니다. 클래스의 메서드에 Annotation을 붙이는 방식이라 라이브러리에서 제공하는 클래스에 해당 Annotation이 붙어있지 않으면 사용할 수 없기 때문입니다.

 

  그래서 일반적인 클래스, 프로젝트에서 자체로 관리하는 클래스에서는 Annotation을 이용한 초기화, 종료처리를 사용하고, 외부 라이브러리를 이용할 때는 Bean 정보에 외부 라이브러리에서 제공해 주는 초기화, 종료 함수를 등록하여 사용하면 됩니다.

 


  Bean의 Lifecycle 시작과 끝이라고 할 수 있는 초기화와 종료에 대해 공부해 봤습니다. 아직 초기화 함수와 종료처리 함수에 대한 사용방안이 구체적으로 머릿속에 떠오르진 않습니다. 중요한 것은 객체의 생성과 초기화에 대한 개념을 분명히 알고 분리해서 구현하는 데 있습니다. 읽어주셔서 감사합니다!

 

이전 글: Autowired와 자동 의존관계 주입의 옵션들

 

[Spring Framework]Autowired와 자동 의존관계 주입의 옵션들

@ComponentScan과 @Component로 원하는 객체들을 자동으로 스프링 Bean으로 등록할 수 있습니다. 그럼 자동으로 등록된 Bean에 자동으로 의존관계를 주입하는 것에 대해 조금 더 디테일하게 알아보도록

belklog.tistory.com

 

반응형

댓글