From 0d9b5318d17773fcf9fba72b80357b1c1242d90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B7=BC=EC=A3=BC?= Date: Fri, 20 Feb 2026 02:30:50 +0900 Subject: [PATCH 1/2] Chapter_8_to_9 --- .../geunju-lee/Chapter_8_to_9.md | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md new file mode 100644 index 00000000..c7632d69 --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md @@ -0,0 +1,73 @@ +# 트레이드오프 위에서의 아키텍처 선택 + +## 8~9장 +--- + +## chapter 8 - 재사용 패턴 + +코드 복제 : 코드 복제는 코드 수정 시 전체를 동시에 수정해야 하는 부담이 있다. 유지보수가 너무 빡세다. + +공유 라이브러리 : 공통 코어를 JAR로 만들고, api app, admin app, batch app에서 해당 모듈을 사용해봤더니 나중에 배포할 때 이중으로 해서 빡셌다. + +버저닝 전략 : 책에서 말하는 버저닝은 JAR 만들고, 버저닝을 하는거라 그닥 추천하지 않는다. + +공유 서비스 : 외부 통신 및 로직을 묶는 것. 타 팀과 보통 http api로 호출하기 때문에 불가피하다고 생각. EDA로 한다고 해도 실시간 조회는 EDA 불가하기 때문. + +사이드카 패턴/서비스 메시 기법 : ingress와 같은 것을 사용하여 트래픽 제어, 인증서 관리 등등에 사용. 해당 기능을 지원하는 플랫폼이 없다면 거의 무조건 사용. +서비스 매쉬의 경우, 사용하면 호출 관련 로깅 및 트래픽 제어에 좋을거 같음. + +## chapter 9 - 데이터 오너십과 분산 트랜잭션 + +오너십이란 정답이 없는거 같다. 기술적으로 볼 지, 도메인 관점으로 볼 지 등등 관점에 따라 다르게 볼 수 있기 때문이다. + +하지만 현실적으로는 팀 구조와 책임 경계가 데이터 오너십을 결정하는 경우가 많다. + +ACID 트랜잭션은 매우 강력하며 단일 데이터베이스 환경에서는 이상적인 모델이다(RDB가 인기 많은 이유인거 같다). +하지만 서비스가 분리되고 MSA 구조로 확장되면 분산 트랜잭션을 유지하는 비용과 복잡성이 급격히 증가한다. + +따라서 현실적으로는 SAGA 패턴과 보상 트랜잭션이 더 적합한 접근 방식이 된다. + +중요한 것은 원자적 성공이 아니라, 실패 이후에도 시스템 상태를 올바르게 복구할 수 있는 능력이다. + +보통 실무에서는 + +1. 동기 호출로 1차 실패 감지 +2. 이벤트 발행을 통한 비동기 보상 +3. 배치 또는 재처리를 통한 최종 보상 + +이렇게 보상을 한다. + +그리고 이런 처리를 위해 잘 설계된 서비스는 멱등성 보장, 재처리 가능 설계, 순서 보장, 장애 이후 재시도 정책 등을 가능하게 설계한다. + +처음부터 ACID로 해서 한번에 딱 성공하거나 실패하거나 둘 중 하나면 참 좋겠지만, 현실적으로 불가능하다. +이러한 이슈로 인해 결국 예약 혹은 선점 시스템이 나왔다고 생각한다. 이는 최종 상태 이전에 중간 상태를 명시적으로 관리하는 방식이며, +분산 시스템에서 일관성을 유지하기 위한 현실적인 접근이다. + +그리고 EDA를 통해 이 작업을 한다면 좀 더 높은 확률로 성공할 수 있다. 여기서 개인적으로 event가 command를 만든다는 것을 생각하며 개발을 하면 좀 더 나은 결과를 만들 수 있다. +책을 예시로 들면 "고객 프로필 123이 삭제되었다"는 kafka message가 producing하면 그것을 지원계약 팀과 과금 결제 팀에서 consuming 후, 123을 삭제한다고 나온다. + +하지만 Event → Command 파생 구조를 생각한다면 다음과 같이 개발 할 수 있다. + +1. 고객 서비스가 “프로필 삭제됨” message producing +2. 고객 도메인이 이걸 consuming(이 때 다른 group id 2개로 각각 consuming 및 producing) +3. 지원계약 삭제 요청 이벤트, 과금/결제 삭제 요청 이벤트 producing + +이렇게 한다면 결합도가 낮아져서 도메인 책임 분리를 확실히 하고, 재처리 및 부분 복구 용이하다. 예를 들면 batch나 admin을 통해 고객 서비스에서 해지 성공했지만 지원계약이나 과금결제는 실패한 경우, +지원계약 삭제 요청 혹은 과금결제 삭제 요청만 가능하다. + +### 논의사항 + +1. 분산 트랜잭션 및 동시성 관련해서 lock을 어떻게 잡는지(예를 들면 같은 seq에 대해 동시에 2번 취소와 같은게 들어온다면 순서를 지키도록 하거나 하나는 이미 처리중이라며 에러를 던져야하기 때문) +2. 중복 요청(기존 결과 반환)을 호출 측이 신규 성공으로 오해하지 않게, 응답 의미를 어떻게 구분하나 +3. Event → Command 파생 구조는 결국 오케스트레이션 느낌인데, 오케스트레이션 vs 코레오그래피 + +### 내 생각 + +1. 저는 nbase-arc와 같은 메모리 DB를 사용하여 순서 보장 혹은 처리중 오류를 내보냅니다. 또한 서비스가 보낸 서비스의 key값도 저장하여 이중으로 중복 취소를 방지합니다. +2. http 응답 코드로 409 응답. +3. 코레오그래피가 기본적으로 개발이 훨씬 편하다. 그렇지만 운영상 A가 성공했다고 무조건 B를 수행하는 것이 아닌 경우가 존재하고, 그러한 경우를 위해 오케스트레이션이 운영상 이점이 있다고 생각한다. + +### 경험 사례 + +멱등성을 보장하기 위해, 취소를 할 때 무조건 결제번호를 받는 것이 아니라, 첫 취소라면 결제번호, 기존에 부분 취소가 있었다면 마지막 취소번호를 받는다. +해당 seq로 이미 취소된 것이 있다면 해당 응답을 하여 멱등성을 보장한다. From efd934df2daacf77d828ff6ee9170782c6ca3e01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EA=B7=BC=EC=A3=BC?= Date: Fri, 20 Feb 2026 02:33:15 +0900 Subject: [PATCH 2/2] Update 2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../geunju-lee/Chapter_8_to_9.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md index c7632d69..008dea26 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/geunju-lee/Chapter_8_to_9.md @@ -14,7 +14,7 @@ 공유 서비스 : 외부 통신 및 로직을 묶는 것. 타 팀과 보통 http api로 호출하기 때문에 불가피하다고 생각. EDA로 한다고 해도 실시간 조회는 EDA 불가하기 때문. 사이드카 패턴/서비스 메시 기법 : ingress와 같은 것을 사용하여 트래픽 제어, 인증서 관리 등등에 사용. 해당 기능을 지원하는 플랫폼이 없다면 거의 무조건 사용. -서비스 매쉬의 경우, 사용하면 호출 관련 로깅 및 트래픽 제어에 좋을거 같음. +서비스 메시의 경우, 사용하면 호출 관련 로깅 및 트래픽 제어에 좋을거 같음. ## chapter 9 - 데이터 오너십과 분산 트랜잭션