본문 바로가기
Back-end/Spring 개념

11. Dependency Injection 기본개념

by devraphy 2022. 2. 10.

0. 개요

- 이전 포스팅에서 Bean 자동 등록과 Spring이 Bean을 탐색하는 방법에 대해 알아보았다.

- Bean 자동 등록을 배웠으니, 이제 DI(의존성, 의존관계) 자동 주입에 대해서 알아보자.


1. DI에 대하여 

- DI(Dependency Injection)는 객체지향 프로그래밍에서 통용되는 개념이다.

- DI는 프로그램간의 결합도를 낮추기위해 사용되는 대표적인 방법으로, 여기에는 강한 결합과 느슨한 결합이 있다.

 

a) 강한 결합 

- 객체 내부에서 직접 다른 객체를 생성하여 강한 결합도를 형성하는 구조다.

- 앞서 SOLID에서 언급하였지만, 이와 같은 방식은 객체지향 프로그래밍의 OCP를 위반하는 방식이다.

- 그 이유는 Client가 직접 구현체를 명시하는 방식이기 때문이다. 

 

b) 느슨한 결합

- 외부에서 객체를 생성하여 이를 인터페이스를 통해 넘겨받는 형식의 구조로, 느슨한 결합도를 형성하는 구조다. 

- Client 측에서는 어떤 구현체가 들어오는지 알 수 없으므로, SOLID의 OCP가 지켜지는 방식이다. 

- 이 느슨한 결합을 구현하기 위해서 사용하는 방식이 DI 자동주입이다. 


2. DI 자동 주입

a) @Autowired 

- 클래스 내부에 의존관계 대상을 멤버 변수로 선언하여 생성자를 만드는데, 생성자에 @Autowired를 붙여 의존관계를 명시한다.

- 아래의 예시를 보자. 

@Component
public class TestServiceImpl implements TestService {
   
   private final TestRepository testRepository;
   
   @Autowired
   public TestServiceImpl(TestRepository testRepository) {
      this.testRepository = testRepository;
   }
}

 

- TestServiceImpl에서는 DB 저장소로 TestRepository(interface)의 구현체를 사용한다.

- 그러므로 위의 코드는 TestServiceImpl과 TestRepository가 의존관계를 형성함을 의미한다. 

 

- 하지만 TestRepository는 인터페이스다. 즉, Client는 어떤 구현체가 사용되는지 알 수 없다. (OCP)  

- 그럼 Spring은 어떻게 의존관계를 형성시킬까?

 

b) @Autowired의 동작원리 

- 위의 예시 코드에서 TestRepository(인터페이스)를 사용하여 의존관계를 명시하였다.  

- 이것이 가능한 이유는 Spring Container에서 모든 Bean(객체)을 관리하기 때문이다. 

 

- Spring은 @Autowired를 통해 의존관계를 인지한다. 

* @Autowired를 사용하기 위해서 관계를 형성하는 두 클래스 모두 Bean으로 등록되어야 한다.

 

- Spring은 @Autowired가 붙은 생성자의 코드를 통해 클래스 이름을 가져온다. 

- 이 클래스 이름을 기반으로 Spring Container에서 해당 클래스 타입을 갖는 구현체를 찾아 의존관계를 형성시킨다.

- 위의 예시에서는 TestServiceImpl의 객체와 TestRepository의 구현체를 Container에서 찾는 것이다.

 

- 이처럼 Spring은 외부에서 관계를 형성시켜 내부로 넣어주기 때문에, DI 특성이 발현된다.

- Client가 직접 관계를 명시하지 않고 Spring이 구현체를 찾아 관계를 형성시키므로, OCP / DIP / IoC 특성이 발현된다.

댓글