Spring과 JPA를 활용해 처음 개발을 해 가면서, 문득 내가 CRUD를 작동하게는 하지만 왜 이런 코드를 작성했는가에 대해서는 모르는 것도 많고 알아도 얕게 알아서 조리있게 답변하지 못하는 내용들이 많은 것을 깨달았다.
Spring의 핵심 원리인 IOC라는 설계원칙, 이를 충족시키는 DI라는 디자인 패턴, 그리고 생성자를 통한 DI를 권장하는 이유에 대해서 정리해 보려 한다.
강한 결합
DI가 필요한 이유를 이해하기 위해선 먼저 강한 결합을 가지는 클래스의 관계에 대해 생각해 보아야 한다.
public class Customer {
private Chicken chicken;
public Customer() {
this.chicken = new Chicken();
}
}
고객이라는 클래스는 치킨이라는 음식을 먹을 수 있다.
그러나 이러한 클래스설계는 두 클래스가 강하게 결합되어 있다는 단점을 가진다.
고객 클래스는 먹을 수 있는 메뉴가 치킨 뿐이다. 만약 다른 음식을 먹고 싶다면, Chicken이라는 필드값을 Pizza로 수정해야 하는 수고로움이 있다.
즉 Customer 클래스는 Chicken 클래스와 강하게 결합되어 있어 다른 음식으로 교체만 하고 싶음에도 Customer 클래스 자체를 수정해야하는 번거로움이 있다.
이는 Customer 클래스가 Chicken이라는 클래스에 '의존' 하고 있기 때문이다.(Customer가 Chicken을 사용하고 있는 것 = Customer가 Chicken에게 의존)
Dependency Injection(의존성 주입)
이제 의존성 주입을 통해서 강한 결합을 느슨하게 만들어보자
일단 위 클래스에서 가장 문제가 되는 것은 Customer가 다른 음식을 먹고 싶을 때마다 Customer 클래스의 필드까지 수정해주어야 하는 번거로움이 있다는 것이다.
이 자체는 객체지향의 특징 다형성을 통해서 해소가 가능하다.
먼저 Food라는 interface를 선언해주고 Chicken이 Food를 Implements 하게 한다면
public class Customer {
private Food food;
public Customer(Food food) {
this.food = food;
}
}
이런 식의 클래스 형태가 만들어진다.
그러면 나중에 Customer의 생성자 인자에 원하는 Food를 갈아끼워주기만 하면 된다.
이러면 클래스를 수정할 필요가 없으므로 편의성과 다른 Food들에 대한 확장성, 유연성도 좋아진다.
//기존 Customer 사용 방법 Chicken 클래스에게만 의존이 가능
Customer customer = new Customer();
//수정 후 Customer 사용 방법
Food food = new Pizza();
Customer customer = new Customer(food);
이제 우리는 Food 인터페이스에 구체 클래스를 확정하고, Customer 클래스가 무엇을 의존할지 '의존성을 주입' 해주면서 강한 결합을 느슨하게 만들어 주었다.
여기서 나오는 것이 IOC의 개념이다.
DI를 하지 않은 설계에서는
Customer -> Chicken 이라는 구체 클래스로 제어가 진행되었다면
DI를 한 설계에서는
Food를 확정한 후 -> Customer에 주입하는 식으로 제어의 역전이 일어난 것이다.
ex) DI를 통해 Repository -> Service -> Controller 로 제어의 역전.
즉 DI라는 디자인 패턴을 통해 IOC라는 설계 원칙을 충족한 것이다.
Spring에서는 DI 컨테이너를 제공하여 application 실행 시점에 Bean을 생성하고
특정 annotation이 붙은 클래스들을 탐색하며 의존성 주입들을 알아서 쫙쫙해준다!
DI 컨테이너가 Bean들의 생명주기와 객체 관계를 알아서 해주는 것도 IOC라고 볼 수 있다.
(우리가 직접 지정해주던 관계 -> JVM, 에서 Spring이 정해주는 관계와 Bean, 생명주기 -> 우리가 사용)
DI의 장점
강한 결합을 느슨하게 만들어줘 확장성과 유연성을 보장한다!!
'Spring' 카테고리의 다른 글
[Spring] 의존성 주입(DI) 시에 생성자 주입을 사용해야하는 이유 (0) | 2023.12.15 |
---|