작성
·
285
1
안녕하세요!
객체지향과 디자인패턴 - 최범균
님 책을 읽고 여기까지 왔네요! ㅎㅎㅎ
복습하기 좋은 강의였습니다.
다만, DIP 에서 조금 헷갈리는게 있는데요.
하나의 예를들면서 여쭤보고 싶습니다.
Controller 와 Service가 있다고 하면
Controller 에서 Service 를 의존하고 있을 때,
Service의 구체적인 구현체를 Controller 에서 의존하고 있기에 이것은 Controller ( 고모듈 ) 이 Service (저모듈 ) 을 의존하고 있는 거잖아요.?
그럼 여기서 Controller 와 Service 사이에 Interface를 둬서 Controller에서는 ServiceInterface의 고수준 모듈을 의존하고 ServiceInterface를 상속한 저모듈 구현체는 상속을 한 Interface ( 고수준 ) 에 의존 되어있기에 딱 좋은 예제라고 생각하는데 맞을까요?!
감사합니다.
답변 3
5
DIP를 적용하는 이유는 의존의 방향을 바꿔서 하위 수준의 구현 변경 때문에 상위 수준이 영향 받지 않도록 하기 위함입니다. 이를 통해 상위 수준의 정책은 유지하면서 하위 수준의 구현을 변경할 수 있게 되죠. 이 관점에서 보면 컨트롤러는 사용자와 서비스를 연결해주는 매개체이기 때문에 컨트롤러가 상위 수준이고 서비스가 하위 수준이라고 보기는 어렵습니다.
소스 코드 위치로 생각해보면 조금 더 이해하기가 쉽습니다. DIP에서 인터페이스는 고수준 패키지에 위치하지, 저수준 패키지에 위치하지 않습니다. 이를 컨트롤러와 서비스에 대입해보죠. web, service 패키지가 있을 때 web 패키지에는 컨트롤러가, service 패키지에는 서비스가 위치할 겁니다. 이 구조에서 서비스 인터페이스가 web 패키지에 위치하는 걸 생각해보세요? web이 없으면 서비스를 구현할 수 없다는 뜻이 되는데 뭔가 이상하죠? web에 상관없이 서비스는 존재할 수 있으니까요(배치가 서비스를 호출할 수도 있죠)
컨트롤러 자체는 "사용자 요청을 처리한다"는 상위 수준의 저수준 구현에 해당합니다. 예를 들어 회원 가입 요청을 생각해보죠. 시스템 입장에서 사용자의 가입 요청을 폼으로 받을지 웹소켓으로 받을지 REST API로 받을지는 요구사항에 따라 달라질 겁니다. 즉, 폼 처리용 컨트롤러, 웹소켓용 컨트롤러, REST API용 컨트롤러가 존재할 겁니다. 즉, 시스템을 큰 덩어리로 보면 "사용자의 요청을 받받아 가입 서비스를 실행한다"라는 상위 수준 정책이 있고, 그 상위 수준 정책을 구현한 저수준 구현체(컨트롤러)가 존재하는 겁니다. 그리고 여기서 웹의 경우 상위 수준은 보통 프레임워크가 맡아서 처리하구요.
1
실용적인 접근이 필요하다 생각합니다.
추상화를 하는 이유 중 하나가 구현 클래스를 변경할 수 있는 유연함인 점을 생각해보면, 구현 클래스가 바뀔 가능성이 없는 서비스에 대해 인터페이스를 사용해서 얻는 이점은 거의 없습니다.
아주 예전에는 단위 테스트의 용이함을 위해 서비스에 대해 인터페이스를 만들기도 했는데, 테스트 도구가 클래스에 대한 모의 객체도 쉽게 만들어주기 때문에 테스트에서 모의 객체를 만들 수 있게 하기 위해 인터페이스를 분리할 필요도 없어졌죠.
그리고 컨트롤러가 서비스에 의존하는 구조이기 때문에, 고수준/저수준으로 나눈다면 컨트롤러가 위치한 패키지에 고수준 인터페이스가 위치하기 보다는 서비스 입장에서 UI와 상호작용하기 위한 고수준 인터페이스를 도출하게 됩니다(클린 아키텍처나 포트&어댑터 아키텍처 관련 문서를 참고).
0
그런데 가끔보면 어느분들은 service를 interface로 구현하고 impl 클래스를 따로만드는 분도 있으신반면에 service 클래스를 생성하고 거기다가 그냥 메서드를 바로 구현해서 controller에서 service.method 로 바로 사용하시는 분들이 계시는데 그럼 두가지 방법은 차이점이 뭔가요..?? 후자는 고수준,저수준을 나누지 않은 잘못된방법인가요..? 헷갈리네요ㅠㅠ 아니면 전자처럼, 강의에 나와있는 방법처럼 고수준 저수준을 나누는 방법이 원래는 정석적인 방법인가요??
저도 궁금했던점인데 잘 읽었습니다.