의존관계 역전의 법칙 (Dependency Inversion Principle)
1. 상위 모듈은 하위 모듈에 의존해서는 안된다. 상위 모듈과 하위 모듈 모두 추상화에 의존해야 한다.
2. 추상화는 세부사항에 의존해서는 안된다. 세부사항이 추상화에 의존해야 한다.
의존관계 역전의 법칙을 잘 적용하게 되면 우리는 하위 모듈의 변경에 의해 상위 모듈이 영향을 받지 않도록 구현할 수 있다
단순 '추상화에 의존해야 한다'로만 DIP 를 이해해서는 안된다
'상위 모듈은 하위 모듈에 의존해서는 안된다' 라는 내용 역시 적용해야 진정한 DIP 를 적용하는 것이라 할 수 있다
그렇다면 과연 상위 모듈과 하위 모듈이 뭘까?
모듈
모듈이란 전체 소프트웨어 시스템을 작은 단위로 쪼개 놓은 것,
작은 단위로 서로 긴밀하게 연관관계가 있는 것,
응집도가 높고 결합도가 낮은 단위로 잘 모아놓은 것이다
자바에서는 패키지가 모듈을 구분하는 기준이 될 수 있다 (항상은 아니다)
예시를 들자면 Service 와 Persistence 등으로 나눌 수 있다
그래서 상위 모듈과 하위 모듈은 무엇인가?
일단 예시를 보면서 이해하자
Service 모듈은 정책과 비즈니스 로직을 담고있는 중요한 모듈이다
Service 모듈은 비즈니스가 바뀌지 않는다면 잘 바뀌지 않는다
Persistence 모듈은 기술적인 역할을 담당하는 모듈이다
Persistence 모듈은 바뀔 가능성이 농후하다
Service 모듈은 상위 모듈이고 Persistence 모듈은 하위 모듈이다
DIP에서 의존성 역전을 하는 이유는 애플리케이션의 중심이 되는 도메인, 비즈니스 로직을 가진 가장 상위 모듈이 기술적인 메커니즘을 다루는 변경 가능성이 높은 하위 모듈에 의존하지 않게 만드는 것이 목적이다
예시로 알아보는 문제점들
Service 는 Persistence 가 수정되면 영향을 받게 된다
다시말해 Service 는 Persistence 에 의존적이다
그렇다면 이 문제를 어떻게 해결해야 할까?
DIP 하면 제일 먼저 생각나는 방법으로 Persistence 를 추상화한 Interface 를 만드는 것이다
그렇다면 Service 는 PersistenceInterface 를 의존하고 Persistence 는 인터페이스를 구현한다
하지만 과연 문제가 끝났을까?
PersistenceInterface 에 대한 문제가 남아있다. 무슨 문제일까?
PersistenceInterface 의 위치에 대한 문제이다
만일 PersistenceInterface 를 Persistence 와 같은 패키지에 두면 여전히 DIP 는 지켜지지 않은 셈이다
걸리는 부분은 상위 모듈은 하위 모듈에 의존해서는 안된다라는 원칙이다
Service 패키지는 상위 모듈, Persistence 패키지는 하위 모듈이다
Persistence 패키지 안에 PersistenceInterface 를 작성한 경우 발생하는 상황은
Service(상위 모듈) 가 Persistence 패키지(하위 모듈) 에 의존하는 상황이 생긴다
그러면 어떻게 해야 DIP 를 위반하지 않을 수 있을까?
간단하다. 인터페이스 소유권만 역전시켜주면 된다
인터페이스 소유권의 역전
인터페이스는 자기를 구현한 클래스가 아닌 자기를 사용하는 클래스 패키지에 위치시킨다는 것이다
Service 패키지에 PersistenceInterface 를 넣어주면 완성이다
이렇게 되면 하위 모듈에서 어떤 일들이 일어나든 상관없이 상위 모듈은 영향을 받지 않게 된다
이 내용을 일반화하면 헥사고날 아키텍처가 완성된다
가장 중심에 도메인과 애플리케이션(최상위 모듈) 이 위치하고, 변경가능성이 높은 웹, 데이터, 인프라 계층이 바깥에 위치하는 구조가 된다
따라서 모든 의존성이 중심으로 향한다
웹이 서비스를 의존하고, 서비스가 데이터를 의존하는 것이 아닌
웹과 데이터(하위 모듈들)가 모두 서비스(상위 모듈) 를 의존하게 된다
이러면 웹과 데이터에서 어떻게 처리하는지, 어떤 기술을 사용하는지에 영향을 받지 않는 구조가 된다
(헥사고날 아키텍처에서 @ID 를 사용하지 않는 순수한 객체를 생각해보라)
출처:
토비의 스프링 6 - 이해와 원리
의존성역전에 대해서 질의 합니다. - 인프런 | 커뮤니티 질문&답변
누구나 함께하는 인프런 커뮤니티. 모르면 묻고, 해답을 찾아보세요.
www.inflearn.com
'Java > Java 기본' 카테고리의 다른 글
함수 파라미터에 final 을 붙이는 이유 (매개변수의 재할당 금지) (0) | 2024.08.30 |
---|---|
record 에 대한 나의 생각 (0) | 2024.08.26 |
[간단] id 의 타입을 long 이 아니라 굳이 Long 으로 주는 이유 (0) | 2024.08.19 |
컴파일러와 JVM 을 곁들인 상속의 원리 (동적 바인딩) (1) | 2024.07.24 |
클래스와 다형성, 그리고 오버라이딩 (2) | 2024.07.23 |