Spring IoC 컨테이너

bp.chys·2020년 4월 26일
2

Spring Framework

목록 보기
2/15

IoC 컨테이너 (DI 컨테이너)

  • 컨테이너란 무언가를 담고, 특정 기능을 수행하는 프레임워크가 제공하는 논리적 컨텍스트라고 볼 수 있다.
  • 스프링에서는 객체 생성연결의 책임이 IoC 컨테이너로 인계된다.
  • 자바 클래스는 의존성을 정의하고 IoC 컨테이너는 객체를 만들고 의존성을 연결한다.
  • 제어의 역전(IoC)을 구현한 방법으로 DI 의존성 주입을 사용하는 것이기 때문에 스프링에서는 같은 의미로 볼 수 있다.

의존성 주입(Dependency Injection)

  • 우리가 개발하는 애플리케이션은 레이어로 구별이되고, 각 레이어들은 단방향으로 의존성을 가지고 있다.
    (Controller → Service, Service → Repository)
  • 의존성 주입을 사용하지 않을 경우, 개발자가 구현 객체를 직접 생성해서 의존성을 연결해주어야 한다.
public class UserServiceImpl implements UserService {
    
    private UserRepositoryImpl userRepository = new UserRepositoryImpl();

    ....
}
  • 그러나 이러한 방법은 단위테스트 작성을 어렵게 만들고, 두 레이어 구현체에 대한 결합도를 높여 유지보수 비용을 불러일으킨다.
  • 인터페이스를 활용하여 두 구현체 간의 결합도를 낮추고, 연결의 책임을 스프링 프레임워크에 인계할 수 있다.
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    ....
}
  • 하지만 스프링이 관리할 수 있는 객체는 스프링 빈으로 등록된 객체만 가능하다.

스프링 빈 (Spring Bean)

정의

  • 빈은 스프링 컨테이너를 통해 생성되고, 스프링에 의해 생명주기가 관리되는 객체를 의미한다.
  • 빈을 생성해야하는 클래스에서 @Component 어노테이션을 사용하면 런타임 시점에 IoC 컨테이너가 객체들을 스캔하며 빈으로 등록해준다.
  • 별도의 목적을 가진 레이어 별로 빈을 생성하고자할 경우에는 @Controller, @RestController, @Service, @Repository를 사용할 수 있다.
  • 이렇게 컨테이너에 의해 관리되는 빈을 컨테이너 관리 빈이라고 한다.

빈의 장점

  • 의존성 생성에 대한 책임이 없기 때문에 느슨한 결합도를 유지할 수 있고 이는 단위테스트의 효율을 높이고 이는 좋은 설계와 적은 결점으로 이어진다.
  • 컨테이너가 빈을 관리하므로 AOP를 사용해서 횡단관심을 분리하여 복잡한 코드를 단순화 시킬 수 있다. 이는 유지 관리가 쉬운 코드로 이어진다.

빈의 스코프

  • 스프링 빈은 여러 스코프로 만들 수 있다. 기본 스코프는 싱글톤 이다.
  • 싱글톤 : 스프링 IoC 컨테이너 인스턴스당 오직 하나의 빈 인스턴스만 생성되는 경우를 말한다. 싱글톤 빈은 무상태여야하고, 여러번 참조되어도 하나의 인스턴스만 생성되고 반환하기 때문에 시간적, 공간적 이점이 있다.
  • 프로토타입 : 스프링 컨테이너에서 빈이 요청될 때마다 새로운 인스턴스가 생성된다. 빈이 상태를 가지고 있는 경우 사용한다.
  • 리퀘스트 : 모든 HTTP 요청마다 빈 인스턴스가 생성되고, 스프링 웹 컨텍스트에서만 사용할 수 있다. 요청이 완료되면 즉시 폐기된다.
  • 애플리케이션 : 웹 애플리케이션당 하나의 빈 인스턴스로 생성되고 웹 컨텍스트에서만 사용할 수 있다.

빈의 의존성 주입(Wiring) 방식

  • setter 주입 방식 : 직접 setter를 구현해도 되지만, 의존 필드에 @Autowired을 지정하면 자동으로 setter 주입 방식을 사용한다. 그러나 순환참조의 위험이 있어 의존 관계가 명확하거나 테스트할 때 주로 사용된다.
  • 생성자 주입 방식 : 생성자를 정의하면 스프링이 알아서 의존관계를 찾아서 연결해준다. 직접 의존관계를 정의하기 때문에 순환참조의 위험이 덜하다. 또한 의존 객체를 불변객체로 지정한다면 생성자 주입 방식을 사용해야한다.

스프링 IoC 컨테이너 생성

  • IoC 컨테이너를 생성하는 방법은 두가지가 있다.
    • 빈 팩토리
    • 애플리케이션 컨텍스트 : 빈 팩토리의 상위 집합, 스프링에서 권장하는 방식
  • 애플리케이션 컨텍스트를 위한 구성은 간단하다. @Configuration 어노테이션을 사용하면 된다.
  • 따로 빈 설정 파일을 만들지 않았다면 @ComponentScan 어노테이션을 같이 사용함으로써 빈을 검색할 위치를 지정할 수 있다.
  • 애플리케이션 컨텍스트를 만드는 코드는 다음과 같다.
ApplicationContext context = new AnnotationConfigApplicationContext(SpringContext.class);
  • 의존성 연결이 가능한 빈이 여러 개일 때는 @Primary 또는 @Qualifier('빈 이름') 을 지정할 수 있다.
  • 테스트를 위한 컨테이너는 SpringTestFramework에 의해서 별도로 생성된다.
  • mocking을 사용하여 테스트 한다면, 스프링 컨텍스트를 시작할 필요가 없다.

결론

스프링은 의존성 주입(DI)를 통해 객체간의 결합도를 느슨하게 하고 단위테스트가 가능한 설계를 도와준다. 객체지향 설계원칙 중 OCP(개방 폐쇄 원칙), DIP(의존성 역전 원칙)은 프레임워크의 도움 없이 지키기 쉽지않다. 프레임워크가 객체를 생성해주고 의존성을 연결해주기 때문에 우리는 더욱 객체지향적 프로그래밍을 할 수 있다고 볼 수 있다.

의존성 주입은 스프링 핵심 기능 중 하나이자, 정체성을 잘 드러내는 기능이라고 생각한다.

profile
하루에 한걸음씩, 꾸준히

0개의 댓글