Pick 서비스를 구현하며 느꼈던 Facade 도입의 필요성 #212
Unanswered
sangwonsheep
asked this question in
Issue tracking 이슈 트래킹
Replies: 1 comment
-
너무 잘 작성해주신것 같습니다. 고생하셨습니다. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
개요
프로젝트를 진행하면서 Facade 패턴의 도입이 왜 필요해지게 되었는지에 대해 이야기를 진행해보도록 하겠습니다.
현재, 프로젝트를 진행하면서 가지고 있는 계층 구조는 이렇습니다.
[Controller - Service - Provider - Repository - DB]
Service와 Repository 사이에
Provider
계층을 하나 더 추가하여 프로젝트를 진행하고 있습니다.Provider
계층의 경우Repository
에서 값을 가져온 후Optional 예외 처리
같은 부분을 담당하고 있습니다.또한,
Provider
계층을 단순히Repository
와1:1 매핑
하여 사용하고 있습니다.이렇게
계층을 분리한 이유
는 위와 같은 예외 처리 코드가 서비스 코드에 작성되어서는 안된다고 판단하여 분리를 결정하였습니다.서비스 계층은 순수한 비즈니스 로직만이 담겨야 한다고 생각하였습니다.
하지만, 서비스 계층에 순수 비즈니스 로직만 담기지 않게 되는 문제가 생겨 그것을 해결하려고 했던 과정에 대해서 알아보겠습니다.
그 과정에서 생각했던 방법 중 하나인
Facade
도입이 왜 필요해지게 되었는지에 대해 설명드리겠습니다.Pick 구조
Pick의 경우
Link
,PickTag
,User
,Folder
와 연관관계를 맺고 있습니다.픽 서비스 코드를 살펴 보시면 많은 연관관계를 가지게 되는 것을 볼 수 있습니다.
연관관계가 많아 생기는 문제 이전에
이 코드에 대한 잘못된 부분
에 대해서 설명드리겠습니다.다른 서비스를 의존하지 않고, 다른 Provider를 의존하는 문제
위 코드에서는 Folder를 이용해야 하는 상황에
Provider를 직접 의존
하고 있습니다. 이는 좋지 않는 방식입니다.FolderService에 관련 코드를 작성해서 Service를 의존하여 해당 메서드를 가져와서 사용하는 방향이 올바르다고 생각합니다.
그렇지 않으면, 다른 서비스에서도 Folder 값이 필요하면 Provider를 이용해서 직접 구현하게 되는 문제가 발생합니다.
이 문제는
Provider를 의존 받지 않고, Service를 의존받아 해결
할 수 있습니다.하지만, Service만 의존한다고 하여도 서비스 계층 존재 목적에 대한 문제도 발생하게 됩니다.
응답 데이터를 서비스 계층에서 모두 조립하려고 하는 문제
픽 서비스에서 많은 의존이 발생하게 되는 이유는 설계 시에 많은 연관관계를 지었던 것도 있습니다.
다른 이유로 응답 데이터를 서비스 계층에서
모두 조립
해서 컨트롤러 측으로 넘겨주려고 합니다.이렇게 하면, Mapper를 이용하여 Entity를 DTO로 변환해서 넘겨준다고 하여도, 코드가 상당히 지저분해지게 됩니다.
순수 비즈니스 로직만 처리하는 것이 아닌, 응답 데이터만을 위한 로직을 작성하게 됩니다.
책임의 분리가 제대로 이루어지지 않아 서비스 계층의 목적에 부합하지 않게 됩니다.
또한, 서비스의 연관관계를 줄이기 위해서 여러 서비스로 분리하게 된다면, 컨트롤러에서 많은 서비스를 의존하게 되는 문제도 발생하게 됩니다.
이를 해결하기 위해 떠올린 방법이
Facade Pattern
입니다.기존 계층 구조
[Controller - Service - Provider - Repository - DB]
변경된 계층 구조
[Controller - Facade - Service - Provider - Repository - DB]
Controller, Service 사이에 Facade 계층을 추가하는 구조로 변경하였습니다.
이렇게 계층을 하나 더 추가했을 때 얻는 이점에 대해 추가적인 설명을 하도록 하겠습니다.
기존에는 Service 계층에서 다른 Service 혹은 Provider를 의존 받아 컨트롤러로 응답 데이터를 조립하여 보내주었습니다.
Facade 계층을 추가하게 되면, Controller - Facade 간 1:1 매핑이 되어 Controller에서 많은 서비스를 의존하지 않아도 되고, 하나의 Facade만 의존하면 됩니다.
Service에서도 다른 서비스들을 의존할 이유 없이, 하나의 서비스는 하나의 역할만 할 수 있게 됩니다.
예를 들어,
PickService
,TagService
를Facade
에서 의존한 후 응답 데이터를 조립하여 컨트롤러로 전달해주면 됩니다.이런 방식을 사용하게 되면 Controller, Service 모두 본래 목적에 맞게 사용할 수 있게 됩니다.
Facade
에게 조립하는 책임을 위임시켜, 각 계층 구조를 순수하게 유지할 수 있게 되었다고 생각합니다.또한, 기존에는 Provider와 Repository를
1:1 매핑
하여 사용하고 있던 문제가 있었습니다.기존에는
PickProvider
-PickRepository
,PickTagProvider
-PickTagRepository
각각 1:1로 되어 있었습니다.Facade를 도입하면서, 함께 Provider의 필요성도 깨닫게 되어 반드시 1:1 매핑이 아닌 공통되거나 비슷한 성격을 가진 부분을
Provider
에 매핑하였습니다.변경된 구조에는
PickProvider
에PickRepository
,PickTagRepository
가 매핑되어 있는 모습을 보실 수 있습니다.그림에서 초록색 박스 부분을 보시면 됩니다.
이렇게 함으로써
Provider
가 단순히 Service와 Repository를 연결해주는 계층이 아닌, 데이터를 전달해주는 목적에 부합하게 되었습니다.결론
실제 프로젝트에서 연관관계가 많아지고, 의존성이 많아지는 상황을 겪어보니, 분리의 필요성을 느끼게 되었습니다.
분리도 단순히 분리하는 것이 아닌, 목적에 맞게 분리하여 각 계층의 목적을 잘 살릴 수 있게 되었습니다.
Provider
계층 도입을 통해 공통되는 Repository를 묶어데이터를 전달하는 책임
을 가지게 되었습니다.Facade
계층 도입을 통해데이터 조립하는 책임
을 가지게 되었고, 각 Service는 해당 도메인에 대한비즈니스 로직
만 처리할 수 있게 되었습니다.각각의 계층의 목적에 맞게 분리가 되어 코드를 읽기 쉽게 되어 개발 생산성이 향상되었다고 볼 수 있습니다.
Beta Was this translation helpful? Give feedback.
All reactions