SPRING-2

Stark Ned·2024년 4월 2일

싱글톤 컨테이너

  • 대부분의 스프링 애플리케이션은 웹 애플리케이션이다. 이런 웹 애플리케이션은 보통 여러 고객이 동시에 요청을 한다.
  • 그런 웹 어플리케이션에 스프링이 없는 싱글톤 패턴이 적용되지 않은 어플리케이션은 요청 마다 객체 인스턴스를 생성 할 것이다.

  • 스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서, 객체 인스턴스를 싱글톤(1개만 생성)으로 관리한다.
  • 스프링 컨테이너 덕분에 고객의 요청이 올 때 마다 객체를 생성하는 것이 아니라, 이미 만들어진 객체를 공유해서 효율적으로 재사용할 수 있다.

  • 스프링 컨테이너는 싱글톤 레지스트리다.
  • 스프링 빈이 싱글톤이 되도록 보장해주어야 한다.
  • 그러한 기능을 스프링은 클래스의 바이트코드를 조작하는 라이브러리를 사용한다.
  • 이전에 AppConfig에 적용했던 @Configuration 어노테이션 이다.
  • @Bean만 사용해도 스프링 빈으로 등록되지만, 싱글톤을 보장하지 않는다.
  • 스프링 설정 정보는 항상 @Configuration을 사용하자

컴포넌트 스캔

지금까지 스프링 빈을 등록할 때는 자바 코드의 @Bean이나 XML의 등을 통해서 설정 정보에 직접 등록할 스프링 빈을 나열했다.
하지만 스프링은 설정 정보가 없어도 자동으로 스프링 빈을 등록하는 컴포넌트 스캔이라는 기능을 제공한다.
의존관계도 자동으로 주입하는 @Autowired라는 기능도 제공한다.

컴포넌트 스캔은 이름 그대로 @Component 애노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록한다.
@Configuration 이 컴포넌트 스캔의 대상이 된 이유도 Configuration소스코드를 열어보면 @Component 어노테이션이 붙어있기 때문이다.

@ComponentScan은 @Component가 붙은 모든 클래스를 스프링 빈으로 등록한다.

생성자에 @Autowired를 지정하면, 스프링 컨테이너가 자동으로 해당 스프링 빈을 찾아서 주입한다.

모든 자바 클래스를 다 컴포넌트 스캔하면 시간이 오래 걸린다. 그래서 꼭 필요한 위치부터 탐색하도록 시작 위치를 지정할 수 있다.

  • 권장하는 방법은 패키지 위치를 지정하지 않고, 설정 정보 클래스의 위치를 프로젝트 최상단에 두는 것 이다.
  • @ComponentScan이 들어있는 스프링 부트의 대표 시작 정보SpringBootApplication을 프로젝트 시작 루트 위치에 두는 것이 관례이다.

느낀점

이번 학습을 통해 스프링이 제공하는 편리한 기능들과 주의할점을 알 수 있었다.
싱글톤의 편리함도 있지만 주의점도 알 수 있었다. 예를들면 싱글톤 패턴이든, 스프링 같은 싱글톤 컨테이너를 사용하든, 객체 인스턴스를 하나만 생성해서 공유하는 싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 상태를 무상태(stateless)로 설계해야 한다는것.
스프링 설정 정보의 필수인 @Configuration어노테이션의 내부는 CGLIB라는 바이트코드 조작 라이브러리를 사용해서 생성된다는 것.
컴포넌트 스캔은 @Component뿐만 아니라 @Controller, @Service, @Repository등 도 포함이 된다는것.
컴포넌트 스캔 대상을 지정할 수있는 includeFilters, excludeFilters 필터기능도 있다는것.
빈 등록시 중복상황의 충돌 경우도 알 수 있었다.


의존관계 자동 주입

의존관계 주입은 크게 4가지 방법이 있다.

생성자 주입

  • 생성자를 통해서 의존 관계를 주입 받는 방법이다.
  • 생성자 호출시점에 딱 1번만 호출되는 것이 보장된다.
  • 불변, 필수 의존관계에 사용
  • 생성자가 딱 1개만 있으면 @Autowired를 생략해도 자동 주입 된다

수정자 주입(setter 주입)

  • setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존관계를 주입하는 방법이다
  • 선택, 변경 가능성이 있는 의존관계에 사용
  • 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법이다.

필드 주입

  • 코드가 간결해서 많은 개발자들을 유혹하지만 외부에서 변경이 불가능해서 테스트 하기 힘들다는 치명적인 단점이 있다

일반 메서드 주입

  • 일반 메서드를 통해서 주입 받을 수 있다.
  • 일반적으로 잘 사용하지 않는다.

과거에는 수정자 주입과 필드 주입을 많이 사용했지만, 최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다.

롬복

  • 롬복 라이브러리가 제공하는 @RequiredArgsConstructor 기능을 사용하면 final이 붙은 필드를 모아서 생성자를 자동으로 만들어준다.
  • 최근에는 생성자를 딱 1개 두고, @Autowired를 생략하는 방법을 주로 사용한다.
  • 여기에 Lombok 라이브러리의 @RequiredArgsConstructor함께 사용하면 기능은 다 제공하면서, 코드는 깔끔하게 사용할 수 있다.

느낀점

주입할 스프링 빈이 없어도 동작해야 할 때(예: 테스트)가 있다면 옵션 처리로 해결을 할 수 있다는것.
생성자 주입은 객체를 생성할 때 딱 1번만 호출되어 불변하게 설계할 수 있고, 오직 생성자 주입 방식만 final 키워드를 사용할 수 있어 생성자에서 혹시라도 값이 설정되지 않는 오류를 컴파일 시점에 막아 줄수 있고,프레임워크에 의존하지 않고, 순수한 자바 언어의 특징을 잘 살리는 방법이기도 하고 등등의 이유로 의존관계는 생성자 주입을 권장 사용하는게 맞는것 같다는것.
똑같은 타입의 스프링 빈이 2개 있을 때 @Autowired 필드 명, @Qualifier, @Primary, 애노테이션 직접 만들기로 해결 가능하다는것.
의도적으로 정말 해당 타입의 스프링 빈이 다 필요한 경우도 있다면 전략 패턴을 사용하여 구현할 수 있다는것.
수동의 올바른 실무 운영 기준상 직접 등록하는 기술 지원 객체는 기술 지원 빈 별도의 설정 정보로 수동 등록 하는게 좋고, 비즈니스 로직은 수동 등록을 고민해보는게 좋다는 것.

profile
Escape

0개의 댓글