Spring 핵심 원리 TIL (6)

7879 단어 TILSpringSpring

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

💡 BeanFactory와 ApplicationContext

✏️ BeanFactory

  • 스프링 컨테이너의 최상위 인터페이스이다.
  • 스프링 빈을 관리하고 조회하는 역할을 담당한다.
  • getBean()을 제공한다.
  • 지금까지 우리가 사용했던 대부분의 기능은 BeanFactory가 제공하는 기능이다.

✏️ ApplicationContext

  • BeanFactory 기능을 모두 상속받아서 제공한다.
  • 빈을 관리하고 검색하는 기능을 BeanFactory가 제공해주는데 BeanFactory를 상속받은 ApplicationContext는 다른 인터페이스들도 상속받으며 수많은 부가기능을 필요로한다.

BeanFactory를 직접 사용할 일은 거의 없다.
편리한 부가기능을 더 많이 제공하는 ApplicationContext를 사용한다.
BeanFactory, ApplicationContext를 모두 스프링컨테이너라 한다! 😎

✏️ 스프링 빈 설정 메타 정보

  • 스프링은 java 클래스, XML 설정 방식 등 다양한 설정 형식을 지원합니다.
  • 이유는 바로 BeanDefinition이라는 추상화가 있기 때문이다.
  • BeanDefinition을 빈 설정 메타정보라고 한다.
  • 스프링 컨테이너는 이 메타 정보를 기반으로 스프링 빈을 생성한다.
    스프링 컨테이너는 자바 코드인지, XML인지 알 필요없이 BeanDefinition만 알면된다 🧐

정리하면 스프링이 다양한 형태의 설정 정보(xml, java..)를 BeanDefinition으로 추상화해서 사용하는 것이다.


💡 싱글톤 컨테이너

기존에 만들었던 스프링 없는 순수한 DI 컨테이너인 AppConfig는 요청을 할 때마다 객체를 새로 생성한다.

웹 애플리케이션은 보통 여러 고객이 동시에 요청을 한다.
이런 웹 애플리케이션 특성에서
기존의 코드는 요청마다 객체를 새로 생성하므로 메모리 낭비가 심하다!
해결 방안은 해당 객체를 딱 하나만 생성하고 그 객체를 공유하면 된다.
바로 이게 디자인 패턴 중 하나인 싱글톤 패턴이다.

✏️ 싱글톤 패턴

  • 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.
  • Private 생성자를 사용해서 외부에서 생성자 호출을 하지 못하게 막아야 한다 😎

test위치에서 예제를 작성해 보겠다.

package hello.core.singleton;
public class SingletonService {

      private static final SingletonService instance = new SingletonService();

      public static SingletonService getInstance() {
          return instance;
  }
  //생성자를 private으로 선언 
      private SingletonService() {
  }
      public void logic() { System.out.println("싱글톤 객체 로직 호출");
  } 
}
  1. static 영역으로 instance 객체를 선언한다.
  2. 이 객체는 오로지 public으로 선언한 메소드인 getInstance()로만 조회가 가능하다. static 영역으로 공유하고 있으므로 같은 인스턴스를 호출한다.
  3. 생성자를 private으로 선언해서 외부에서 생성자를 호출하는 것을 막는다
    -> 객체 인스턴스가 딱 하나로 공유된다.

싱글톤 패턴을 사용하는 테스트 코드

@Test
@DisplayName("싱글톤 패턴을 적용한 객체 사용")
public void singletonServiceTest() {
//private으로 생성자를 막아두었다. 컴파일 오류가 발생한다. 
//new SingletonService();

//1. 조회: 호출할 때 마다 같은 객체를 반환
SingletonService singletonService1 = SingletonService.getInstance();
//2. 조회: 호출할 때 마다 같은 객체를 반환
SingletonService singletonService2 = SingletonService.getInstance();

//참조값이 같은 것을 확인
System.out.println("singletonService1 = " + singletonService1); System.out.println("singletonService2 = " + singletonService2);
      // singletonService1 == singletonService2
      assertThat(singletonService1).isSameAs(singletonService2);
}

호출될 때마다 같은 인스턴스를 반환하는 것을 알 수 있다 😊

이를 통해 고객의 요청마다 객체를 생성하는 뻘짓은 막을 수 있게 되었다.
하지만 위와 같은 싱글톤 패턴은 다음과 같은 문제점들이 있다.

✏️ 싱글톤 패턴 문제점

  • 구현 코드 자체가 많다
  • DIP를 위반한다. 클라이언트가 구체 클래스에 의존하기 때문이다
  • DIP를 위반하므로 OCP 위반 가능성도 크다
  • 테스트가 어렵다
  • 내부 속성을 변경하거나 초기화하기 어렵다
  • private 생성자로 자식 클래스를 만들기 어렵다
  • 그러므로 유연성이 떨어진다

하지만 ..!! 우리의 스프링은 위와 같은 싱글톤 패턴의 문제점을 해결하며 싱글톤 패턴을 유연적이게 관리하는 컨테이너가 있다.
바로 우리가 지금까지 학습한 스프링 빈이 바로 싱글톤으로 관리되는 빈이다.

스프링이 활용하는 싱글톤 컨테이너에 대해선 다음 TIL에서 정리해 보겠다 😎

좋은 웹페이지 즐겨찾기