Spring 핵심 원리 TIL (10)

10028 단어 TILSpringSpring

[참고 강의] 김영한님의 스프링 핵심 원리 - 기본편

✏️ 자동, 수동의 올바른 실무 운영 기준

" 편리한 자동 기능을 기본으로 사용하자 "
그러면 어떤 경우에 컴포넌트 스캔과 자동 주입을 사용하고, 어떤 경우에 설정 정보를 통해서 수동으로 빈을 등록하고, 의존관계도 수동으로 주입해야 할까?

스프링이 나오고 시간이 갈수록 점점 자동을 선호하는 추세다. 스프링은 @Component 뿐만 아니라 @Controller, @Service, @Repository 처럼 계층에 맞추어 일반적인 애플리케이션 로직을 자동으로 스캔할 수 있도록 지원한다. 최근 스프링 부트는 컴포넌트 스캔을 기본으로 사용하고, 스프링 부트의 다양한 스프링 빈들도 조건이 맞으면 자동으로 등록하도록 설계했다.
자동 빈 등록을 사용해도 OCP, DIP를 지킬 수 있다.

수동 빈 등록이 사용하면 좋을 때는?

애플리케이션은 크게 업무 로직과 기술 지원 로직으로 나눌 수 있다.

  • 업무 로직 빈 : 웹을 지원하는 컨트롤러, 핵심 비즈니스 로직이 있는 서비스, 데이터 계층의 로직을 처리하는 레포지토리 등이 모두 업무 로직이다. 보통 비즈니스 요구사항을 개발할 때 추가되거나 변경된다.
  • 기술 지원 빈 : 기술적인 문제나 공통 관심사(AOP)를 처리할 때 주로 사용된다. 데이터베이스 연결이나, 공통 로그 처리 처럼 업무 로직을 지원하기 위한 하부 기술이나 공통 기술들이다.

업무 로직 빈은 자동 기능을 적극 사용하는 것이 좋다. 문제가 발생했을 때 어떤 곳에서 문제가 발생했는지 명확하게 파악하기 쉽다.
기술 지원 로직은 수가 매우 적고, 광범위하게 영향을 미친다. 또한 로직이 적용 잘 되고 있는지도 파악하기 어려운 경우가 많으므로 가급적 수동 빈 등록을 사용해서 명확하게 하는 것이 좋다.

💡 빈 생명주기 콜백

✏️ 빈 생명주기 콜백

네트워크 소켓처럼 애플리케이션 시작 시점에 필요한 연결을 미리 해두고, 애플리케이션 종료 시점에 연결을 모두 종료하는 작업을 진행하려면, 객체의 초기화와 종료 작업이 필요하다.

예제 코드

package hello.core.lifecycle;

public class NetworkClient {

     private String url;
    
     public NetworkClient() { 
        System.out.println("생성자 호출, url = " + url);
        connect();
        call("초기화 연결 메시지");
}
      public void setUrl(String url) {
          this.url = url;
}
    //서비스 시작시 호출
      public void connect() {
          System.out.println("connect: " + url);
      }
      public void call(String message) {
          System.out.println("call: " + url + " message = " + message);
}
      //서비스 종료시 호출
      public void disconnect() {
          System.out.println("close: " + url);
      }
}
 

스프링 환경설정과 실행

 public class BeanLifeCycleTest {
      @Test
      public void lifeCycleTest() {
          ConfigurableApplicationContext ac = new AnnotationConfigApplicationContext(LifeCycleConfig.class);
          NetworkClient client = ac.getBean(NetworkClient.class); ac.close(); //스프링 컨테이너를 종료, ConfigurableApplicationContext 필요
      }
      
      @Configuration
      static class LifeCycleConfig {
      
          @Bean
          public NetworkClient networkClient() {
          
              NetworkClient networkClient = new NetworkClient();
              networkClient.setUrl("http://hello-spring.dev");
              return networkClient;
       } 
    }
}

실행 결과

생성자 부분을 보면 url 정보 없이 connect가 호출되는 것을 확인할 수 있다.
너무 당연한 이야기지만 객체를 생성하는 단계에는 url이 없고, 객체를 생성한 다음에 외부에서 수정자 주입을 통해서 setUrl()이 호출되어야 url이 존재하게 된다.

스프링 빈은 간단하게 다음과 같은 라이프사이클을 가진다.
객체 생성 -> 의존관계 주입

스프링은 의존관계가 주입이 완료되면 스프링 빈에게 콜백 메서드를 통해서 초기화 시점을 알려주는 다양한 기능을 제공한다. 스프링은 스프링 컨테이너가 종료되기 직전에 소멸 콜백을 주기때문에 안전하게 종료 작업을 진행할 수 있다.

스프링 빈의 이벤트 라이프사이클
스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존관계 주입 -> 초기화 콜백 -> 사용 -> 소멸 콜백 -> 스프링 종료

  • 초기화 콜백: 빈이 생성되고, 빈의 의존관계 주입이 완료된 후 호출
  • 소멸전 콜백 : 빈이 소멸되기 직전에 호출

스프링은 3가지 방법으로 빈 생명주기 콜백을 지원한다.

  • 인터페이스
  • 설정 정보에 초기화 메서드, 종료 메서드 지정
  • @PostConstruct, @PreDestroy 애노테이션 지원

좋은 웹페이지 즐겨찾기