-
Notifications
You must be signed in to change notification settings - Fork 5
소프트웨어 아키텍처 The Hard Parts sprint 4 - 이근주 #615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| # 트레이드오프 위에서의 아키텍처 선택 | ||
|
|
||
| ## 8~9장 | ||
| --- | ||
|
|
||
| ## chapter 8 - 재사용 패턴 | ||
|
|
||
| 코드 복제 : 코드 복제는 코드 수정 시 전체를 동시에 수정해야 하는 부담이 있다. 유지보수가 너무 빡세다. | ||
|
|
||
| 공유 라이브러리 : 공통 코어를 JAR로 만들고, api app, admin app, batch app에서 해당 모듈을 사용해봤더니 나중에 배포할 때 이중으로 해서 빡셌다. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| 버저닝 전략 : 책에서 말하는 버저닝은 JAR 만들고, 버저닝을 하는거라 그닥 추천하지 않는다. | ||
|
|
||
| 공유 서비스 : 외부 통신 및 로직을 묶는 것. 타 팀과 보통 http api로 호출하기 때문에 불가피하다고 생각. EDA로 한다고 해도 실시간 조회는 EDA 불가하기 때문. | ||
|
|
||
| 사이드카 패턴/서비스 메시 기법 : ingress와 같은 것을 사용하여 트래픽 제어, 인증서 관리 등등에 사용. 해당 기능을 지원하는 플랫폼이 없다면 거의 무조건 사용. | ||
| 서비스 메시의 경우, 사용하면 호출 관련 로깅 및 트래픽 제어에 좋을거 같음. | ||
|
|
||
| ## chapter 9 - 데이터 오너십과 분산 트랜잭션 | ||
|
|
||
| 오너십이란 정답이 없는거 같다. 기술적으로 볼 지, 도메인 관점으로 볼 지 등등 관점에 따라 다르게 볼 수 있기 때문이다. | ||
|
|
||
| 하지만 현실적으로는 팀 구조와 책임 경계가 데이터 오너십을 결정하는 경우가 많다. | ||
|
|
||
| ACID 트랜잭션은 매우 강력하며 단일 데이터베이스 환경에서는 이상적인 모델이다(RDB가 인기 많은 이유인거 같다). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| 하지만 서비스가 분리되고 MSA 구조로 확장되면 분산 트랜잭션을 유지하는 비용과 복잡성이 급격히 증가한다. | ||
|
|
||
| 따라서 현실적으로는 SAGA 패턴과 보상 트랜잭션이 더 적합한 접근 방식이 된다. | ||
|
|
||
| 중요한 것은 원자적 성공이 아니라, 실패 이후에도 시스템 상태를 올바르게 복구할 수 있는 능력이다. | ||
|
|
||
| 보통 실무에서는 | ||
|
|
||
| 1. 동기 호출로 1차 실패 감지 | ||
| 2. 이벤트 발행을 통한 비동기 보상 | ||
| 3. 배치 또는 재처리를 통한 최종 보상 | ||
|
|
||
| 이렇게 보상을 한다. | ||
|
|
||
| 그리고 이런 처리를 위해 잘 설계된 서비스는 멱등성 보장, 재처리 가능 설계, 순서 보장, 장애 이후 재시도 정책 등을 가능하게 설계한다. | ||
|
|
||
| 처음부터 ACID로 해서 한번에 딱 성공하거나 실패하거나 둘 중 하나면 참 좋겠지만, 현실적으로 불가능하다. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| 이러한 이슈로 인해 결국 예약 혹은 선점 시스템이 나왔다고 생각한다. 이는 최종 상태 이전에 중간 상태를 명시적으로 관리하는 방식이며, | ||
| 분산 시스템에서 일관성을 유지하기 위한 현실적인 접근이다. | ||
|
|
||
| 그리고 EDA를 통해 이 작업을 한다면 좀 더 높은 확률로 성공할 수 있다. 여기서 개인적으로 event가 command를 만든다는 것을 생각하며 개발을 하면 좀 더 나은 결과를 만들 수 있다. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| 책을 예시로 들면 "고객 프로필 123이 삭제되었다"는 kafka message가 producing하면 그것을 지원계약 팀과 과금 결제 팀에서 consuming 후, 123을 삭제한다고 나온다. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| 하지만 Event → Command 파생 구조를 생각한다면 다음과 같이 개발 할 수 있다. | ||
|
|
||
| 1. 고객 서비스가 “프로필 삭제됨” message producing | ||
| 2. 고객 도메인이 이걸 consuming(이 때 다른 group id 2개로 각각 consuming 및 producing) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| 3. 지원계약 삭제 요청 이벤트, 과금/결제 삭제 요청 이벤트 producing | ||
|
|
||
| 이렇게 한다면 결합도가 낮아져서 도메인 책임 분리를 확실히 하고, 재처리 및 부분 복구 용이하다. 예를 들면 batch나 admin을 통해 고객 서비스에서 해지 성공했지만 지원계약이나 과금결제는 실패한 경우, | ||
| 지원계약 삭제 요청 혹은 과금결제 삭제 요청만 가능하다. | ||
|
|
||
| ### 논의사항 | ||
|
|
||
| 1. 분산 트랜잭션 및 동시성 관련해서 lock을 어떻게 잡는지(예를 들면 같은 seq에 대해 동시에 2번 취소와 같은게 들어온다면 순서를 지키도록 하거나 하나는 이미 처리중이라며 에러를 던져야하기 때문) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코레오그래피 형태로 운영되고 있어서, 각 MS에서 데이터오너쉽을 가지는 데이터 기준으로, 동시성 처리에 대한 책임을 가집니다 그래서 lock 구현도 굉장히 다양한 편 입니다. 낙관적, 비관적 lock 모두 상황에 따라 각 서비스 담당자들 판단하에 선택해서 사용하고 있습니다
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
과거 책에서 본 기억을 떠올려 보면 낙관적 락으로 우선 DB 점유를 짧게 가져가는 방식을 쓸 것 같습니다.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저희 팀이 오너십으로 있는 서비스들은 대부분 낙관적 락을 사용합니다. |
||
| 2. 중복 요청(기존 결과 반환)을 호출 측이 신규 성공으로 오해하지 않게, 응답 의미를 어떻게 구분하나 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 신규 성공으로 오해하지 않도록 하기 위해서는 중복된 복수 요청임을 알려야해서, 409로 내려주는 선택을 주로 하는 것 같습니다 중복 요청임을 알려주지 않아도 될 경우는 그냥 2XX로 처리 합니다
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 전 409 에러를 의미있게 써 보진 않았지만 상태 코드로 쓰기에는 맞는 것 같습니다.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 해당 방식을 생각해 본 적이 없는데, 이번 기회에 409를 알게 되었네요! |
||
| 3. Event → Command 파생 구조는 결국 오케스트레이션 느낌인데, 오케스트레이션 vs 코레오그래피 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Event -> Command 형태로 했을 때, 말씀해주신 장점이 있는 반면에, 이벤트를 발행하는 측에서, 타 MS의 비즈니스 도메인에 의존되는 문제가 있을 것 같습니다 그래서 결국에는 말씀하신대로 설계했을 때, 자연스럽게 오케스트레이터가 되지 않을까 생각되고(타 MS 비즈니스 도메인 의존 때문에), 그렇기 때문에 코레오그래피 형태로 가게 된다면, 어쩔 수 없이 책에서 나오는대로, 이벤트 발행 주체의 이벤트 발생에만 집중하는 형태(프로필 삭제됨)로 가는게 더 낫지 않을까 라는 생각 입니다 저희 회사에서는 일단은, 각 팀 마다 운영효율을 가져갈 목적으로 코레오그래피 형태로 운영되고 있고, 이벤트 발행 주체의 부담을 최소화 하기위해서(다른 MS 의 비즈니스 도메인은 알 바가 아니다 라는 태도로 함), 이벤트 수신처에서 이벤트의 멱등성과 비즈니스로직 처리 여부를 결정하는 방식으로 되어있습니다
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 코레오그래피로 한다고 해도 event와 command 처리 순서에 정상 상황과 예외 상황에 대해서 오케스트레이션이 하는 방식을 대안으로 구현해 두면 어떨까? 하는 생각을 해봤습니다. 책에서는 개념에 대한 설명을 해야 하기 때문에 한 가지 방식씩 설명하는 건데, 실제로는 두 가지 방식을 혼합해서 사용해도 괜찮지 않나 하는 생각이죠.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
혼합해서 사용하는것도 괜찮은 방법 같습니다 어느쪽에서 이벤트 발생에 대한 각 MS의 도메인로직 제어의 책임을 가질 것인가에 따라서, 오케스트레이터 혹은 코레오그래피로 나뉠거 같은데요 근주님이 말씀해주신대로 이벤트 발행 -> 커맨드(오케스트레이터) 처럼 함으로써 장애 처리에 장점이 있는 부분을 최대한 살릴 수 있는 부분은 실제로 오케스트레이터 역할을 하는 팀과 팀의 서비스가 실제 그 역할을 할 수 있도록 해주고, 나머지는 기본적으로는 코레오그래피이면서, 이벤트발행 식으로 동작하도록 하면 어떨까 생각됩니다 이부분 관련해서 가끔씩 회사 내에서도 논쟁이 있는 부분인데(도메인로직 제어 책임을 어떤 MS에서 가질 것인지), 활용해볼 만한 내용 같습니다 |
||
|
|
||
| ### 내 생각 | ||
|
|
||
| 1. 저는 nbase-arc와 같은 메모리 DB를 사용하여 순서 보장 혹은 처리중 오류를 내보냅니다. 또한 서비스가 보낸 서비스의 key값도 저장하여 이중으로 중복 취소를 방지합니다. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| 2. http 응답 코드로 409 응답. | ||
| 3. 코레오그래피가 기본적으로 개발이 훨씬 편하다. 그렇지만 운영상 A가 성공했다고 무조건 B를 수행하는 것이 아닌 경우가 존재하고, 그러한 경우를 위해 오케스트레이션이 운영상 이점이 있다고 생각한다. | ||
|
|
||
| ### 경험 사례 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 실무에서의 경험도 공유 해주셔서 감사합니다! |
||
|
|
||
| 멱등성을 보장하기 위해, 취소를 할 때 무조건 결제번호를 받는 것이 아니라, 첫 취소라면 결제번호, 기존에 부분 취소가 있었다면 마지막 취소번호를 받는다. | ||
| 해당 seq로 이미 취소된 것이 있다면 해당 응답을 하여 멱등성을 보장한다. | ||


There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The phrase "유지보수가 너무 빡세다" is quite informal. While this is a personal note, for a more professional document, consider rephrasing it to something like "유지보수 부담이 크다" or "유지보수가 어렵다."