Juuunew 살아남기

[Spring] 스프링 컨테이너, 제어의 역전(IoC), 의존관계주입(DI) 본문

Framework/Spring

[Spring] 스프링 컨테이너, 제어의 역전(IoC), 의존관계주입(DI)

Juuunew 2022. 12. 23. 15:44

스프링 컨테이너

 

  • Spring Framework는 스프링 컨테이너를 통해 객체(Bean)들을 관리한다.
  • Spring Framework에서 Bean은 객체를 말한다.
  • ApplicationContext 인터페이스를 스프링 컨테이너라 한다.
  • BeanFactory 인터페이스를 상속받은 하위 인터페이스
  • BeanFactory가 제공하는 기능 외 자원 처리 추상화, 메시지 및 국제화와 이벤트 지원 등을 제공
  • XML 기반 방식과 어노테이션 기반의 자바 설정 클래스로 생성가능.

어노테이션 기반을 살펴보면

 

  • Controller - @Controller, @RestController
  • Service - @Service
  • Repository - @Repository

해당 어노테이션들의 내부를 타고 들어가다 보면, @Component라는 어노테이션을 찾아볼 수 있는데, 이 어노테이션은 Bean Configuration 파일에 따로 Bean을 등록하지 않아도 스프링 컨테이너에서 컴포넌트 스캔을 통해 @Component를 가진 모든 대상을 가져와서 Bean에 등록해 준다.

 

@Controller 어노테이션 내부

 


제어의 역전 - IoC

 

Inversion of Control의 약자로, 프로그램의 제어를 다른 대상이 맡는 것을 말한다.

 

객체의 생명주기 (객체의 생성, 초기화, 소멸, 메서드 호출 등)를 클라이언트 구현 객체가 직접 관리하던 것을

스프링에서는 IoC 컨테이너를 통해 프레임워크에서 자동적으로 생명주기를 관리해 준다. 프로그램의 제어권이

객체 자체에서 프레임워크로 역전된 것이다.

 

  • 라이브러리 : 어플리케이션에서 필요로 하는 시점에 라이브러리에 작성된 객체를 가져다 사용
  • 프레임워크 : 어플리케이션 코드에 작성된 객체들을 프레임워크가 필요한 시점에 사용

간편하게 정리하면 객체의 생명주기를 직접 관리할 수 있지만 Spring Framework에서는 Spring이 알아서 관리를 해준다.

 

🌟편리하다.🌟


의존관계주입 - DI

 

DI는 Dependency Injection의 줄임말로 Controller 클래스 -> Service 클래스, Service 클래스 -> Repository 인터페이스

처럼 한 클래스가 외부(다른 클래스 또는 인터페이스)에 의하여 결정하고 주입하는 것이다.

 

의존대상 B가 변하면, 그것이 A에 영향을 미친다.

- 토비의 스프링 3.1 (이일민 저)

 

DI는 객체를 직접 생성하는 대신 Bean에 등록된 의존 객체를 전달받는 방식을 사용한다.

의존성 주입 방법에는 크게 3가지가 있다.

  1. 생성자 주입
  2. 수정자 주입
  3. 필드 주입

 

1. 생성자 주입

public class MemberController {

    private final MemberService memberService;

    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

 

생성자 주입은 생성자의 호출 시점에 1회 호출되는 것이 보장된다.

(남은 두 가지 방법도 알아볼 테지만 Spring에서는 생성자 주입을 적극 권장하고 있다.)

 

Lombok 사용 시 위의 코드는 아래와 같이 변경된다.

@RequiredArgsConstructor
@RestController
public class MemberController {

    private final MemberService memberService;
    
}

@RequiredArgsConstructor는 초기화되지 않은 final 필드나, @NonNull이 붙은 필드에 대해 생성자를 생성해주는 롬복 어노테이션이다.

 

기존 MemberService 외에 다른 의존성을 주입할 때 생성자를 또 만들어서 관리해야 하는 번거로움이 사라진다.

 

2. 필드 주입

public class MemberController {

    @Autowired
    private MemberService memberService;

}

@Autowired 어노테이션 하나만으로 의존성을 추가할 수 있다.

하지만 필드 주입방식은 객체를 불변상태로 만들 수 없다는 단점이 존재하며, 순환 참조 문제가 발생할 수 있기 때문에 사용하지 않는 것이 좋다.

 

3. 수정자 주입

public class MemberController {

    private MemberService memberService;

    @Autowired
    public void setMemberService(MemberService memberService) {
        this.memberService = memberService;
    }

}

수정자 주입은 필드 값을 변경하는 Setter를 통해 의존 관계를 주입하는 방법이다.


💡생성자 주입을 권장하는 이유

 

1. 순환 참조를 방지할 수 있다.

 

필드 주입과 수정자 주입은 빈을 생성 후 어노테이션이 붙은 필드에 해당하는 빈을 찾아서 주입한다.

빈이 먼저 생성되고, 필드에 대한 주입을 수행하지만

 

생성자 주입은 생성자로 객체를 생성하는 시점에 필요한 빈을 주입한다.

빈을 먼저 생성하는 것이 아닌, 생성자의 인자에 사용되는 빈을 찾거나 Bean Factory에서 먼저 만든다.

 

2. Immutable (불변)

 

생성자 주입은 어플리케이션 실행 시 객체 불변성을 보장한다.

필드 주입과 수정자 주입은 final 필드로 선언이 불가능하지만, 생성자 주입은 final 필드로 선언이 가능하기에 불변성이 보장된다.

 

💡 공부 중 정리하는 내용이므로 부족한 부분이 있을 수 있습니다.

 

💡 참고자료

스프링 핵심 원리 - 기본편 (인프런 김영한)

 

스프링 핵심 원리 - 기본편 - 인프런 | 강의

스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...

www.inflearn.com

블로그1

 

[Spring] 스프링 컨테이너 - ApplicationContext, IoC, DI

이 글은 공부를 하면서 알게 된 내용들을 기록하는 글 입니다. 오류나 고쳐야 할 사항들이 있다면 지적 부탁드립니다! 1. IoC란? 2. DI란? 3. ApplicationContext : 스프링 컨테이너란? 4. 스프링 컨테이너

m42-orion.tistory.com

블로그2

 

[Spring DI/IoC] IoC? DI? 그게 뭔데?

스프링을 공부하다 보면 꼭 나오는 이야기가 있다. 스프링은 IoC 컨테이너로 빈을 관리한다. 스프링은 DI를 사용한다 .DI 방법에는 생성자 주입, setter 주입, 필드 주입 등이 있다.... 아니 근데 대체

velog.io

블로그3

 

[Spring] 다양한 의존성 주입 방법과 생성자 주입을 사용해야 하는 이유 - (2/2)

Spring 프레임워크의 핵심 기술 중 하나가 바로 DI(Dependency Injection, 의존성 주입)이다. Spring 프레임워크와 같은 DI 프레임워크를 이용하면 다양한 의존성 주입을 이용하는 방법이 있는데, 각각의 방

mangkyu.tistory.com