inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

제미니의 개발실무 - 커머스 백엔드 기본편

상품 상세 - 코드 느끼기

상품 상세 컨트롤러 내 서비스 호출 질문

해결된 질문

165

메이플

작성한 질문수 4

1

강의에서 상품 상세 컨트롤러에서 여러 개의 서비스를 직접 참조해 하나의 응답으로 반환하고 있는데요

이 경우, 단일 서비스에서 데이터를 묶어 응답하지 않고 각 서비스를 개별적으로 호출하는 이유가 궁금합니다.

이런 구조가 모듈을 분리했을 때 Aggregation 성격의 서비스가 여러 서비스에 의존하게 되는 문제를 피하기 위한 설계인가요?

또, 여러 서비스를 호출하면 하나의 API 요청 내에서 여러 트랜잭션 커넥션이 열릴 수 있는데, 이를 설계 상 트레이드오프로 봐야 할까요?


추가로, 강의에서는 productId 하나만 받아서 여러 서비스를 독립적으로 호출하고 있는 것 같았는데,
서비스 간 호출 순서가 없으므로 각각을 독립적인 유즈케이스로 보는 게 맞을까요?
아니면 컨트롤러가 여러 서비스를 조합하는 역할을 가져도 되는 걸까요?

마지막으로, 저는 조회 시 실무에서는 모듈별 유즈케이스가 각각 존재하고, 이를 묶어주는 별도의 서비스가 로직과 조합을 포함하여 담당하고 있습니다.

예를 들어 상품 조회 API 응답 시 상품내용과 함께 회원 이름/생년월일 등등 포함, 쿠폰 정보 포함 요구사항이 주어졌을 때
두 가지 방식으로 구현할 수 있을 것 같은데요

어떻게 바라보시는지 궁금합니다.

# 방법1
# 특정 서비스에서 조합하여 호출
상품 API 모듈(컨트롤러) → 상품 Service 모듈 → 회원 모듈 서비스1, 쿠폰 모듈 서비스2, ...
# 방법2
# 각 서비스를 컨트롤러에서 호출
상품 API 모듈(컨트롤러) → 회원 모듈 서비스1, 쿠폰 모듈 서비스2

강의에서는 방법2 와 비슷하게 처리하신 것 같습니다.


강의 중 여러가지 패턴을 소개해 주신다고 했지만 급하게 질문드리는 점 죄송합니다.

kotlin spring-boot 도메인 dbms/rdbms backend

답변 1

1

제미니

안녕하세요 질문 감사합니다!
질문이 좀 산개 되어있어서 😅 하나씩 정리해서 답변드리겠습니다!

[질문1]

적어주신 내용들 보다는 개념간의 적절한 격벽 구성을 유지하며 가장 쉽게 요구사항을 구현하는 목적을 달성하기 위한 전략 중 하나를 적용하였다고 봐주시면 됩니다

+ 추가로 기존 질문과 유사한 느낌의 질문이 있어서 링크 첨부 드립니다!

위의 링크드린 질문 답변에도 있지만 이 방식이 제가 선호하는 구현 방식은 아닙니다
그저 지금 상황과 규모에 맞는 적절한 구현 전략을 선택한 예시를 보여드리고 생각을 해보시게 만들어드리고 싶었습니다 😃

++ 트랜잭션에 대해서는 추가로 적어두면 Service 하나에 트랜잭션 하나로 묶는 것은 경우에 따라 역으로 비효율이 발생할 수 있습니다 (너무 길고 큰 트랜잭션일 경우 + 내부에서 외부 통신으로 Tran 시간이 길어지고 커넥션을 과소비하는 등)
그래서 이것 자체가 트레이드 오프가 될 수 있다고 봅니다,
개인적으로 저는 Service 함수에 Transaction을 무조건 or 쉽게 거는 것을 선호하지는 않습니다!
(그래서 Controller 에서 이 구조와 Transaction은 크게 관여가 없는 전략이라고 봐주셔도 될 것 같습니다! 또 우리 강의 예제 규모에서는 신경쓸 수준이 아니라고 보여지구요!)

 

[질문2]

유즈케이스 라는 관점으로 봐도 크게 문제는 없을 것 같은데요! 지금 강의 기준으론 각각의 개념이 요구사항을 충족하기 위한 기능을 제공하고 있는 것이라고 이해해주시면 될 것 같습니다!
사실 이 강의 규모에서는 잘 정리된 느낌의 유즈케이스라던가, Aggregation이라던가 를 논하기엔 너무작은 규모+혼란스러운+요구사항이 너무 빈약한형태라 생각합니다 😃

가령 ProducSectionService 함수 하나를 유즈케이스로 보기엔 미묘한 부분이 있다고 봅니다

 

[질문3]

일단 제가 바라보는 기준과 구현 전략에서는 대부분의 경우 Service 에서 다른 Service 를 호출하게 하지 않습니다

위의 유사 질문의 답변에도 있지만 저는 방법1,2 둘다 아닌 Service -> 구현을 위한 도구들을 호출하는 방식으로 작업하는 것을 선호합니다 (당연히 무조건은 아니고 대부분의 경우입니다)

이것 관련해서는 지속 성장 가능한 소프트웨어를 만들어가는 방법 이라는 제가 작성한 블로그 글인프런 무료강의 가 있으니 궁금하시면 봐보셔도 좋을 것 같습니다!

 

++ 추가로 어느 정도 규모의 서비스를 운영중이신지는 제가 잘 몰라서 조심스럽지만 제 의견을 적어보면
모듈별이라는 의미가 만약 멀티모듈의 모듈이라면 조금 과한 구조가 아닐까 싶단 생각이 들었습니다!

제가 상상하는 구조라면 적절한 응집이 구성되지 않은 형태일 것 같이 느껴집니다 🤔
(이건 제가 상황을 잘 모르고 한 말이니 그냥 지금 제가 가진 정보 기준의 잘 모르는 사람이 말하는 느낌이라 봐주시면 될 것 같습니다 😃 아니라면 참 다행이에요!)


추가적으로 질문 주신 것들에 대한 의도와 느낌과 고민은 뒷 강의들을 들으시다보면 더 혼란을 느끼시면서 생각이 정리 되실 수 있을 것 같습니다, 종류별로 구현체를 뒤죽박죽 해두었거든요! 😃

모쪼록 시작하시는 시점에 혼란을 충분히 느끼고 계신데 아주 좋다고 봅니다!
지금 상태에서 약간이나마 답이 되었길 바라며 완강까지 화이팅입니다!
추가 질문이 있다면 편하게 주시길 바랍니다!

0

메이플

안녕하세요 답변 감사합니다!
출근길에 듣다가 출근 후 급하게 작성 한 질문이었는데 정리 까지 너무 잘 해주셔서 너무 감사합니다 😭

지금 보니 질문자체가 많이 엉망이었네요..

 

# 방법1# 특정 서비스에서 조합하여 호출
상품 API 모듈(컨트롤러) → 상품 Service 모듈 → 회원 모듈 서비스1, 쿠폰 모듈 서비스2

위 질문 중 모듈 서비스1, 서비스2라고 퉁쳤지만

강의에서 설명하는 네이밍을 적용했을 때

상품 API → 상품 유즈케이스 → 회원 Finder 혹은 Reader, 쿠폰 Finder 혹은 Reader
같이 질문을 드렸다면 더 좋았을 것 같네요

블로그글을 과거에 본적이 있었는데

초반 강의에서 소개한 스타일과는 느낌이 달라서 혼란이 왔던 것 같습니다.

완강까지 빠르게 달려보겠습니다!


모듈 내용이 있어서 추가 질문이 있는데요
말씀 주신대로 현재 저희 팀에서는 모노레포 멀티모듈 구조로 개발 중이며, MSA 환경은 아닙니다.

 

모듈 구조는 크게 아래와 같이 구성되어있습니다.

  • api: HTTP 요청/응답 처리

  • application: 유즈케이스(Service)

  • domain: 도메인 모델

  • infra: 구현체

  • integration: 외부 도메인 데이터 제공

    • 도메인 객체가 무분별하게 전파되지 않도록 Finder, Reader 등을 통해 DTO로만 반환하도록 하고 있습니다.

위 구조가 member, product 등 도메인 단위별로 분리되어 있는 형태로 봐주시면 좋을 것 같습니다.

 

이때 만약 product 상품 조회에서 회원 이름과 같이 응답해야한다고 했을 때

product:api -> product:application -> product:domain, member:integration<-- product:infra(product:domain) 의존


이러한 의존 방향으로 처리를 하고 있었는데요

 

  • product 서비스가 member를 의존한다.

    • integration 으로 간적접인 dto를 의존으로 타협했으니 넘어가자

  • api와 application 사이에 또 다른 레이어를 두는 방법

    • 규모 상 공수가 너무 많이 들 것 같아 포기

  • api 모듈에서 필요한 객체들을 의존해서 조합

    • 컨트롤러에 조합 로직이 많아진다..

  • FE에서 키를 가지고 조합

    • 상황상 불가

     

이러한 고민들이 있었고 타협이 있었습니다.

 

강의를 듣다보니 과거에 고민했던 내용들이 다시 떠오르면서 생각이 많아졌습니다

정답은 없겠지만 현재 구조에서 조언 좀 부탁드립니다..

3

제미니

흠.. 우선 회사or팀에서 저렇게 나누는 선택을 하셨나보군요!

먼저 개인적으론 구조가 좀 아쉽습니다ㅠㅠ 모듈이 어느 수준으로 쪼개진지 모르겠지만 member, product 이런 수준으로 나뉘어진 것이라면,, 장기적으로 모듈간 상호 참조 이슈도 꽤 나올 것 같은데요..😢


일단 제 경우는 기본적으로 다른 것은 다 부수적이고 핵심비즈니스를 다루는 클래스 -> 도구가 되는 구현 중심 클래스 로 흐르게 하는 것을 선호합니다

사실 개념(적어주신 것 기준 모듈 수준)마다 무게와 각각의 개념 사이거리감이 다르고 실질적으로 더 중요한 개념의 급수(1급,2급)이 나뉘게 됩니다

그런 구조에서 member 가 모듈 수준으로까지 나와있는 형태가 된다면 member 는 상당 부분 많은 기능에서 사용할 것이기 때문에 중구난방에 퍼져있는 형태가 되는 문제가 생길 것 같습니다 😢

마이페이지 같은 것이 member 에 들어간다면 타 모듈을 다 알고 있어야할 것 일거구요..
의존 방향을 고민하기 전에 전체적인 구조 먼저 바꿔야겠단 생각이 들긴합니다만.... 🤔

그럼에도 내부에서 많은 고민을 가지고 결정하셧을테니 존중합니다!
많이 고민해보시고 내부에서 토의해보시는게 좋을 것 같다고 생각합니다!


모쪼록 제가 전체 상황을 다 이해하고 의견드린 것은 아니니 절대적으로 정답이 아닐 것이라서 한명의 의견 정도로 참고만 부탁드립니다!

0

메이플

답변 알림을 못봤었네요!
많은 도움이 되었습니다. 강의 너무 재밌습니다!

다양한 관점의 코드 경험을 위해 개선하지 않은 코드

1

47

1

histories() 응답에 PointHistory.id를 포함한 이유가 궁금합니다/

1

44

2

SettlementTargetRepository Jquery 질문

1

48

2

부가 기능을 이벤트 핸들러로 분리하는 기준이 있을까요?

1

60

2

엔티티의 pk 를 0으로 초기화하시는 이유가 있을까요??

1

67

2

제미니님 안녕하세요!

1

73

2

개념 간 격벽 분리와 목록 조회 시 발생하는 참조 구조

1

80

2

프로덕트와 프로덕트카테고리 사이의 삭제 정책

1

75

2

새로 개발한다면 구현 순서

1

133

1

의존 방향에 대한 고민

1

122

2

어드민(Back-office)에서 예약 변경 시, '할인 조건 재검증(쿠폰 회수)' vs '기존 혜택 유지' 중 어떤 정책이 일반적인가요?

1

95

2

OrderKeyGenerator 인스턴스화 generate() 질문

1

83

1

외부 API 통합 시 데이터 제어 범위 설계 질문

1

96

1

PG 결제 승인 로직

1

128

2

QnA에서 Join 필드 표현법

1

88

1

결제서비스 콜백 동시성문제 가능성

1

106

2

굿

1

107

1

도메인/엔티티 분리 상황에서 쓰기 작업 하는 방법

1

135

2

도메인 객체와 엔티티 객체 사용

1

137

2

CouponService 의존성 의문

1

96

2

상품 목록 조회 고도화 질문

1

111

2

표현 계층에서의 접근 지점이 다양해지는것과 이를 해결하기 위한 파사드의 도입에 대해 제미니님의 생각이 궁금합니다.

1

123

2

제품상세 코드 느끼기

1

144

2

격벽의 순환 참조(?)

1

113

2