스프링의 핵심 개념인 IoC(Inversion of Control, 제어의 역전)과 DI(Dependency Injection)에 대해서 조금 적어보려고한다.
이것 저것 보다보니, 개발의 핵심을 초큼 파악하게 됐는데, 그건,,
결합도를 낮추고 응집도는 높이기와,최대한 코드 쉽게 짜기
저 두 개를 달성하게 해줘서 스프링/스프링부트가 성공했나,,,
아무튼 우선 결합도와 응집도의 개념은 다음과 같다.
결합도
클래스간의 상호의존정도를 나타내는 지표. 높은 결합도는 하나를 수정한다고 하면 의존적인 다른 객체를 수정해야한다. 따라서, 결합도가 낮을수록 객체 재사용 및 유지보수가 유리하다.
응집도
하나의 모듈 내부에 존재하는 구성요소들의 기능적 관련성을 나타내는 지표. 응집도가 높은 모듈은 하나의 책임에 집중하고 독립성이 높아져, 역시 재사용 및 유지보수가 용이하다.
추가로 클린 소프트웨어 저자인 로버트 마틴에 따르면
모든 모듈은 1. 제대로 실행되어야 하고, 2.변경이 용이해야되고, 3. 이해하기 쉬워야 한다.
2번 3번에 해당되는 내용이 아닌가 싶다.
아무튼 IoC와 DI가 무엇이기에 결합도를 낮춰 줄까? 우선 결합도가 높은 클래스를 살펴보자
class A {
private B b;
public A() {
b = new B(); //결합력이 강하다. 강한 의존이다. has a 관계이다.
}
}
위의 경우는 A객체가 제대로 동작하기 위해서는 B가 필수적으로 필요하다. 만약 B가 담당하고 있는 기능을 수정하고 싶을 경우에는 1)B의 소스 코드를 찾아 수정하는 방법 2)아에 새로 C를 만드는 방법이 있는데, 많은 경우 2번 방법이 더 수월하다. 그런데 2번 방법을 사용한다면, 우와 같이 강한 의존관계 있는 모든 클래스를 찾아 수정해줘야하는 문제가 있다.
DI(의존 주입)
이런 문제를 해결하는 것이 바로 DI(Dependency Injection)이다. 우선 코드를 보자.
class A {
private X c; //인터페이스 타입으로 변경
public A() {
//b = new C(); //내부에서 직접 생성해서 쓰지 않고
}
public void setX(X c) { //의존성 주입(dependency injection)
this.c = c; // 외부에서 전달받아서 쓸 수도 있다. 결합력이 낮아진다. 느슨한 결합. 더 쉽게 의존성을 바꿀 수 있다.
}
위 처럼 외부에서 메서드를 통해 필요한 객체를 주입받는 것이다. 이렇게 하면 어떠한 변경사항이 있어도 A 내부 코드를 수정할 필요가 없다. A입장에서는 B나 C 객체가 중요한 게 아니고, X인터페이스를 상속받은 객체면 누구나 가능하기 때문에 결합력이 낮아졌다.
하지만 여전히 개발자가 필요한 객체를 주입해주어야하는 귀찮음이 생긴다. 개발자가 a.setX(c)를 입력해주어야 A가 온전히 작동한다.
IoC(제어의 역전)
이때 등장하는 개념이 IoC(제어의 역전)이다. 제어의 역전은 개발자가 직접 객체를 제어(Control)하지 않고, 다른 객체(프로그램)이 컨트롤 하는 것이다. 쉽게 말하면, 어떤 외부의 프로그램이 모든 코드를 쓰윽 보고, DI가 필요한 곳을 찾아서 알아서 객체를 생성해서 DI해주는 것이다. 따라서 아래와 같이 코드를 작성하면 된다.
class A {
private X c;
public A() {
}
}
IoC Container
그럼 이 작업을 누가 해주는가? 이걸 해주는 객체를 'IoC Container'이라고 부르며, 스프링/스프링부트에서는 이런 기능을 제공한다.
또한 이렇게 생성된 객체를 빈(Bean)이라고 하는데, IoC Container에서는 빈을 생성하고, 빈 사이의 의존성을 엮어주고, 빈을 주입(DI)해준다. 또한 빈은 여러 객체에서 자원을 공유하기 위해 싱글톤으로 관리가 되는데, 이것 또한 컨테이너에서 하는 일이며, 빈이 필요하면 생성하고, 보관하고 있다가, 필요 없어지면 제거하는 라이프사이클 관리도 한다.
뭔가 엄청난 기술을 나처럼 기술력이 뛰어나지 않는 사람들도 쉽게 이용할 수 있는 게 결국 핵심이고 경쟁력이구나하는 걸 느낀다.
'Back-end > Spring Boot' 카테고리의 다른 글
[SpringBoot] 스프링부트 이해하기 - 5편 Annotation (0) | 2022.07.16 |
---|---|
[SpringBoot] 스프링부트 이해하기- 4편 Reflection(feat. 동적 로딩) (0) | 2022.07.16 |
[SpringBoot] 스프링부트 이해하기- 2편 Dispatcher Servlet, FrontController패턴 (0) | 2022.07.14 |
[SpringBoot] 스프링부트 이해하기- 1편 Servlet이란(feat. Web Container) (0) | 2022.07.12 |
Entity / Value Object / DTO / DAO 간단하게 개념 정립하기 (0) | 2022.07.03 |