- 어댑터 = 외부 세계와의 소통 창구
- 웹 어댑터 = 웹 인터페이스
5-1. 의존성 역전
- 제어 흐름: adapter.in.web.Controller → application.service.Service
- 호출
- adapter.in.web.Controller →(직접 호출) application.service.Service
- adapter.in.web.Controller →(호출) application.port.in.IncomingPort ←(구현) application.service.Service
Port의 존재 이유
- 코어가 외부와 통신할수 있는 곳에 대한 명세
- 외부와 어떤 통신이 일어나는지 정확히 알 수 있다.
- 레거시 코드를 다루는 유지보수 엔지니어
- 애플리케이션이 웹 어댑터 쪽으로 실시간 데이터를 주어야 하는 경우 ex. 웹 소켓
- 제어 흐름: 웹 어댑터 ← 애플리케이션 코어
- adapter.in.web.WebSocketController →(구현) applicatoin.port.out.WebSocketPort ←(호출) application.service.Service
5-2. 웹 어댑터의 책임
웹 어댑터는 어떠한 도메인 로직도 수행하지 않으며, HTTP 관련 작업 같은 애플리케이션 코어가 신경 쓸 필요 없는 많은 일들을 수행한다.
- HTTP 요청을 자바 객체로 매핑
- 인증 및 권한 검사
- 입력 유효성 검증
- 유스케이스의 입력 모델 유효성 검증과는 다르다.
- 웹 어댑터의 입력 모델을 유스케이스의 입력 모델로 변환할 수 있는가?
- 입력을 유스케이스의 입력 모델로 매핑
- 유스케이스 호출
- 유스케이스의 출력을 HTTP로 매핑
- HTTP 응답을 반환
한 군데에서라도 문제가 생기면 바로 예외를 던진다.
5-3. 컨트롤러 나누기
하나의 컨트롤러에 모든 코드가 들어가 있다면
- 코드가 늘어날수록 파악하기 쉽지 않다.
- 데이터 구조 재활용 촉진
왜 컨트롤러를 나누어야 할까?
- 클래스마다 코드는 적을수록 좋다.
- 코드를 파악하고 테스트하기 쉽다.
- 여러 연산에 대한 동시 작업이 가능하다.
- 유지보수하기 용이하다.
어떻게 컨트롤러를 나누어야 할까?
- 별도의 패키지 안에 별도의 컨트롤러를 만든다.
- 메서드와 클래스명은 유스케이스를 반영해서 짓는다.
- Create, Update, Delete, .. 보다 의미를 드러낼 수 있는 단어를 사용한다.
질문 & 논의할 점
-
p55 웹소켓 컨트롤러는 아웃고잉 포트를 구현하는데 port.in에 위치시켜야 하는가
의미적으로는 애플리케이션이 능동적으로 외부로 데이터를 보내야 하지만, 이것 또한 실제로는 외부에서 인커밍 어댑터이자 아웃고잉 어댑터인 웹소켓 컨트롤러를 호출을 해야하는 것인지
-
p60 AccountResource
dto 클래스를 모든 컨트롤러 메서드에서 재활용하고 있다. 하지만 이건 컨트롤러를 세분화해서 나누는 것의 책임이 아니고, 한 컨트롤러에서도 연산마다 필요한 정보만을 가진 dto를 사용한다면 해결될 문제 같다.
-
p60 각 연산에 대해 가급적이면 별도의 패키지 안에 별도의 컨트롤러를 만드는 방식을 선호한다.
p61 컨트롤러끼리는 모델을 공유할 수 있지만 다른 패키지에 있는 덕분에 공유해서 사용하기 전에 다시 한 번 생각해볼 수 있고, ~.
- adapter.in.web.안에 in.web.sendmoney, in.web.registeraccount 이런 식으로 패키지를 나누어야하는건가?