스프링 빈과 의존 관계 / Why DI ?
사용자의 요청에 따른 응답을 주기 위해 게시판 컨트롤러를 구현해 볼 건데 그러려면
게시판 컨트롤러가 게시판 서비스와 게시판 리포지토리를 사용할 수 있게 의존 관계를 준비해야 한다.
생성자에 @Autowired가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게 객체 의존 관계를 외부에서 넣어주는 것을 DI (Dependency Injection ), 의존성 주입이라 한다.
이대로 돌리면 오류가 발생하는데 스프링 컨테이너에 BoardService가 스프링 빈으로 등록되어 있지 않기 때문에 스프링이 BoardService의 존재 자체를 몰라서 발생하는 오류이다.
(그림)
이를 해결하기 위해 스프링 빈으로 등록하려면 어떻게 해야 할까?
2가지 방법으로 등록할 수 있다
- 컴포넌트 스캔과 자동 의존 관계 설정
- 자바 코드로 직접 스프링 빈으로 등록
컴포넌트 스캔 원리
스프링이 관리하는 파일들을 전부 돌며
@Component 애노테이션이 있으면 스프링 빈으로 자동 등록해준다.컨트롤러가 자동으로 스프링 빈으로 등록된 이유도 @Component 을 통한 컴포넌트 스캔 때문이다.
@Component를 포함하는 애노테이션들이 있다.
- @Controller
- @Service
- @Repository
위 애노테이션들이 있으면 스프링이 자동으로 컨테이너에 스프링 빈으로 등록한다.
자바 코드로 직접 스프링 빈 등록
직접 등록하기 위해서는 @Service, @Repository, @Autowired 애노테이션이 없어야 한다.
따로 SpringConfig 클래스를 만들어 @Configuration 애노테이션을 달아준다.
@Bean 애노테이션을 통해 스프링 빈으로 등록된 객체와
개발자가 의존 관계를 만들고자 할 때 스프링이 컨테이너에서 해당 객체를 가져와 의존 관계를 넣어주게 된다.
그냥 스프링이 컨테이너에 스프링 빈으로 등록된 객체를 가지고 있으면서 개발자가 필요할 때마다 생성자에 넣어줄 수 있다.
스프링(외부)이 의존 관계를 맺어준다(주입). => DI ( Dependency Injection )
Why DI ?
그러면 의존성 주입은 왜 하는 걸까?
의존성 주입이 없는 기존 게시판 서비스는 게시판 리포지토리 구현체를 직접 의존할 수 밖에 없다. 그러면 나중에 리포지토리가 확장/수정될 경우 클라이언트인 게시판 서비스의 코드도 변경해줘야 하므로 이는 OCP를 위반 한다.
하지만 스프링을 통해 DI를 해주면 서비스가 (추상)게시판 리포지토리를 의존하므로 확장/수정 시에 게시판 서비스는 수정없이 게시판 리포지토리의 구현체만 갈아 끼워주면 되므로 OCP를 만족하는 설계가 된다.