Kim-Baek 개발자 이야기

[책] 스프링 철저 입문 - DI 본문

개발/Spring

[책] 스프링 철저 입문 - DI

김백개발자 2020. 8. 24. 17:06

자바 앱을 개발 할 때, 요즘에는 여러 인터페이스를 결합해서 쓰는 경우가 많다.

결합해서 쓸 때, 구체 클래스를 미리 생성해서 하려면, 이 클래스는 미리 개발이 되어야 있어야 하고, 교체가 힘들다.

이를 위해서, 생성자를 통해서, 받기도 하는데 , 이것도 마찬가지로 더미로 쓰고 있다면 바꿔줘야 하는 문제가 있다. 컴포넌트를 외부에서 생성한 후, 내부에서 사용가능하게 해주는 것을 의존성 주입이라 한다.

의존성 주입을 자동으로 하는 기반을 DI 컨테이너라고 한다.

스프링에서 가장 중요한 것이 이 DI 컨테이너의 기능이다. 스프링에 미리 인터페이스와 구현 클래스를 알려주고, 의존 관계를 정의하면 생성될 때, 구현 클래스가 자동으로 생성되어 주입 된다.

이것의 장점은, 의존성 해결도 있지만, 스코프 관리 ( 싱글톤으로 만들지, 매번 새로 만드는 프로토타입 객체를 쓸지 ) 도 해준다는 것이다. AOP 기능도 컨테이너가 해준다.

IoC 는 인스턴스를 제어하는 주도권이 역전된다는 의미로 주로 사용되고, 컴포넌트를 구성하는 인스턴스의 생성과 의존 관계의 처리를 해당 소스코드가 아닌 컨테이너에서 대신 해주기 때문에 역전되었다고 본다.

DI 컨테이너에서 인스턴스를 관리하는 방식의 장점

  1. 인스턴스의 스코프를 제어한다
  2. 인스턴스의 생명 주기를 제어한다
  3. AOP 방식으로 공통 기능을 집어넣을 수 있다.
  4. 의존하는 컴포턴트 간의 결합도를 낮춰서 단위 테스트하기 쉽게 한다

빈 설정 방법은 대표으로 세 가지가 존재한다.

  1. 자바 기반 설정 방식
    • @Configuration 을 클래스에, 메서드에 @Bean을 사용한다. 메소드 이름이 빈 이름이 된다
  2. xml 기반 설정 방식
  3. 애너테이션 기반 설정 방식 ( 보통 많이 사용해본 기법이다 )
    • DI 컨테이너에 관리할 빈을 빈 설정 파일에 정의하는 대신 빈을 정의하는 애너테이션을 빈의 클래스에 부여하는 방식
    • 애너테이션이 붙은 클래스를 탐색해서 자동으로 등록하는데 이 탐색을 컴포넌트 스캔이라 한다
    • 의존성 주입도 명시적으로 설정하는 것이 아니라, DI 가 자동으로 필요로 하는 의존 컴포넌트를 주입하게 된다. 이러한 과정을 오토와이어링이라 한다
    • 컨테이너에 등록되는 빈의 이름은 클래스명의 첫 글자를 소문자로 바꾼 이름고 같음

의존성 주입도 세 가지 방법이 있다

  1. 설정자 기반 주입 방식
  2. 생성자 기반 주입 방식
    • 이걸 사용하면 필드를 final로 선업해서 생성 후에 변경되지 않게 많들 수 있다. 다른 방식에서는 할 수 없는 방법
  3. 필드 기반 의존성 주입 방식 ( 가장 많이 사용해봄 )
    • 필드에 @Autowired 애너테이션을 달아 사용
    • 소스코드가 간결해보이는 장점

오토와이어링은 두 가지 방식이 있다. 

  1. 타입을 사용한 방식
    • @Autowired 애너테이션이 이 방식이고, 해당 타입의 빈이 없으면 에러가 발생. 이러한 필수조건은 required 속성으로 완화가 가능하다
    • 같은 타입이 두 개가 있을 때는 이름으로 구분이 가능하다. @Qualifier 애너테이션으로 이름을 명시하면 된다.
  2. 이름을 사용한 방식
    • @Resource를 쓰면 빈의 이름이 필드명과 프로퍼티 명과 일치하는 것을 찾아서 이름으로 넣는다. 만약 찾아서 없으면 타입으로 매핑을 하게 된다.

빈 스코프는 빈의 생존기간이다.

개발자가 직접 빈 스코프를 다루지 않는 것이 DI 컨테이너의 큰 장점이다. 만약 개발자가 직접 관리해야 한다면, 싱글톤이라던가, 인스턴스 파괴 등을 직접 구현해야 되는 불편함이 있다. 이러한 내용은 중요하지만 구현하고자 하는 비즈니스 관점에서는 본질과는 동떨어진다.

기본으로 사용되는 스코프는 싱글톤이다. 변경하고 싶은 경우에는 @Scope 애너테이션을 쓰자

생존기간이 다른 빈에 주입이 될 때는 주입되는 빈의 생존기간에 따른다. 싱글톤인 빈에 프로토타입의 빈을 넣으면 결국 싱글톤으로 쓰이게 되는 것이다. 

이걸 방지하기 위해서, ApplicationContext에서 직접 빈을 받아오면 된다. 이를 위해서 @Lookup 에너테이션을 쓰면 된다, 그러면 해당 컨테이너에서 해당 빈을 직접 찾아오게 된다.

빈의 생명 주기

  1. 빈 초기화 단계
    • 빈 설정 정보 일기 및 보완 : xml이나 컴포넌트 스캔으로 정보만 읽어온다. BFPP를 통해 빈의 정보를 보완
    • 빈 생성 및 의존 관계 해결 : 생성자 기반, 필드 기반, 세터 기반 순서로 의존성 주입이 시작된다
    • 빈 생성 후 초기화 작업 : 빈생성 후, 전처리, 초기화, 후처리로 구분된다. 초기화 방식은 다양하게 정의 가능하다. @PostConstruct 애너테이션 사용한다. 빈이 생성된 후에 이뤄지는 초기화는 빈을 생성할 때 하는 초기화와는 큰 차이가 있는데, 의존성 주입이 끝난 필드 값을 초기화에 활용할 수 있다는 것 ( 반환이 void이고 메소드의 매개변수는 없어야 함 )
  2. 빈 사용 단계
  3. 빈 종료 단계
    • @PreDestroy

프로파일별 설정 구성

설정 파일을 특정 환경이나 목적에 맞게 선택적으로 사용할 수 있도록 그룹화 할 수 있다. 이 기능을 프로파일이라 한다. 

자바 기반 설정 방식과 애너테이션 기반 설정 방식은 프로파일을 지정할 때 @Profile 애너테이션을 쓴다. xml 기반에서는 <beans>를 통해 설정이 가능하다. 프로파일의 선택은 자바 앱을 실행할 때, 명령행 옵션으로, spring.profiles.active 라는 프로퍼티 값과 사용할 프로파일 이름을 지정하면 된다.

반응형
Comments