스프링 DI라는 말이 처음 배울 때 많이 나옵니다. DI란 무엇일까요?
DI는 dependency Injection의 약자로 의존관계 주입이라는 뜻을 가지고 있습니다.
의존관계를 주입한다는 말이 무엇일까요? 다음 코드를 보겠습니다.
@Service
@Transactional
@RequiredArgsConstructor
public class PostService {
private final PostRepository postRepository;
private final UserService userService;
public PostDto write(PostCreateDto createDto, Email email) {
checkNotNull(email, "email must be provided.");
User user = userService.findByEmail(email)
.orElseThrow(() -> new NotFoundException(Email.class, email));
Post post = new Post(createDto.getTitle(), createDto.getContents(), user.getName(), user);
return PostDto.of(postRepository.save(post));
}
}
위 코드에서 PostService는 PostRepository와 UserService라는 클래스를 이용해 로직을 구성하고 있습니다. 만약 이 둘이 없다면 PostService는 큰 낭패를 볼 것입니다. 이를 봤을 때 PostService는 PostRepository와 UserService에 의존하고 있다고 보입니다. 그런데 이 두 클래스는 새로 만들어서 사용하는 것이 아닌 어디에 선가에서 가져와서 사용하고 있습니다.
스프링에서는 실행시점에 빈으로 등록한 객체들을 생성하고 관리하면서 위 코드처럼 의존관계를 주입해 주고 있습니다. 말하자면 한 곳에 빈으로 등록한 모든 객체들을 생성해서 보관하고 필요할 때 제공하는 역할을 하는 것입니다.
그렇다면 왜 이렇게 하는 것일까요?
사실 DI라는 개념은 객체지향 프로그래밍에서 자주 등장하는 개념입니다.
- 강한 결합도
- 객체 내부에서 다른 객체를 생성하는 것은 강한 결합도를 가지는 구조입니다. PostService클래스 내부에서 PostRepository라는 객체를 직접 생성하고 있다면, PostRepository 객체를 다른 객체로 바꾸고 싶은 경우에 PostService 클래스도 수정해야 하는 방식이기 때문에 변경을 한다면 모두 바꿔야 하는 비효율적인 일이 발생합니다.
- 느슨한 결합도
- 객체를 주입 받는다는 것은 외부에서 생성된 객체를 인터페이스를 통해서 넘겨받는 것입니다. 이렇게 하면 결합도를 낮출 수 있고, 런타임시에 의존관계가 결정되기 때문에 유연한 구조를 가집니다. SOLID 원칙에서 O 에 해당하는 Open Closed Principle 을 지키기 위해서 디자인 패턴 중 전략 패턴을 사용하게 되는데, 생성자 주입을 사용하게 되면 전략 패턴을 사용하게 됩니다.
느슨한 결합도를 유지하고 좀 더 유연한 설계를 할 수 있게 만들 수 있는게 DI입니다.
DI는 생성자, 필드, Setter를 이용해 주입할 수 있고, 스프링을 사용할 때 기본적으로 사용하게 되는 부분인 것 같습니다.
'Spring' 카테고리의 다른 글
스프링 기초 이론 1장 (0) | 2020.08.22 |
---|