'마이' 도메인 없이 마이페이지 데이터를 조합하는 법
사용자, 주문, 상품의 책임은 각 도메인에 유지하면서 전용 조합 계층으로 마이페이지 요약 데이터를 만드는 방법을 설명합니다.
출처 및 AI 안내: 이 글은 제미니의 개발실무 유튜브를 기반으로 작성되었습니다.
gpt-5.6-sol모델을 사용해 생성·편집했습니다.
마이페이지 하나에서 프로필, 주문, 상품과 여러 상태별 건수를 한꺼번에 보여줘야 할 수 있습니다. 이때 바로 선택지가 생깁니다. 프론트엔드가 각 도메인의 API를 따로 호출하게 할지, 백엔드가 화면 전체를 조립하는 API를 제공할지 결정해야 합니다. 두 번째 방법을 택하면 백엔드에 My라는 새 도메인이 필요해 보이지만, 대부분은 그렇지 않습니다.
한 화면이 기존 정보를 모아서 표현한다고 해서 사용자와 주문 개념이 같은 책임을 갖게 되지는 않습니다. 따라서 설계의 핵심은 새 도메인을 만드는 일이 아니라, 기존 구현의 경계를 해치지 않으면서 여러 조회를 어디에서 조율할지 정하는 일입니다.
화면 요구사항과 도메인 모델을 분리합니다
먼저 화면이 실제로 무엇을 보여주는지 확인해야 합니다. 주문 내역 화면으로 가는 링크, 짧은 요약, 전체 주문 목록은 서로 다른 요구사항입니다. 세 기능이 모두 ‘마이’라는 메뉴 아래에 있다는 이유로 같은 API 모양을 물려받을 필요는 없습니다.
프로필 옆에 총 주문 수, 배송 중인 주문 수, 결제 완료 건수를 보여준다고 가정해 봅시다. 이런 집계는 이 요약 화면에서만 필요할 수 있습니다. 일반적인 주문 서비스가 반드시 소유해야 하는 행위는 아닙니다. 반면 별도의 주문 내역 화면은 주문 목록을 탐색하도록 설계한 주문 기능을 계속 사용하면 됩니다.
이 구분은 패키지 위치에도 영향을 줍니다. 기능이 사용자 프로필 행위의 확장에 그친다면 사용자 영역 가까이에 두는 선택도 가능합니다. 사용자, 주문, 상품과 다른 영역을 함께 조합한다면 어느 한 영역의 안쪽보다 바깥에 조합 코드를 두는 편이 의존 방향을 더 분명하게 보여줍니다. My라는 이름은 사용자가 보는 화면을 설명할 뿐, 그 자체로 독립된 비즈니스 도메인의 존재를 증명하지는 않습니다.
참여하는 서비스보다 한 단계 위에서 조율합니다
같은 계층의 여러 서비스가 하나의 결과에 기여해야 한다면, 저는 그 서비스들보다 한 단계 위에 작은 조합 계층을 둡니다. 프로젝트에 맞춰 MyFacade, 래퍼 서비스 같은 이름을 붙일 수 있습니다. 이름보다 중요한 것은 역할입니다. 안정된 기능들을 조율하고 프레젠테이션 계층이 요구하는 데이터를 만드는 곳이어야 합니다.
사용자 서비스 ------+
주문 리더 ----------+--> My 파사드 --> 마이페이지 응답
결제 리더 ----------+
이 계층을 두면 동등한 위치의 한 서비스가 다른 서비스의 구현체에 직접 접근하는 상황을 피할 수 있습니다. 서비스끼리 접근할 때 구체 구현에 의존해야 하는 레이어 규칙을 사용한다면, 이 조율자를 다시 일반 서비스라고 부르는 것은 역할을 가리고 복잡도만 높일 수 있습니다.
조율자가 모든 값을 얻기 위해 주 주문 서비스를 호출해야 하는 것도 아닙니다. 일반 주문 유스케이스가 제공하지 않는 집계가 필요하다면 주문 리더를 직접 사용하거나 요약 전용 조회 구현을 둘 수도 있습니다. 현재 코드와 실제 요구사항에 따라 선택은 달라집니다. 중요한 검토 기준은 이미 잘 만든 기능을 활용하면서 구현 중복을 적게 유지해 이 화면을 완성할 수 있느냐입니다.
API마다 의미 있는 작업량을 부여합니다
범용 API도 응답 데이터가 소비자의 작업에 맞을 때 유용합니다. 구매한 항목과 가격, 상태를 모두 반환하는 상세 주문 내역 API를 생각해 봅시다. 마이페이지가 이 API를 호출한 뒤 프론트엔드에서 건수를 세면 코드를 재사용한 것처럼 보입니다. 그러나 불필요한 데이터 전송과 계산이 생길 수 있습니다.
페이징을 적용하면 문제가 더 분명해집니다. 주문을 만 번 한 고객이 있다고 해서 총 주문 수 하나를 계산하려고 프론트엔드가 모든 페이지를 가져와서는 안 됩니다. 요약 요구사항에는 요약 조회가 필요합니다. 전체 주문 내역 API는 주문 내역을 탐색하는 책임에 집중시키는 편이 맞습니다.
마이페이지가 실제로 동일한 전체 내역을 보여줘야 한다면 마이 전용 주문 API도 선택할 수 있습니다. 이때는 제품 요구사항도 다시 살펴볼 필요가 있습니다. 프로필에서 전체 내역을 보여주면서 별도의 주문 내역 화면도 유지하면 사용자 경험이 중복될 수 있습니다. API 경계는 현재 화면의 모든 상자가 아니라 의미 있는 유스케이스를 따라야 합니다.
클라이언트가 여러 API를 호출할지, 하나의 조합 응답을 받을지는 여전히 프레젠테이션 영역의 결정입니다. 특히 앱 호환성을 고려하면 API 계약을 바꾸는 비용이 커질 수 있습니다. 그런 제약 안에서도 프레젠테이션 API는 그 아래 구현보다 비교적 유연하게 나누거나 합칠 수 있습니다. 오래 지켜야 할 대상은 특정 UI 버전에 묶인 컨트롤러 모양이 아니라 재사용할 수 있는 비즈니스 기능과 조회 기능입니다.
규모가 커질 때 더 강한 경계를 만듭니다
조회 조합이 필요해졌다는 이유만으로 넓은 ‘통합 조회’ 도메인을 만들거나 모든 개념을 곧바로 별도 최상위 모듈로 분리할 필요는 없습니다. 사용자, 주문, 상품, 재고, 결제는 시간이 지나며 더 분명한 군집을 이룰 수 있습니다. 일부 영역이 커져서 별도 서비스로 분리할 상황에 가까워질 수도 있습니다. 그때 더 강한 패키지나 모듈 경계의 비용이 정당화됩니다.
그전에는 각 도메인 영역의 응집을 유지하고, 화면에 필요한 좁은 조율 지점만 추가하면 됩니다. 백엔드가 원하지 않아도 UI와 API의 모양은 바뀝니다. 작은 파사드나 조회 조율자는 그 변화를 한곳에 모으면서 내부 구현을 계속 재사용할 수 있게 합니다.
실무에서는 순서가 중요합니다. 화면에 상세와 요약 중 무엇이 필요한지 확인하고, 참여하는 각 도메인의 책임을 지키며, 그보다 한 단계 위에서 데이터를 조합하고, 실제 유스케이스에 맞는 API 응답을 설계합니다. 그러면 마이페이지가 커져도 My를 모든 것을 담는 도메인으로 만들거나 화면 변경이 코어 코드 전체로 번지게 하지 않을 수 있습니다.