-
"한빛미디어 서평단 <나는리뷰어다> 활동을 위해서 책을 제공 받아 작성된 서평입니다."
DI의 개념
- DI는 'Dependency Injection'의 약자로, 프로그램을 설계할 때 사용되는 개념
- 사용되는 객체를 사용하는 객체 외부에서 생성하여 전달받는 사고 방식
1에서 사용되는 객체를 준비
2에서 사용하는 객체에 생성자의 인수 등을 사용해 전달
사용하는 쪽은 3에서 전달받은 객체의 메서드를 호출
- DI의 D는 의존(dependency)을 의미하고, I는 주입(injection)을 의미
DI와 인터페이스
- 일반적으로 DI를 설명할 때는 의존 객체가 인터페이스를 구현한다고 가정
- 하지만 의존 객체가 반드시 인터페이스를 구현할 필요는 없다.
- 예를 들어 아래와 같이 인터페이스를 사용하지 않는 클래스도 DI를 적용할 수 있다.
- TrainingRepository는 인터페이스가 아닌 구상 클래스
public class TrainingRepository { ... public List<Training> selectAll() { // 데이터 가져온다. ... return trainings; } } public class TrainingService { private TrainingRepository trainingRepository; public TraingingService(TrainingRepository trainingRepository) { this.trainingRepository = trainingRepository; } public List<Training> findAll() { retrun trainingRepository.selectAll(); } } //외부 소스 코드 TrainingRepository trainingRepository = new TrainingRepository(); TrainingService traingingService = new TrainingService(trainingRepository);
- TrainingService 객체와는 다른 곳에서 TrainingRepository 객체를 생성하고 전달받았으므로 DI를 적용했다고 할 수 있다.
- 인터페이스를 사용하지 않으면 테스트할 때 의존 객체를 Mock 객체로 전환할 수 없지 않을까? 하는 생각이 들 수도 있지만
Mock용 라이브러리를 사용하면 간단히 전환할 수 있다. - Mock용 라이브러리는 의존 객체의 구상클래스(TrainingRepository)의 서브 클래스를 자동으로 생성해 준다.
public class MockTrainingRepository extends TrainingRepository { .... @Override public List<Training> selectAll() { //적당한 테스트 데이터 ... return trainings; } } TrainingRepository trainingRepository = new MockTrainingRepository(); TrainingService trainingService = new TrainingService(trainingRepository);
- 자동 생성된 서브 클래스의 객체를 인젝션 해준다.
DI 컨테이너(IoC 컨테이너)
- DI를 적용하려면 객체를 외부에서 준비할 필요가 있다.
- 하지만 외부에서 직접 객체를 생성하려고 하면 문제가 생길 우려가 있고, 그 문제를 해결해 주는 것이 스프링 DI 컨테이너
외부에서 직접 객체를 준비할 때의 문제점
public static void main(String[] args) { TrainingRepository trainingRepository = new JdbcTrainingRepository(); TrainingService trainingService = new TrainingServiceImpl(trainingRepository); List<Training> trainings = trainingService.findAll(); .... }
- 애플리케이션의 규모가 커지면 외부에서 준비할 객체 수가 많아진다.
- 실제 개발 프로젝트에서는 Service, Repository 역할을 가진 객체가 수백 개에 달하는 경우가 많다.
- 이런 경우에 객체를 일일이 준비해서 다른 객체에 인젝션 하는 처리를 작성하는 것은 매우 번거로우며 유지 보수성도 좋지 않다.
DI 컨테이너를 사용한 솔루션
- DI 컨테이너는 외부에서 하는 처리를 담당하는 스프링의 기능
- 자바에서 컨테이너라는 용어가 나오면 객체를 담는 상자로 생각하면 된다.
- 컨테이너에 객체를 넣으면 컨테이너는 객체에 부가적인 기능을 제공
- DI 컨테이너는 다양한 기능을 제공하는데, 그중 대량의 객체 생성이나 인젝션을 간결한 코드로 처리해 주는 기능이 있다.
- 이 기능으로 외부에서 직접 생성할 때 발생하는 문제를 해결할 수 있다.
DI 컨테이너 관련 기본 용어
- Bean, Bean 정보, 설정 정보, 애플리케이션 컨텍스트
Bean
- DI 컨테이너가 관리하는 객체
- Java Beans의 Beans와는 직접적인 관계가 없다.
Bean 정의
- Bean을 정의하는 정보를 가리킨다.
- 예를 들어 관리할 객체의 구상 클래스는 무엇인지, 어느 의존 객체를 인젝션할 것인지와 같은 정보
설정 정보 (configuration)
- DI 컨테이너로 불러올 정보
- Bean 정의도 포함, Bean 정의 외에도 DI 컨테이너의 특정 기능을 활성화, 비활성화할 수 있는 정보가 포함
- 설정 정보를 작성해서 DI 컨테이너에서 불러오면 설정 정보에 따라 Bean 객체가 생성, 의존 객체가 인젝션 됨
어플리케이션 컨텍스트
- DI 컨테이너의 다른 이름
- DI 컨테이너에 해당하는 객체가 ApplicationContext 인터페이스를 구현
- DI 컨테이너를 종종 어플리케이션 컨텍스트라고 부르기도 한다.
Bean 정의
Bean 정의를 작성하는 대표적인 방법은 3가지
- 스테레오타입 어노테이션
- @Bean 메서드
- <bean> 태그
728x90'BOOK' 카테고리의 다른 글
부트캠프 QA편 (0) 2024.06.23 알고리즘 인사이드 with 파이썬 (0) 2024.05.25 게임 AI를 위한 탐색 알고리즘 입문 (0) 2024.03.23 HTTPS 통신의 암호화, RSA 그리고 양자 컴퓨터 (1) 2024.02.16 게임이론, 나폴레옹 그리고 중용 23장 (0) 2023.12.24