From 6209e365811cb0d3a1c6776ef44fa1b403640a76 Mon Sep 17 00:00:00 2001 From: chichoon Date: Fri, 20 Mar 2026 18:35:24 +0900 Subject: [PATCH 1/9] add chapter 10 --- .../chichoon/09.md | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md new file mode 100644 index 00000000..37cda007 --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md @@ -0,0 +1,42 @@ +## Chapter 10: 분산 데이터 액세스 + +### 개요 + +- 서비스간 통신패턴: 서비스 간 데이터를 주고받는 방식 + - 요청하는 대로 데이터를 다 줬다가는 레이턴시가 발생하므로 성능이 떨어진다 + - 또한 여러 서비스가 데이터 때문에 커플링되어 의존성이 생기기 때문에, 한 쪽을 수정할 때 다른 쪽도 수정해야 하는 불상사가 발생 + +--- + +### 컬럼 스키마 복제 패턴 + +- 컬럼을 여러 테이블에 복제해서, 다른 경계 콘텍스트에서도 가져다 쓸 수 있게 하는 방법 +- 데이터를 매번 동기화해야 함 => 일관성 유지 어려움 +- 데이터 오너십 통제 어려움 + - 복제해서 다른 서비스에 쥐어주는 순간, 해당 데이터는 내 소유가 아니기 때문 + +### 복제 캐싱 패턴 + +- 데이터를 그대로 복사하여 새 테이블에 저장하는 것이 아니라, 대신 캐싱을 하는 방법 +- 캐시는 서비스별로 고유하게 저장되기 때문에 타 서비스와 공유되지 않음 (분산 캐싱) +- 단점 + - 대신 위의 스키마 복제 패턴과 동일하게, 디펜던시만 이동했을 뿐 동기화 문제에서 자유롭지 않다 + - 캐시 데이터는 중앙으로 공유되기 때문에, 타 서비스에서 데이터를 자유롭게 업데이트 할 수 있는 것은 그대로고, 경계 콘텍스트도 무너질 수 있다 + - 중앙 분산 캐시 (각 서비스별 캐시가 공유되는 위치) 는 원격 호출을 위해 접근해야 하므로 레이턴시가 늘어나는 것도 동일하다 + - 경우에 따라 복제 캐싱이 지원되지 않을 수 있다 +- 장점 + - 각 서비스별로 캐시를 갖고 있기 때문에 서로 간섭할 일이 없다 + - 또한 각 서비스별 캐시에 접근하면 되므로 데이터 액세스가 빠르다 +- 트레이드오프 + - 캐시 데이터와 시작 타이밍에 서비스가 크게 의존한다 + - 각 서비스별로 캐시에 데이터를 채우므로, 그 캐시에 접근하는 다른 서비스는 해당 주인 서비스가 먼저 시작되어야 대기 상태에서 탈출할 수 있다 + - 데이터 양이 많을 경우 실용성이 떨어진다 + - 캐시 수만큼 용량이 \*n 이 되므로 + +### 데이터 도메인 패턴 + +- 여러 서비스가 공유하는 테이블을 하나의 스키마에 집어넣어 관리 +- 서비스가 서로 디커플링되어 디펜던시 문제와 응답성, 처리량, 확장성 이슈가 해소됨 +- 여러 서비스가 동일한 테이블을 바라보기 때문에, 무결성 문제에서도 자유롭다 +- 다만 해당 스키마의 테이블 구조가 변경될 경우 다른 서비스들도 영향을 받을 수 있다 +- 서비스 오너십과 경계 콘텍스트를 엄격하게 설정하여 타 서비스가 접근해야 하면 안될 데이터들을 적절히 막는 것이 좋다 From 27c224813e9324d2fa5b416f1bc39a82f1c45079 Mon Sep 17 00:00:00 2001 From: chichoon Date: Fri, 20 Mar 2026 18:35:29 +0900 Subject: [PATCH 2/9] add chapter 11 --- .../chichoon/10.md | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/10.md diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/10.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/10.md new file mode 100644 index 00000000..2c4a3635 --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/10.md @@ -0,0 +1,61 @@ +## Chapter 11: 분산 워크플로 관리 + +### 개요 + +- 조정: 분산 아키텍처에서 도메인에 특정한 작업을 수행하고, 그와 관련된 부수적인 문제를 처리하기 위해 서비스를 조합하는 것 + +--- + +### 오케스트레이션 통신 스타일 + +- 오케스트레이터 (중재자) 를 이용하여 워크플로 상태나 에러, 알림 등을 관장 +- 복잡한 워크플로를 오케스트레이션을 통해 하나의 관리자가 전담하여 관리한다 +- 에러 조건 및 경로를 다루는 것이 가장 어려운데, 오케스트레이터는 각 트랜잭션을 관리함으로써 각 서비스의 상태와 에러 여부를 관장한다 +- 장점 + - 중앙화 워크플로: 상태와 동작을 통합한 컴포넌트 운용 + - 에러 처리 + - 복원성 + - 상태 관리 +- 단점 + - 응답성 + - 내고장성 + - 확장성 + - 서비스 커플링 + +``` +궁금증: ESB도 전역 오케스트레이터라는데, ESB는 서비스간 결합을 유도하기 때문에 오케스트레이션이랑 차이가 있다고 한다. 허나 그냥 오케스트레이터랑 ESB가 무엇이 다른지 이해가 안된다. 오케스트레이터 중 하나가 ESB라는게 아닌가? +``` + +--- + +### 코레오그래피 통신 스타일 + +- 중앙 조정을 하는 오케스트레이션과 달리, 각 서비스가 개별로 움직이는 스타일 +- 서로 통신하고 에러 처리도 한다 +- 허나 하나의 시나리오 진행 중에 서비스에서 오류가 발생할 경우, 이미 진행이 많이 되어 각 서비스를 거쳐간 상태이기 때문에 에러가 인지한 직후 이벤트를 생성해서 메시지를 브로드캐스팅해야 다른 서비스들이 볼 수 있다 +- 통신 경로가 많아질 수 밖에 없는 구조 +- 장점 + - 응답성, 확장성, 내고장성, 서비스 디커플링 + - 사실상 오케스트레이션과 반대됨 +- 단점 + - 분산된 워크플로 + - 상태 관리 + - 에러 처리 + - 복원성 + +### 워크플로 상태 관리 + +- 코레오그래피 통신 스타일에서는 워크플로의 상태를 관장하는 대장이 따로 없다 + - 위에 오케스트레이션 방식에서는 오케스트레이터가 직접 관장했음 +- 이 경우 상태를 관장하는 방법이 다음과 같다 + - 프론트 컨트롤러: 시나리오상 가장 먼저 호출된 서비스에게 책임을 맡기기 + - 무상태 코레오그래피: 각 서비스별 스냅샷을 구축하여 워크플로 전이 상태를 유지하지 않음 +- 스탬프 커플링: 서비스 간 전송되는 메시지 계약에 워크플로 상태를 같이 넣어서 전달 + +--- + +### 오케스트레이션 <-> 코레오그래피 간 트레이드오프 + +- 에러 빈도가 낮고, 에러 시나리오가 복잡하지 않으면 코레오그래피 + - 확장성 면에선 코레오그래피가 훨씬 편하다 +- 경계 조건과 에러 조건이 너무 복잡하면 오케스트레이션 From 0c5a856fff8e1e3d83966379b8fafc0b4d020d73 Mon Sep 17 00:00:00 2001 From: chichoon Date: Fri, 20 Mar 2026 18:51:16 +0900 Subject: [PATCH 3/9] feat: chapter 12 --- .../chichoon/11.md | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/11.md diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/11.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/11.md new file mode 100644 index 00000000..d4150f7f --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/11.md @@ -0,0 +1,155 @@ +## Chapter 12: 트랜잭셔널 사가 + +### 개요 + +- 사가 패턴: 각 업데이트가 완료되면 이벤트를 발행하고, 다음 업데이트를 실행시키는 릴레이 트랜잭션 +- 만약 업데이트들 중 하나라도 실패하면, 보상 트랜잭션을 가동시켜 이전 모든 변경사항을 무로 되돌린다 + +--- + +### 트랜잭셔널 사가 패턴 + +- 에픽 사가 +- 폰 태그 사가 +- 페어리테일 사가 +- 타임트래블 사가 +- 판타지 픽션 사가 +- 호러 스토리 사가 +- 패럴렐 사가 +- 앤솔로지 사가 +- 이름이 공식은 아니고 적당히 붙인듯 + +--- + +### 에픽 사가 + +- 오케스트레이티드 사가 라고도 함 +- 동기 통신 + 원자적 일관성 + 오케스트레이션 조정 +- 트랜잭션 중 하나의 호출이라도 실패할 경우, 모두 실패한 것으로 처리해 이전 상태로 되돌림 + - 성공 or 실패밖에 없다는 뜻 +- 보상 트랜잭션을 사용하여 구현 + - 분산 트랜잭션 도중 다른 서비스가 수행한 작업을 되돌리는 업데이트 + - 중재자는 요청 처리 성공여부를 모니터링하다가, 실패할 경우 다른 서비스를 보상호출 하여 중단 +- 높은 결합도 (복잡한 커플링) +- 높은 복잡도 + - 동기 호출이라 이에 대한 복잡도는 내려감 +- 응답성이 떨어짐 +- 이 패턴을 구현하기 위한 조정 및 병목은 확장성을 낮춤 + +--- + +### 폰 태그 사가 + +- 에픽 사가에서 사용하는 조정방식을 오케스트레이션 > 코레오그래피로 바꿈 + - 동기 + 원자성 + 코레오그래피 +- 텔레폰 게임 (한 사람이 다른 사람에게 비밀을 이야기하여 마지막 사람이 이를 맞추는 게임) 과 유사하여 이런 이름이 붙음 +- 오케스트레이터가 따로 없음 + - 따라서 각 서비스별로 책임 체인을 갖고 실패시 거슬러 올라갈 수 있어야 함 +- 결합도는 에픽 사가에 비해 약간 줄어듦 (코레오그래피이므로) + - 큰 차이는 없음 +- 에픽 사가보다 훨씬 복잡해짐 + - 오케스트레이터의 빈 자리를 채우기 위해 더 많은 로직이 각 서비스별로 들어가게 됨 +- 오케스트레이션이 없어졌으므로 응답성은 좋아짐 + - 허나 에러 처리에 더 많은 시간이 소요되므로 이 때문에 응답성이 낮아질 수 있음 +- 마찬가지로 오케스트레이션을 사용하지 않아 확장성이 아주 조금 좋아짐 + +--- + +### 페어리테일 사가 + +- 동기 + 최종일관성 + 오케스트레이션 +- 서비스가 잠시 중단되었을 경우, 최종 일관성을 통해 변경된 데이터를 일시 캐싱 +- 오케스트레이터가 존재는 하지만, 트랜잭션을 관리하지 않음 + - 요청, 응답, 에러처리만 + - 트랜잭션은 각 서비스가 알아서 관리 +- 동기 통신이라 이해하기 쉽고, 오케스트레이터가 있어 관리하기 쉬우며, 전체 트랜잭션이 없고 최종 일관성에 따라 서비스 각각이 수행하는 트랜잭션만 관리하면 됨 +- 결합도는 매우 높음 (동기 + 오케스트레이션) + - 단 트랜잭션이 최종 일관성으로 대체되어, 그에 따른 결합도는 약간 낮아짐 +- 복잡도가 매우 낮음 (최종일관성 + 오케스트레이션) + - 아주 간단한 조합으로만 만들어짐 +- 응답성 + - 동기 호출이지만 빠른 편 +- 확장성 + - 커플링 (결합도) 이 낮아 확장성도 좋음 + +--- + +### 타임 트래블 사가 + +- 동기 + 최종일관성 + 코레오그래피 +- 중재자가 없으므로 도메인 서비스들이 알아서 워크플로우를 관리해야 함 + - 요청을 받고, 작업 수행 후, 다음 서비스에 요청 전달 + - 각 단계가 한 방향으로, 하나의 시간적 흐름으로 순차적으로 흘러감 +- 트랜잭션이 없어 워크플로 모델링이 쉽지만, 오케스트레이터가 없으므로 각 서비스별로 워크플로 상태와 정보를 다 가지고 있어야 함 + - 워크플로가 복잡할 수록 오케스트레이터의 필요성이 증가 + - 따라서 워크플로가 단순할 때 타임트래블 사가가 적합하다 +- 결합도가 비교적 낮고 확장성이 좋음 +- 트랜잭션이 없어 복잡도가 낮음 +- 동기 호출을 사용하기 때문에 오버헤드가 발생하여 응답성은 약간 낮은 편 +- 확장성이 매우 좋음 + +--- + +### 판타지 픽션 사가 + +- 비동기 + 원자적 일관성 + 오케스트레이션 +- 에픽 사가와 비슷하지만, 비동기를 사용 + - 따라서 분산 트랜잭션을 병렬로 수행 + - 이 비동기성 때문에 중재자가 해야할 일도 복잡해진다 +- 오케스트레이터로 조정되는 워크플로가 비동기로 움직이는 것은 일을 더 복잡하게 만들기 쉽다 +- 비동기 통신 때문에 결합도는 매우 높음 => 복잡도도 높음 +- 다수의 호출에 의해 트랜잭션 조정이 이루어지므로, 하나 이상의 서비스가 실패하면 응답성도 수직 하락함 +- 트랜잭션 체제를 사용하므로 높은 확장성 얻기가 어려움 +- 단점만 잔뜩 있는데, 비동기 통신 하나로 에픽 사가의 단점을 상쇄할 수 있다는 믿음 때문에 많이 사용되는 편 + - 정말 별로라는 뜻 + +--- + +### 호러 스토리 사가 + +- 이름부터가 호러이다 +- 비동기, 원자적 일관성, 코레오그래피 사용 +- 원자적 일관성이라는 가장 엄격한 체제 아래 가장 느슨하게 만드는 비동기 통신과 코레오그래피가 어우러져 있는 매우 최악의 조합 +- 중재자가 없기 때문에, 각 서비스들은 비동기성 때문에 언제 어디서 어긋날지 모를 트랜잭션을 계속 추적하고 되돌릴 준비를 해야 한다 + - 하나의 트랜잭션 호출이 실패할 경우 해당 파트를 전부 되돌려야 하는데, 이 조건이 매우 까다롭기 때문에 에러 처리가 매우 어렵다고 할 수 있다 +- 결합도는 에픽 사가보단 낫다 (중재자를 사용하지 않으므로) +- 매우 복잡하다 +- 중재자 패턴이 아니므로 확장은 비교적 잘 된다 +- 서비스끼리 지속적으로 통신해야 하므로 좋지 않은 응답성 + +--- + +### 패럴렐 사가 + +- 비동기 통신, 최종 일관성, 오케스트레이션 +- 에픽 사가에서의 동기 통신에 기반된 트랜잭션 패턴은 성능 저하가 일어날 수밖에 없으므로, 이를 비동기와 최종일관성으로 보완 +- 중재자가 있으므로 복잡한 워크플로에 적합하다 +- 제약조건이 느슨한 대신, 각 단계에서 발생할 에러나 문제점을 중재자에 떠맡기므로, 이 부분에서의 타이밍 문제와 안정성이 떨어지게 된다 +- 결합도가 낮으면서 복잡도도 같이 낮다 +- 확장성이 매우 좋다 +- 비동기 통신 덕이 응답성도 좋다 + +--- + +### 앤솔로지 사가 + +- 에픽 사가의 정반대 +- 비동기 통신, 최종 일관성, 코레오그래피 + - 결합도가 낮을 수밖에 없는 요소 조합 +- 중앙 조정 기능이 없기 때문에 서비스는 복잡해지지만, 그 외의 특성 면에선 좋아진다 +- 단순하면서 선형적으로 진행되는 워크플로에 적합 + - 중앙조정 기능이 없기 때문에 단순한 워크플로에 적합한 것 + - 성능이 높아야 하고, 확장성도 추구한다면 가장 적합 +- 결합도가 매우 낮은 대신, 복잡도가 매우 높다 (코레오그래피 때문) +- 확장성, 탄력성은 결합도가 낮으므로 같이 낮음 +- 응답성 높음 + +--- + +### 상태 관리와 최종 일관성 + +- 상태 관리와 최종 일관성은 유한 상태 기계를 통해 현재 사가 상태를 파악하고 오류를 해결하는 방법 + - 사가 상태 기계: 분산 아키텍처에서 있을 법한 모든 가능한 경로를 기술하는 패턴 + - 각 상태가 변경될 때마다 수행할 액션과 전이 상태가 등장 + - 모든 상태 전이와 그에 해당하는 액션 목록을 정리하고, 이를 토대로 코드로 구현하는 것이 좋음 + - 사가 관리 기법: 상태들을 enum화 하고 트랜잭션을 클래스로 구현하는 것 같다 From 9fa0733a972f41f8c67cedb32187910d49b38ac3 Mon Sep 17 00:00:00 2001 From: chichoon Date: Fri, 20 Mar 2026 19:06:50 +0900 Subject: [PATCH 4/9] add chapter 13 --- .../chichoon/12.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md new file mode 100644 index 00000000..c2911c0d --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md @@ -0,0 +1,53 @@ +## Chapter 13: 계약 + +### 개요 + +- 계약: 종류가 다른 아키텍처 파트가 어떻게 연결될 것인지 정의한 것 + - 아키텍처의 거의 모든 부분에서 영향을 끼친다 +- 하드 파트 계약: 어떤 정보나 디펜던시를 전달하기 위해, 아키텍처의 각 파트에서 사용되는 포맷 +- 계약이란 곧 프레임워크와 라이브러리 간의 디펜던시, 통합점, 각 서비스간 통신 등 서로를 연결시키는 모든 기술들을 포괄하는 개념 + +--- + +### 엄격한 계약 vs 느슨한 계약 + +- 엄격한 계약: 이름, 타입, 순서 등 세부사항을 전부 준수하고, 모호한 부분을 남기지 않음 + - 단, 여러 아키텍처 파트에서 두루 쓰이면서 자주 변경되는 경우, 엄격한 계약에 취약점이 생길 수 있다 + - JSON 에 키, 값 쌍을 엄격하게 제한할 수 있다 +- 느슨한 계역: 커플링이 느슨한 경우 + - REST, 그래프QL 등 + - 다른 개발자가 하나의 리소스와 기능을구축하고 이 리소스를 확장한다고 해도, 특정 기능이 갑자기 문제가 생기지 않는 경우 +- 필요한 정보 외에도 갖은 정보들을 다 계약에 넣어버릴 경우, 취약점이 생기기 쉽다 + - 예를 들어, 고객의 위시리스트는 고객의 이름 식별자만 있으면 된다 + - 허나 고객의 성별, 나이 등의 정보까지 제공해버리면 안티패턴 + - 또한 해당 정보가 수정될 경우 계약이 깨지면서 위시리스트 기능까지 수정해야 할 수도 있다 +- 트레이드오프 + - 엄격한 계약 + - 계약 충실도 보장 (계약만으로 스키마 검증 가능) + - 버저닝 + - 장점이자 단점인데, 적절하지 못한 버저닝 (버전을 너무 많이 만들거나 너무 적게 만들기) 는 서비스를 더 복잡하게 만든다 + - 빌드 시 검증이 쉽다 + - 문서화하기 좋음 + - 커플링이 단단해짐 (한 쪽 변경하면 다른 쪽도 변경해야 함) + - 느슨한 계약 + - 높은 디커플링, 매우 유연함 + - 스키마 정보가 엄격하지 않으므로, 계약을 더 자유롭게 발전 가능 + - 계약 자체가 엄격하지 않으므로, 이름 - 값 쌍 누락 또는 철자 오류 등 결합이 발생할 여지가 큼 + - 피트니스 함수를 통해 느슨한 계약을 수행하는 데 필요한 정보가 모두 들어오는지 확인이 필요 +- 마이크로서비스에서는? + - 여러 서비스의 관계와 전달되는 정보, 결합도를 생각해야 한다 +- 컨슈머 주도 계약 + - 사용자가 서비스 제공자로부터 받고 싶은 정보를 계약에 넣고, 이를 토대로 빌드에 포함시켜 계약 테스트를 수행하는 기법 + - 필요에 따라 계약을 엄격하게 하거나, 느슨하게 할 수 있다 + - 자동 테스트로 테스트 가능하므로 이 부분에선 엄격할 수 있다 + - 단, 기술자가 이 절차들을 정확히 인지하고 지켜야 한다 + +--- + +### 스탬프 커플링 + +- 서비스 끼리 매우 큰 데이터를 주고받지만, 각 서비스는 그 데이터 안에서도 매우 작은 일부만 사용하는 경우 +- 위의 위시리스트 예시에서, 고객의 이름 (또는 ID) 만 있으면 되지만 모든 회원 정보를 전부 제공하는 경우? +- 데이터 때문에 계약에 과도한 커플링이 발생하면서, 전체 구조가 매우 취약해진다 +- 대역폭에 비해 너무 큰 데이터가 오고가면서 통신에 문제가 생길 수 있다 +- 코레오그래피 방식을 사용할 수 밖에 없는 경우, 스탬프 커플링을 이용하여 도메인 정보, 워크플로 상태를 계약에 넣어 전달하면 각 서비스는 이를 받아 계약 상태와 워크플로 상태를 업데이트하여 다음 서비스에 전달할 수 있다 From 440159523c61d5ca9efa0824a5b23aa4ebf9b34e Mon Sep 17 00:00:00 2001 From: chichoon Date: Fri, 20 Mar 2026 19:19:19 +0900 Subject: [PATCH 5/9] add chapter 14 --- .../chichoon/13.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/13.md diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/13.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/13.md new file mode 100644 index 00000000..e4459439 --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/13.md @@ -0,0 +1,47 @@ +## Chapter 14: 분석 데이터 관리 + +### 개요 + +- 운영 데이터와 분석 데이터를 분리하려면? + - 두 종류의 데이터는 용도가 완전히 다르므로 + +--- + +### 데이터 웨어하우스 + +- 모든 어플리케이션이 모놀리식일 때의 이야기 +- 데이터 웨어하우스 패턴을 통해 쿼리 가능한 분석 데이터를 제공하려고 했다 +- 운영 데이터들이 개별 데이터베이스들에 각각 들어있으므로, 이를 한번에 쿼리하고 분석값을 내놓는 것은 어렵기 때문에, 분석용 데이터는 웨어하우스로 추출 +- 데이터 웨어하우스는 데이터를 반정규화 하여 처리 속도를 높이고, 쿼리를 단순하게 한다 +- 각 디비별 내장 매커니즘을 사용하여 스키마를 웨어하우스용 스키마로 변환해야 하는데, 스키마가 변경되면 이걸 반복해야 하므로 변경 관리가 어렵다 +- 데이터가 웨어하우스에 머무르는 구조라, 모든 분석은 웨어하우스가 전담한다 + - 따라서 데이터 분석자도 데이터 웨어하우스를 바라보고 사용한다 + - 분석을 위해서는 도메인 지식이 필요 +- 단점 + - 통합 취약성: 특정 도메인 변경 시 관련 스키마도 함께 변경해야 한다 + - 웨어하우스 간에 온갖 데이터가 복잡하게 엮여있어, 이를 분석하기 위해 높은 도메인 지식과 모든 분야의 사람들이 달려들어서 분석과 데이터 변경을 도와야 한다 + - 대체 스키마 구축을 통해 시스템이 점점 복잡해진다 + - 아무튼 매우 복잡한 것에 비해 비즈니스적 가치는 떨어져서, 실패한 방식이 되었다 + - 유지보수도 매우 비쌌고, 병목 유발, 등등 + +--- + +### 데이터 레이크 + +- 데이터 웨어하우스의 중앙화 모델과 파이프라인은 그대로 +- 변환 후 적재 방식을, 적재 후 변환 방식으로 바꿈 + - 스키마 변환 필요성이 줄어들어, 데이터가 있는 그대로 저장됨 + - 이 데이터들을 분석가들이 필요한 형태로 가공하여 응답해주는 것 +- 이 중에서 필요한 데이터를 골라내기가 어렵다 +- 민감정보가 같이 저장되므로, 사생활 침해의 여지가 있다 +- 기술 분할에 초점을 둠 (요즘 대세는 도메인 분할) + +--- + +### 데이터 메시 + +- 분석 데이터를 탈중앙화 방식으로 접근하고 관리 +- 도메인 오너십: 각 데이터별로 출처가 되거나 일급 컨슈머가 되는 서비스들이 데이터를 소유하고 관리한다 +- 데이터를 프로덕트로 서비스하는 개념을 도입하였고, 데이터 프로덕트 퀀텀을 통해 데이터를 적절하게 찾아내고 이해하기 쉽게끔 관리한다 +- 도메인 팀이 데이터를 관리할 수 있는 셀프 서비스 플랫폼을 두고 있음 +- 데이터 프로덕트 퀀텀 From 59789f615b48531a4c6801901d605c243ebdca07 Mon Sep 17 00:00:00 2001 From: chichoon Date: Fri, 20 Mar 2026 19:57:58 +0900 Subject: [PATCH 6/9] add chapter 15 --- .../chichoon/14.md | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/14.md diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/14.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/14.md new file mode 100644 index 00000000..e98e08c4 --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/14.md @@ -0,0 +1,52 @@ +### Chapter 15: 자신만의 트레이드오프 분석 + +### 개요 + +- 책에서 살펴본 분산 아키텍처들과 각 트레이드오프를 고려하여 적재적소에 사용하는 스킬이 필요하겠다 +- 다음 3단계를 거침 + - 어느 파트가 서로 연관되어 있는지 확인 (연관된 차원 확인) + - 어떻게 서로 결합되어 있는지 확인 + - 상호 의존적 시스템의 변경 영향도 파악 후 트레이드오프 파악 + +--- + +### 서로 연관된 차원 확인 + +- 커플링 + - X를 변경하면 그 때문에 Y도 변경해야 할까? 를 생각하면 된다 +- 결합점 분석 + - 결합점을 식별하면, 각 특성들을 조합하여 적절한 아키텍처를 찾아내면 된다 + - 동기 / 비동기 여부, 일관성 방식, 오케스트레이션 / 코레오그래피 + - 결합도, 복잡도, 응답성 / 가용성, 확장성 / 탄력성 + - 각 패턴을 분석하고, 특성을 비교하면 몇 가지 특징이 보인다 + - 결합도와 확장성 / 탄력성은 반비례한다 + - 결합도가 높아질 수록 확장성은 떨어짐 + - 응답성 / 가용성과 결합도 또한 어느정도 반비례한다 + - 여러 차원을 조합해보면서 의미를 파악하기 위해, 경우의 수 매트릭스를 작성하는 것도 좋다 +- 트레이드오프 평가 + - if 시나리오를 반복하여 주어진 상황에서의 각 특성 선택 시 트레이드오프를 고민한다 + +### 트레이드오프 기법 + +- 정성적 분석 vs 정량적 분석 + - 각 표들은 전부 정성적 분석에 근거한 자료들이다 + - 대량의 데이터에 통계적 분석 기법을 동원하여 정량적 분석도 가능할 것 +- MECE 리스트 + - 상호 배제, 전체 포괄 + - 상호 배제: 비교 대상간 서로 기능이 겹치지 않아야 한다 + - 다른 부분은 무시하고 특정 기능만 비교한다는 전제가 있어야 함 + - 전체 포괄: 의사 결정 과정에서 모든 가능성을 짚어보고, 명백한 기능은 빠트리면 안됨 +- 콘텍스트 왜곡의 함정 + - 트레이드오프 검토 시에는 콘텍스트에 따라 의사 결정을 해야 한다 + - 그렇지 않으면 트레이드오프 분석 결과가 외부 요인에 막대한 영향을 받게 되므로 + - 분석 결과에 특정한 부가 콘텍스트가 결여되어 있다면, 실제 적용 시 무용지물이 된다 + - 의사 결정 콘텍스트를 정확하게 좁혀가면 아키텍트가 생각해야 할 것들이 줄고, 설계가 단순해진다 + - 만약에? 게임을 반복하여 아키텍처 차원간 영향을 꼼꼼히 고려해야 한다 +- 모델과 연관된 도메인 케이스 + - 도메인 동인을 추가하여 아키텍트가 가능한 방안을 걸러내고, 트레이드오프에 집중하는 데에 도움이 된다 +- 차고 넘치는 증거보다 한마디 결론이 낫다 + - 트레이드오프 분석에 온갖 정보를 수집하려고 하려는 사람이 있는데, 정보의 양 때문에 질이 묻힐 가능성이 있다 + - 중요한 핵심 주제로만 좁히는 것이 낫다 +- 터무니없는 말과 에반젤리즘은 금물 + - 어떠한 신기술이 좋아보인다고 해서 너무 매몰되지 말라는 뜻 + - 장점과 단점을 정직하게 평가한 자료를 이용하여 검토해야 한다 From fc5233da98b461ae44db37699587c3187e555608 Mon Sep 17 00:00:00 2001 From: chichoon Date: Fri, 20 Mar 2026 20:12:01 +0900 Subject: [PATCH 7/9] fix: review --- .../chichoon/09.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md index 37cda007..28827c8b 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md @@ -18,11 +18,14 @@ ### 복제 캐싱 패턴 - 데이터를 그대로 복사하여 새 테이블에 저장하는 것이 아니라, 대신 캐싱을 하는 방법 -- 캐시는 서비스별로 고유하게 저장되기 때문에 타 서비스와 공유되지 않음 (분산 캐싱) +- 캐시는 서비스별로 고유하게 저장되기 때문에 타 서비스와 공유되지 않음 +- 다른 캐싱 패턴 + - 단일 메모리 캐싱: 각 서비스별 고유 캐시 데이터를 가지고 있음 + - 분산 캐싱: 데이터를 외부 캐시 서버에 보관, 이 덕분에 서비스간 데이터 공유가 가능 + - 캐시 데이터는 중앙으로 공유되기 때문에, 타 서비스에서 데이터를 자유롭게 업데이트 할 수 있는 것은 그대로고, 경계 콘텍스트도 무너질 수 있다 + - 중앙 분산 캐시 (각 서비스별 캐시가 공유되는 위치) 는 원격 호출을 위해 접근해야 하므로 레이턴시가 늘어나는 것도 동일하다 + - 대신 위의 스키마 복제 패턴과 동일하게, 디펜던시만 이동했을 뿐 동기화 문제에서 자유롭지 않다 - 단점 - - 대신 위의 스키마 복제 패턴과 동일하게, 디펜던시만 이동했을 뿐 동기화 문제에서 자유롭지 않다 - - 캐시 데이터는 중앙으로 공유되기 때문에, 타 서비스에서 데이터를 자유롭게 업데이트 할 수 있는 것은 그대로고, 경계 콘텍스트도 무너질 수 있다 - - 중앙 분산 캐시 (각 서비스별 캐시가 공유되는 위치) 는 원격 호출을 위해 접근해야 하므로 레이턴시가 늘어나는 것도 동일하다 - 경우에 따라 복제 캐싱이 지원되지 않을 수 있다 - 장점 - 각 서비스별로 캐시를 갖고 있기 때문에 서로 간섭할 일이 없다 From f2da1a20806fdbf6f1557e3d1dd30587965c87bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=B5=9C=EC=A7=80=EC=9C=A4?= Date: Fri, 20 Mar 2026 20:12:27 +0900 Subject: [PATCH 8/9] Update 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../chichoon/12.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md index c2911c0d..9c3d8c44 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md @@ -14,7 +14,7 @@ - 엄격한 계약: 이름, 타입, 순서 등 세부사항을 전부 준수하고, 모호한 부분을 남기지 않음 - 단, 여러 아키텍처 파트에서 두루 쓰이면서 자주 변경되는 경우, 엄격한 계약에 취약점이 생길 수 있다 - JSON 에 키, 값 쌍을 엄격하게 제한할 수 있다 -- 느슨한 계역: 커플링이 느슨한 경우 +- 느슨한 계약: 커플링이 느슨한 경우 - REST, 그래프QL 등 - 다른 개발자가 하나의 리소스와 기능을구축하고 이 리소스를 확장한다고 해도, 특정 기능이 갑자기 문제가 생기지 않는 경우 - 필요한 정보 외에도 갖은 정보들을 다 계약에 넣어버릴 경우, 취약점이 생기기 쉽다 From c91283cb74e58e70bac6aef6eea340f53aff495b Mon Sep 17 00:00:00 2001 From: chichoon Date: Fri, 15 May 2026 17:05:53 +0900 Subject: [PATCH 9/9] =?UTF-8?q?fix:=20=ED=8C=8C=EC=9D=BC=20=EB=B2=88?= =?UTF-8?q?=ED=98=B8=20=EB=B0=80=EB=A0=A4=EC=93=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chichoon/00.md | 53 ----- .../chichoon/01.md | 83 +++---- .../chichoon/02.md | 68 +++--- .../chichoon/03.md | 86 +++----- .../chichoon/04.md | 135 +++++------- .../chichoon/05.md | 183 +++++++--------- .../chichoon/06.md | 129 ++++++++--- .../chichoon/07.md | 45 ++++ .../chichoon/09.md | 45 ---- .../chichoon/10.md | 86 +++----- .../chichoon/11.md | 180 ++++------------ .../chichoon/12.md | 202 +++++++++++++----- .../chichoon/13.md | 80 +++---- .../chichoon/14.md | 87 ++++---- .../chichoon/15.md | 52 +++++ 15 files changed, 757 insertions(+), 757 deletions(-) delete mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/00.md create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/07.md delete mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md create mode 100644 2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/15.md diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/00.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/00.md deleted file mode 100644 index 66e2dfdb..00000000 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/00.md +++ /dev/null @@ -1,53 +0,0 @@ -## Chapter 01: 베스트 프랙티스가 없다면? - -### 개요 - -- 개발자: 좀 더 기술적인 분야를 다룸, 라이브러리를 활용해서 문제를 어떻게 해결할 것인지? 에 초점인듯 - - 소프트웨어의 좀 더 세부적인 범위를 작업 -- 아키텍트: 하나의 제품 (소프트웨어) 에서 전체적인 흐름을 설계하고 구조를 잡아내는 기술자 - - 소프트웨어의 큰 흐름을 주도 -- 소프트웨어 아키텍트의 경우 시대의 흐름이나 트렌드에 따라 고려해야 할 점이 지속적으로 변화하고 각 구조별 장단점이 극명하므로, 개발에는 최선이 있을 수 있으나 아키텍트는 그러기 어려움 - - 최고의 설계를 고집하기보단 상황에 맞는 최적의 설계를 고려하는 것이 좋다 - - 하나의 아키텍처를 바라볼 땐 특히나 그 아키텍처가 대세가 되었을 때의 시대적 배경을 고려해야 함 - - 옛날에는 중앙 집중식 체제가 강세였다면, 오픈소스의 대두와 함께 요즘은 마이크로서비스 인프라를 쉽게 구축할 수 있게 된 것처럼 - -``` -논의점: 오픈소스 혁명처럼, 2023년경 챗지피티를 필두로 한 LLM 인공지능의 범람으로 새로운 패러다임이 또 등장하고 있진 않을까? AI와 아키텍처를 긴밀하게 엮을 수 있다면 어떤 부분이 있을지? -``` - -### 데이터 - -- 데이터는 아키텍처를 넘어서서, 소프트웨어의 모든 것이라고 볼 수 있음 - - 어떻게 하면 특정 데이터를 효율적, 효과적으로 다룰 수 있는지가 소프트웨어의 목표라고 할 수 있음? - - 수익과 직결 - - 운영 데아터: 비즈니스 활동에 사용되는 데이터 (소비자와 직접적으로 연결) - - 분석 데이터: 제품의 전략을 짜거나 의사결정을 할 때 큰 영향을 미치는, 통계적이고 분석적인 데이터 - -### ADR - -- 아키텍처 결정을 문서화할 때 ADR (아키텍처 결정 레코드) 활용 - - 문제와 대안 열거 - - 확정된 아키텍처와 그 이유 - - 해당 아키텍처를 적용했을 때 예상 결과와 고려해야 할 트레이드오프 - -### 피트니스 함수 - -- 피트니스 함수 - - 아키텍처가 정상적으로 도입되었고 그에 따라 적절히 개발되고 있는지 평가할 수 있는 함수 - - 계층별로 적절한 데이터를 주고받는지, 계층이나 객체 간 적절한 방법으로 데이터를 주고받는지 등등... - - 개발자들이 아키텍처를 정확하게 이해하고 있지 않거나, 자동화 도구를 사용할 때 발생하는 부작용 등을 방지 - -``` -논의점: 피트니스 함수 등 아키텍처 테스트를 위한 도구를 적절하게 도입한 예시가 있을지? 일단 저희 팀은 모르겠습니다. 별도의 도구 없이 개발자들 간의 합의와 믿음으로 진행되는듯. -단순 유닛 테스트 기반 CI/CD 자동화도 아키텍처 테스트 도구라고 볼 수 있을지? '아키텍처가 흐트러지는 것을 방지하는' 피트니스 함수의 범위는 어디까지일까? -``` - -### 아키텍처 vs 설계 - -- 아키텍트는 소프트웨어의 상세 구현보다는 전체적인 흐름에서의 구조를 보려고 함 -- 아키텍처를 도입할 땐 왜? 라는 질문을 지속적으로 던져야 하는 듯 - - 왜 이러한 구조를 도입했는지, 왜 이것이 최적으로 여겨지는지, 도입했을 때 부작용은 왜? 어떤 부분에서 발생할지? 등... - -``` -논의점?: FE 관점으로 봤을 때, 폴더 구조, 페이지 및 컴포넌트 간의 데이터 흐름도 (소프트웨어 전체에서 봤을 때) 미시적 측면에서의 아키텍처에 영향받는 부분으로 볼 수 있을까? (위의 논의점과 연관되는듯) -``` diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/01.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/01.md index 8cb19040..66e2dfdb 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/01.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/01.md @@ -1,44 +1,53 @@ -# 따로 떼어놓기 - -## Chapter 02: 아키텍처 퀀텀 +## Chapter 01: 베스트 프랙티스가 없다면? ### 개요 -- 개발은 라이브러리 문서, 최적의 알고리즘 등 다양한 베스트 프랙티스가 존재하지만, 아키텍처는 명확한 가이드가 없기 때문에 특정 아키텍처를 도입하려고 해도 세부적인 면을 파고들었을 때 난관에 봉착하기도 함 -- 겉보기에는 우리 소프트웨어에 적절히 도입할 수 있을 것 같았는데, 막상 도입하려고 보니 다음과 같은 요소들이 눈에 띄는 것 - - 현재 구현된 소프트웨어에 아키텍처를 끼워맞추려 할 때 봉착하는 문제점 - - 미래에 높은 확률로 예상되는 부작용 - - 한빛전자 아키텍트들이 무조건적인 디커플링만으론 데이터 통신 시의 문제를 염두에 두는 것과 같음 -- 무작정 좋아 보인다고 해서 바로 가져다 쓸 수 있는 게 없다 -- 마이크로서비스가 대세가 되면서 소프트웨어의 복잡도가 늘어났고, 아키텍트들의 의사 결정을 더 까다롭게 만들었다 - - 마이크로서비스 아키텍처는 하나의 큰 어플리케이션을 독립적이고 작은 서비스들의 집합으로 분할하여 개발하는 스타일 - - 온갖 관심사들이 하나의 소프트웨어에 뭉쳐지면서 요소 파악이 어려워지고 구조가 복잡해졌기 때문 - - 독립적인 서비스를 어느 정도의 크기로 쪼갤 것인지부터 고려해야 함 -- 복잡한 서비스에서는 내부적으로 서로 얽혀 있는 부분 (커플링) 을 파악하고, 변경을 가했을 때의 영향을 고려하여 트레이드오프를 분석 - -### 아키텍처 퀀텀 - -- 아키텍처 퀀텀: 독립적으로 분리 및 배포가 가능한 하나의 서비스 집합체 - - 마이크로서비스 아키텍처가 잘 도입되었다는 전제하에, 각 서비스들을 아키텍처 퀀텀으로 볼 수 있다 - - 적절히 구성된 아키텍처 퀀텀은 제품과 그 흐름을 효과적으로 이해하고, 각 부서간 소통에 도움을 준다 - - 아무리 서비스가 잘 격리되어 있어도 각 서비스들이 하나의 데이터베이스를 같이 바라볼 경우 독자적인 아키텍처 퀀텀으로 여기지 않는다 - - 퀀텀이 데이터베이스를 통해서 데이터를 주고받으면 안됨, 각 퀀텀간에는 별도의 통신이 필요 (비동기 통신 등) - - 하나의 사용자 인터페이스를 여러 서비스들이 공유해도 안됨 - - 하나의 사용자 인터페이스 내에서 독자적으로 운용되는 컴포넌트들을 각각 바라볼 경우 아키텍처 퀀텀으로 분류할 수 있음 +- 개발자: 좀 더 기술적인 분야를 다룸, 라이브러리를 활용해서 문제를 어떻게 해결할 것인지? 에 초점인듯 + - 소프트웨어의 좀 더 세부적인 범위를 작업 +- 아키텍트: 하나의 제품 (소프트웨어) 에서 전체적인 흐름을 설계하고 구조를 잡아내는 기술자 + - 소프트웨어의 큰 흐름을 주도 +- 소프트웨어 아키텍트의 경우 시대의 흐름이나 트렌드에 따라 고려해야 할 점이 지속적으로 변화하고 각 구조별 장단점이 극명하므로, 개발에는 최선이 있을 수 있으나 아키텍트는 그러기 어려움 + - 최고의 설계를 고집하기보단 상황에 맞는 최적의 설계를 고려하는 것이 좋다 + - 하나의 아키텍처를 바라볼 땐 특히나 그 아키텍처가 대세가 되었을 때의 시대적 배경을 고려해야 함 + - 옛날에는 중앙 집중식 체제가 강세였다면, 오픈소스의 대두와 함께 요즘은 마이크로서비스 인프라를 쉽게 구축할 수 있게 된 것처럼 + +``` +논의점: 오픈소스 혁명처럼, 2023년경 챗지피티를 필두로 한 LLM 인공지능의 범람으로 새로운 패러다임이 또 등장하고 있진 않을까? AI와 아키텍처를 긴밀하게 엮을 수 있다면 어떤 부분이 있을지? +``` + +### 데이터 + +- 데이터는 아키텍처를 넘어서서, 소프트웨어의 모든 것이라고 볼 수 있음 + - 어떻게 하면 특정 데이터를 효율적, 효과적으로 다룰 수 있는지가 소프트웨어의 목표라고 할 수 있음? + - 수익과 직결 + - 운영 데아터: 비즈니스 활동에 사용되는 데이터 (소비자와 직접적으로 연결) + - 분석 데이터: 제품의 전략을 짜거나 의사결정을 할 때 큰 영향을 미치는, 통계적이고 분석적인 데이터 + +### ADR + +- 아키텍처 결정을 문서화할 때 ADR (아키텍처 결정 레코드) 활용 + - 문제와 대안 열거 + - 확정된 아키텍처와 그 이유 + - 해당 아키텍처를 적용했을 때 예상 결과와 고려해야 할 트레이드오프 + +### 피트니스 함수 + +- 피트니스 함수 + - 아키텍처가 정상적으로 도입되었고 그에 따라 적절히 개발되고 있는지 평가할 수 있는 함수 + - 계층별로 적절한 데이터를 주고받는지, 계층이나 객체 간 적절한 방법으로 데이터를 주고받는지 등등... + - 개발자들이 아키텍처를 정확하게 이해하고 있지 않거나, 자동화 도구를 사용할 때 발생하는 부작용 등을 방지 ``` -논의점? 궁금증?: '독자적으로 배포 가능한 서비스 집합' 이 아키텍처 퀀텀이기 때문에 데이터베이스 or 사용자 인터페이스가 분리되어 있지 않고 하나의 DB에 모든 서비스가 접근할 경우 아키텍처 퀀텀으로 볼 수 없다고 이해하면 되는 것일지? 2개 이상의 아키텍처 퀀텀들로 구성된 서비스의 예시가 무엇이 있을까 +논의점: 피트니스 함수 등 아키텍처 테스트를 위한 도구를 적절하게 도입한 예시가 있을지? 일단 저희 팀은 모르겠습니다. 별도의 도구 없이 개발자들 간의 합의와 믿음으로 진행되는듯. +단순 유닛 테스트 기반 CI/CD 자동화도 아키텍처 테스트 도구라고 볼 수 있을지? '아키텍처가 흐트러지는 것을 방지하는' 피트니스 함수의 범위는 어디까지일까? ``` -### 퀀텀 커플링 트레이드오프 - -- 기능 응집도: 구성 요소들이 비슷한 도메인과 구조로 잘 결합되어 있는지 - - 모놀리식 (소프트웨어가 하나의 구조? 서비스? 로 이루어져 있는 아키텍처) 의 경우 응집도가 매우 낮다 - - 높은 정적 커플링 -- 통신: 서비스 간 데이터 주고받는 방식, 동기 | 비동기가 있음 - - 동기적 통신은 송신자가 수신자의 응답을 대기함 - - 비동기적 통신은 송신자가 응답과 관계없이 하던 일을 계속함 (ACK 시그널 정도만 받는듯) -- 일관성: 통신 시의 무결성 엄격함 -- 조정: 통신 방식을 도입한 워크플로에서의 조정 필요성 -- 통신, 일관성, 조정은 서로 영향을 주고받으므로 한 쪽을 택하면 다른 쪽으로 트레이드오프가 발생한다 - - 아키텍처 선택 시 중요한 지표 +### 아키텍처 vs 설계 + +- 아키텍트는 소프트웨어의 상세 구현보다는 전체적인 흐름에서의 구조를 보려고 함 +- 아키텍처를 도입할 땐 왜? 라는 질문을 지속적으로 던져야 하는 듯 + - 왜 이러한 구조를 도입했는지, 왜 이것이 최적으로 여겨지는지, 도입했을 때 부작용은 왜? 어떤 부분에서 발생할지? 등... + +``` +논의점?: FE 관점으로 봤을 때, 폴더 구조, 페이지 및 컴포넌트 간의 데이터 흐름도 (소프트웨어 전체에서 봤을 때) 미시적 측면에서의 아키텍처에 영향받는 부분으로 볼 수 있을까? (위의 논의점과 연관되는듯) +``` diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/02.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/02.md index a1344174..8cb19040 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/02.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/02.md @@ -1,40 +1,44 @@ # 따로 떼어놓기 -## Chapter 03: 아키텍처 모듈성 +## Chapter 02: 아키텍처 퀀텀 ### 개요 -- 아키텍처는 소프트웨어의 근간을 다루지만, 막상 시장이 변화하고 기술이 발전함에 따라 구조부터 다시 짜야 하는 경우가 많다 - - 옛날엔 모놀리식이 유행하다가도 지금은 마이크로서비스가 유행하는 것처럼 - - 모놀리식 시스템의 경우에는 확장이 어렵기 때문에 변화에 대처하기가 힘듦 - - 물컵 예시: 같은 양의 물을 여러 컵에 나눠 담으면, 각 컵은 물을 추가로 담을 수 있기 때문에 확장성 면에서 유연하다 - - 하지만 오선빈의 예처럼, 그럴 듯한 이유 없이 무작정 쪼개려고만 해서는 제품의 상위 담당자를 설득시키기 어렵다 - - 큰 아키텍처를 갑자기 한번에 바꾸려고 시도하기보다는 아키텍처 또한 시대의 변화에 민첩하게 따르는 것이 적절하다 - -### 모듈화 동인 - -- 동인: 움직이게 만드는 계기? - - 오선빈이 상사를 어떻게 잘 설득시킬 수 있을지 여기서 엿볼 수 있음 -- 시장에서 우위를 점하기 위한 아키텍처 특성: 가용성, 확장성, 배포성, 시험성, 유지보수성 - - 이 중 몇몇은 모놀리식 아키텍처에서도 충분히 달성가능 -- 유지보수성: 기능의 추가, 변경, 삭제 및 코드 내부적 변경이 얼마나 쉽게 달성 가능한지의 여부 - - 컴포넌트간 결합도가 높을 수록, 유지보수성은 낮아진다 - - 하나의 컴포넌트만 수정하려 해도 다른 컴포넌트 (또는 어플리케이션 전체) 를 손봐야 하므로 - - 아키텍처 전체에 같은 도메인이 흩어져있는 경우가 많기 때문에 도메인별 관리 또한 어렵다 - - 마이크로서비스 아키텍처처럼 모듈화를 적절히 수행했을 경우 변경이 필요한 서비스의 컴포넌트만 수정하면 나머지는 영향이 없다 -- 시험성: 테스트의 완전성과 용이함 - - 작은 컴포넌트 하나의 변경점 때문에 더 큰 컴포넌트 또는 어플리케이션 전체에 테스트를 수행해야 할 경우, 수고로움이 클 것이다 - - 모듈화를 통해 필요한 테스트의 범위를 좁히고 관리를 수월하게 할 수 있음 -- 배포성: 배포의 용이함 (낮은 리스크, 배포에 필요한 작업이 적음) -- 확장성: 부하가 증가해도 시스템에 오류가 발생하지 않고 부하를 감당가능한 정도 - - 확장성은 제품이 서비스되는 기간이 길어짐에 따라 사용자 수가 점점 증가해도 시스템이 응답을 유지함 - - 탄력성은 갑자기 짧은 기간 내에 사용자 수가 폭증하고 사그라드는 것을 반복해도 시스템이 응답을 유지함 - - 확장성이 조금 더 모듈화와 관련이 깊다 > 구조의 덩치가 작을 수록 이것저것 붙이기도 쉽고 구조별 목적이 정확하기 때문에 확장이 용이 -- 가용성 (내고장성): 시스템의 특정 부분이 고장나도 나머지 부분은 정상적으로 작동하는 능력 - - 모놀리식은 내고장성에 매우 취약하다 - - 도메인 분리가 되어있지 않고 각 컴포넌트가 강결합 되어있어 하나의 구조에서 오류가 발생하면 다른 곳에서도 오류가 발생할 확률이 높음 - - 모듈화를 통해 특정 배포 단위에서만 버그가 발생하도록 제한하여 다른 모듈에서는 오작동을 막을 수 있다 +- 개발은 라이브러리 문서, 최적의 알고리즘 등 다양한 베스트 프랙티스가 존재하지만, 아키텍처는 명확한 가이드가 없기 때문에 특정 아키텍처를 도입하려고 해도 세부적인 면을 파고들었을 때 난관에 봉착하기도 함 +- 겉보기에는 우리 소프트웨어에 적절히 도입할 수 있을 것 같았는데, 막상 도입하려고 보니 다음과 같은 요소들이 눈에 띄는 것 + - 현재 구현된 소프트웨어에 아키텍처를 끼워맞추려 할 때 봉착하는 문제점 + - 미래에 높은 확률로 예상되는 부작용 + - 한빛전자 아키텍트들이 무조건적인 디커플링만으론 데이터 통신 시의 문제를 염두에 두는 것과 같음 +- 무작정 좋아 보인다고 해서 바로 가져다 쓸 수 있는 게 없다 +- 마이크로서비스가 대세가 되면서 소프트웨어의 복잡도가 늘어났고, 아키텍트들의 의사 결정을 더 까다롭게 만들었다 + - 마이크로서비스 아키텍처는 하나의 큰 어플리케이션을 독립적이고 작은 서비스들의 집합으로 분할하여 개발하는 스타일 + - 온갖 관심사들이 하나의 소프트웨어에 뭉쳐지면서 요소 파악이 어려워지고 구조가 복잡해졌기 때문 + - 독립적인 서비스를 어느 정도의 크기로 쪼갤 것인지부터 고려해야 함 +- 복잡한 서비스에서는 내부적으로 서로 얽혀 있는 부분 (커플링) 을 파악하고, 변경을 가했을 때의 영향을 고려하여 트레이드오프를 분석 + +### 아키텍처 퀀텀 + +- 아키텍처 퀀텀: 독립적으로 분리 및 배포가 가능한 하나의 서비스 집합체 + - 마이크로서비스 아키텍처가 잘 도입되었다는 전제하에, 각 서비스들을 아키텍처 퀀텀으로 볼 수 있다 + - 적절히 구성된 아키텍처 퀀텀은 제품과 그 흐름을 효과적으로 이해하고, 각 부서간 소통에 도움을 준다 + - 아무리 서비스가 잘 격리되어 있어도 각 서비스들이 하나의 데이터베이스를 같이 바라볼 경우 독자적인 아키텍처 퀀텀으로 여기지 않는다 + - 퀀텀이 데이터베이스를 통해서 데이터를 주고받으면 안됨, 각 퀀텀간에는 별도의 통신이 필요 (비동기 통신 등) + - 하나의 사용자 인터페이스를 여러 서비스들이 공유해도 안됨 + - 하나의 사용자 인터페이스 내에서 독자적으로 운용되는 컴포넌트들을 각각 바라볼 경우 아키텍처 퀀텀으로 분류할 수 있음 ``` -느낀점: FE 관점이긴 하지만 최근에 레거시 코드를 들어내면서 (하나의 큰 화면 컴포넌트가 모든 기능을 담당하고 있었음) 컴포넌트의 관심사를 분리하여 작은 단위로 쪼개는 작업을 했었는데, 그래서 그런지 가용성과 시험성, 유지보수성 측면에서 예시에 공감이 많이 갔음. 허나 FE 하나의 파트에서도 컴포넌트 모듈화는 쉽지 않은 작업이었는데 하나의 제품 단위에서는 얼마나 많은 공수가 필요할지. +논의점? 궁금증?: '독자적으로 배포 가능한 서비스 집합' 이 아키텍처 퀀텀이기 때문에 데이터베이스 or 사용자 인터페이스가 분리되어 있지 않고 하나의 DB에 모든 서비스가 접근할 경우 아키텍처 퀀텀으로 볼 수 없다고 이해하면 되는 것일지? 2개 이상의 아키텍처 퀀텀들로 구성된 서비스의 예시가 무엇이 있을까 ``` + +### 퀀텀 커플링 트레이드오프 + +- 기능 응집도: 구성 요소들이 비슷한 도메인과 구조로 잘 결합되어 있는지 + - 모놀리식 (소프트웨어가 하나의 구조? 서비스? 로 이루어져 있는 아키텍처) 의 경우 응집도가 매우 낮다 + - 높은 정적 커플링 +- 통신: 서비스 간 데이터 주고받는 방식, 동기 | 비동기가 있음 + - 동기적 통신은 송신자가 수신자의 응답을 대기함 + - 비동기적 통신은 송신자가 응답과 관계없이 하던 일을 계속함 (ACK 시그널 정도만 받는듯) +- 일관성: 통신 시의 무결성 엄격함 +- 조정: 통신 방식을 도입한 워크플로에서의 조정 필요성 +- 통신, 일관성, 조정은 서로 영향을 주고받으므로 한 쪽을 택하면 다른 쪽으로 트레이드오프가 발생한다 + - 아키텍처 선택 시 중요한 지표 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/03.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/03.md index 6e44ec14..a1344174 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/03.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/03.md @@ -1,58 +1,40 @@ -## Chapter 04: 아키텍처 분해 +# 따로 떼어놓기 -### 개요 - -- 컴포넌트 기반 분해 - - 어플리케이션의 논리적 구성 요소 단위 (컴포넌트 단위) 를 추출하고 이를 이용하여 아키텍처를 구성 - - 코드베이스가 컴포넌트 단위로 구성되어 있어 분해 가능할 경우 이쪽 선택 -- 전술적 분기 - - 애플리케이션 사본을 복사하고 필요없는 부분을 깎아내며 구성 - - 코드베이스 분해 불가능할 경우 (엉망일 경우) 이쪽이 적절한 선택 -- 도구를 이용하여 코드베이스의 특성을 파악하고 구조를 판별 - -### 추상도와 불안정도 - -- 코드베이스의 균형을 나타내는 척도 -- 추상도 - - 구현 대비 추상화가 이뤄진 정도 - - 추상 요소와 구상 요소의 개수로 측정한다 -- 불안정도 - - 코드베이스가 불안정한 정도 - - 커플링 (구심, 원심) 이 높을 경우 불안정도가 올라감 - - 컴포넌트끼리 강하게 엮여 있어 하나를 수정하면 다른 컴포넌트에 영향을 미칠 확률이 높다는 뜻 +## Chapter 03: 아키텍처 모듈성 -![image03-01](./images/03_01.png) - -- 메인 시퀀스로부터의 거리 - - 추상도와 불안정도 사이의 이상적인 관계 - - x절편, y절편, 기울기 1의 직선 - - 이 선에 가까울수록 이상적이다 (컴포넌트 균형이 적절하다) -- 메인 시퀀스로부터의 거리 그래프 기준으로 - - 오른쪽 위로 치우친 부분은 추상화가 과도한 (쓸모없는) 구역 - - 사용이 어려움 - - 왼쪽 아래로 치우친 부분은 추상화가 없다시피한 (고통스러운) 구역 - - 취약하고 관리가 어려움 - -``` -논의점: 추상도, 불안정도, 거리 등의 요소가 굉장히 수학적인 요소로 보이는데, 개발에는 정답이 없듯이 컴포넌트가 추상적인지, 불안정한지 여부를 판가름하는 기준도 매우 모호할 듯하다. 추상 클래스 등 명확하게 추상적인 요소가 없는 경우 이러한 수치들을 계산하고, 아키텍처 구성에 참고할 만한 자료로 삼는 것이 과연 가능할까 의문이 든다. -``` - -### 컴포넌트 기반 분해 - -- 컴포넌트 단위의 폴더구조 및 파일로 디렉터리를 구성 및 각 코드 분리 -- 모놀리식을 분산 아키텍처로 마이그레이션할 때 도움이 된다 - -### 전술적 분기 +### 개요 -- 진흙잡탕 아키텍처를 다듬을 때, 추출보다는 필요없는 것을 떼어내는 것에 중점 -- 서로간의 의존성 때문에 추출에 한계가 있는 경우 -- A팀, B팀이 서로 각각 코드베이스 사본을 복사한 후, 각자의 팀에 필요한 코드만 남기고 나머지를 삭제하는 기법 - - 이렇게 하면 각 파트별 큰 구조는 유지하면서 모놀리식 구조를 덩어리로 쪼갤 수 있다 -- 분해보다 상대적으로 쉽지만 모놀리스 코드의 흔적이 계속 남아있을 가능성이 있다 -- 개발자가 노력을 기울이지 않으면, 조금 더 가벼워졌을 뿐인 (코드 용량만 줄어든) 진흙덩어리가 될 수도 있음 +- 아키텍처는 소프트웨어의 근간을 다루지만, 막상 시장이 변화하고 기술이 발전함에 따라 구조부터 다시 짜야 하는 경우가 많다 + - 옛날엔 모놀리식이 유행하다가도 지금은 마이크로서비스가 유행하는 것처럼 + - 모놀리식 시스템의 경우에는 확장이 어렵기 때문에 변화에 대처하기가 힘듦 + - 물컵 예시: 같은 양의 물을 여러 컵에 나눠 담으면, 각 컵은 물을 추가로 담을 수 있기 때문에 확장성 면에서 유연하다 + - 하지만 오선빈의 예처럼, 그럴 듯한 이유 없이 무작정 쪼개려고만 해서는 제품의 상위 담당자를 설득시키기 어렵다 + - 큰 아키텍처를 갑자기 한번에 바꾸려고 시도하기보다는 아키텍처 또한 시대의 변화에 민첩하게 따르는 것이 적절하다 + +### 모듈화 동인 + +- 동인: 움직이게 만드는 계기? + - 오선빈이 상사를 어떻게 잘 설득시킬 수 있을지 여기서 엿볼 수 있음 +- 시장에서 우위를 점하기 위한 아키텍처 특성: 가용성, 확장성, 배포성, 시험성, 유지보수성 + - 이 중 몇몇은 모놀리식 아키텍처에서도 충분히 달성가능 +- 유지보수성: 기능의 추가, 변경, 삭제 및 코드 내부적 변경이 얼마나 쉽게 달성 가능한지의 여부 + - 컴포넌트간 결합도가 높을 수록, 유지보수성은 낮아진다 + - 하나의 컴포넌트만 수정하려 해도 다른 컴포넌트 (또는 어플리케이션 전체) 를 손봐야 하므로 + - 아키텍처 전체에 같은 도메인이 흩어져있는 경우가 많기 때문에 도메인별 관리 또한 어렵다 + - 마이크로서비스 아키텍처처럼 모듈화를 적절히 수행했을 경우 변경이 필요한 서비스의 컴포넌트만 수정하면 나머지는 영향이 없다 +- 시험성: 테스트의 완전성과 용이함 + - 작은 컴포넌트 하나의 변경점 때문에 더 큰 컴포넌트 또는 어플리케이션 전체에 테스트를 수행해야 할 경우, 수고로움이 클 것이다 + - 모듈화를 통해 필요한 테스트의 범위를 좁히고 관리를 수월하게 할 수 있음 +- 배포성: 배포의 용이함 (낮은 리스크, 배포에 필요한 작업이 적음) +- 확장성: 부하가 증가해도 시스템에 오류가 발생하지 않고 부하를 감당가능한 정도 + - 확장성은 제품이 서비스되는 기간이 길어짐에 따라 사용자 수가 점점 증가해도 시스템이 응답을 유지함 + - 탄력성은 갑자기 짧은 기간 내에 사용자 수가 폭증하고 사그라드는 것을 반복해도 시스템이 응답을 유지함 + - 확장성이 조금 더 모듈화와 관련이 깊다 > 구조의 덩치가 작을 수록 이것저것 붙이기도 쉽고 구조별 목적이 정확하기 때문에 확장이 용이 +- 가용성 (내고장성): 시스템의 특정 부분이 고장나도 나머지 부분은 정상적으로 작동하는 능력 + - 모놀리식은 내고장성에 매우 취약하다 + - 도메인 분리가 되어있지 않고 각 컴포넌트가 강결합 되어있어 하나의 구조에서 오류가 발생하면 다른 곳에서도 오류가 발생할 확률이 높음 + - 모듈화를 통해 특정 배포 단위에서만 버그가 발생하도록 제한하여 다른 모듈에서는 오작동을 막을 수 있다 ``` -느낀점?: 마침 아주 최근에 큰 덩어리의 진흙 코드를 서비스별로 분기하는 작업을 진행했는데, 그 과정에서 덩어리를 서비스별로 복사하고 그중 필요없는 코드를 지우고 공통화할 수 있는 코드만 분리하여 덩어리를 경량화한 적이 있었음. 전술적 분기 파트를 읽으면서 해당 작업 생각이 났다. (내가 진행한 작업이 어찌보면 전술적 분기구나? 하는) - -난이도는 확실히 처음부터 작정하고 분리를 시도하는 것보다 간단한 편이고 시간도 많이 걸리지 않았지만, 덩어리 A를 분리하고 나서 덩어리 B를 작업하는 도중에 덩어리 A에 미처 덜어내지 못한 찌꺼기를 발견하는 등 코드 깎아내기에 어느 정도 익숙하지 않으면 실수하기가 쉬운 듯 하다. A 덩어리는 C, D, E 서비스를 분기할 때까지도 찌꺼기와 공통화가 덜된 요소들이 계속 발견되어 추가작업을 진행해야 했다.. 눈물.. +느낀점: FE 관점이긴 하지만 최근에 레거시 코드를 들어내면서 (하나의 큰 화면 컴포넌트가 모든 기능을 담당하고 있었음) 컴포넌트의 관심사를 분리하여 작은 단위로 쪼개는 작업을 했었는데, 그래서 그런지 가용성과 시험성, 유지보수성 측면에서 예시에 공감이 많이 갔음. 허나 FE 하나의 파트에서도 컴포넌트 모듈화는 쉽지 않은 작업이었는데 하나의 제품 단위에서는 얼마나 많은 공수가 필요할지. ``` diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/04.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/04.md index 606a7227..6e44ec14 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/04.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/04.md @@ -1,83 +1,58 @@ -## Chapter 05: 컴포넌트 기반 분해 패턴 +## Chapter 04: 아키텍처 분해 ### 개요 -![04_01](./images/04_01.png) - -1. 컴포넌트 식별 및 사이징 - - 나눌 컴포넌트의 크기를 결정 -2. 공통 도메인을 갖는 컴포넌트 수집 - - 중복 가능성이 있는 로직 통합 -3. 컴포넌트 눌러펴기 - - 도메인, 서브도메인, 컴포넌트를 정리 -4. 컴포넌트 디펜던시 결정 - - 디펜던시를 다듬어 마이그레이션 실현가능성 및 작업량 결정 -5. 컴포넌트 도메인 생성 - - 컴포넌트를 애플리케이션 내부의 논리적 도메인들로 그룹핑 및 리팩터링 -6. 도메인 서비스 생성 - - 모놀리식 애플리케이션의 논리 도메인을 개별 배포된 도메인 서비스들로 이동 - - 모놀리식을 서비스 단위로 쪼개기 - -### 컴포넌트 식별 및 사이징 - -- 애플리케이션을 구성하는 컴포넌트를 식별하여 크기를 조절 -- 너무 크거나 너무 작은 컴포넌트를 찾아내는 작업 - - 큰 컴포넌트의 경우 다른 컴포넌트들과의 결합도가 높을 가능성이 높다 -- 컴포넌트 크기를 결정하는 지표 - - 문장 수 (조건문, 분기문 등, 세미콜론으로 구분) - - 파일 수 - - 이러한 수치들을 이용하여 컴포넌트의 비중 계산 - - 컴포넌트 사이즈를 일정하게 유지하기 위해 피트니스 함수나 툴을 쓰면 좋다 - - 어떤 컴포넌트가 추가되고 삭제되었는지 알려주는 툴 - - 코드베이스에서 차지하는 비중을 나타내고 임계치를 벗어나지 않게끔 돕는 툴 - - 컴포넌트가 코드베이스 컴포넌트들의 크기 평균치보다 크지 않게 알려주는 툴 - - etc - -- 사이즈는 애플리케이션 전반적으로 일정한 크기 유지가 필요함 -- 컴포넌트 식별하기 - - 컨벤션을 유지한 적절한 이름 - - 네임스페이스 (컴포넌트가 위치한 디렉터리 또는 패키지 등) - - 컴포넌트 비중 > 문장 수, 파일 수 - -- 예시에서 성한은 리포팅 컴포넌트의 비중이 지나치게 크다는 것을 발견하여 이를 적절한 세부 단위로 쪼개는 것으로 컴포넌트 크기를 고르게 만들었음 - -### 공통 도메인을 갖는 컴포넌트 수집 - -- 공통 도메인 로직을 발굴하여 단일 컴포넌트로 중앙화하는 패턴 -- 여러 서비스에서 같이 사용되는 기능을 통합해 두면, 추후 중복 서비스를 쉽게 제거할 수 있다 -- 이름이나 네임스페이스를 이용하여 구분 -- 공통 도메인 로직 통합 전후의 커플링 (결합도) 을 계산하면 컴포넌트의 비중 및 통합 필요성 여부 판단에 도움이 된다 - -### 컴포넌트 눌러펴기 - -- A 컴포넌트가 B 컴포넌트를 기반으로 생성되고, B 컴포넌트가 C 컴포넌트를 기반으로 생성되는 등 - - 예시: 설문 (ss.survey) 하위에 설문 템플릿 (ss.survey.templates) 이 존재하는 경우 - - 설문 (ss.survey) 클래스와 직접적으로 연관된 컴포넌트는 없음 - - ss.survey.templates 컴포넌트를 ss.survey 로 옮겨 합치거나, ss.survey 기능을 분해하여 ss.survey.create, ss.survey.process 등으로 확장하여 루트 네임스페이스로 만드는 방법이 있다 - - 이때 ss.survey의 공통 클래스는 고아 클래스이므로, ss.survey 하위에 있는 컴포넌트들이 가져다 쓰는 ss.survey.template 를 추가하면 된다 - -- 디렉터리 상에 리프 노드만 존재하게끔 평평하게 누르는 작업 -- 고아 클래스를 없애는 작업 - - 고아 클래스: 어떠한 컴포넌트와도 연관되지 않은, 루트 네임스페이스에 속하는 클래스 - -### 컴포넌트 디펜던시 결정 - -![dependencies](./images/04_02.png) - -- 컴포넌트 간의 커플링 (데이터가 오가는 구간) 을 분석하여, 디펜던시가 어떤 양상을 보이는지 결정하는 패턴 -- 모놀리식 어플리케이션을 분해했을 때 각 서비스간 어떠한 연관 (의존성) 을 가질지 분석하는 과정 -- 위 이미지의 경우, 컴포넌트 간의 디펜던시가 너무 커서 사실상 컴포넌트 분해가 어렵고, 다시 코딩하는게 나은 수준 -- 미리 컴포넌트 간의 결합도를 파악하는 것은 각 디펜던시를 리팩터링하고 서비스 단위로 분해하는 데에 큰 도움을 준다 -- 피트니스 함수로는 디펜던시 개수에 제한을 두거나 특정 컴포넌트간 디펜던시를 갖지 않게 막을 수 있다 - -### 컴포넌트 도메인 생성 - -- 서로 관련된 기능들을 수행하는 컴포넌트들을 그룹핑하여 도메인을 식별하는 것은 결국 서비스 기반 아키텍처에서 각 서비스의 대상을 결정하는 과정이다 -- 네임스페이스 노드로 도메인을 표현하면 좋다 -- 예를 들어, 과금 관련 컴포넌트와 고객 프로필 관련 컴포넌트를 `고객` 이라는 더 큰 도메인으로 묶어서 체계화할 수 있다 - -### 도메인 서비스 생성 - -- 컴포넌트 도메인 구조를 잘 잡았다면, 이를 각 도메인 서비스로 옮겨서 서비스 기반 아키텍처를 구축한다 -- 도메인 서비스 마이그레이션 전에 컴포넌트들을 그 도메인의 특성에 맞게 리팩터링한 후 마이그레이션을 하는 것이 좋다 - - 그렇지 않으면 한 도메인이 다른 도메인에 꾸겨들어가야 하는 불상사가 발생 +- 컴포넌트 기반 분해 + - 어플리케이션의 논리적 구성 요소 단위 (컴포넌트 단위) 를 추출하고 이를 이용하여 아키텍처를 구성 + - 코드베이스가 컴포넌트 단위로 구성되어 있어 분해 가능할 경우 이쪽 선택 +- 전술적 분기 + - 애플리케이션 사본을 복사하고 필요없는 부분을 깎아내며 구성 + - 코드베이스 분해 불가능할 경우 (엉망일 경우) 이쪽이 적절한 선택 +- 도구를 이용하여 코드베이스의 특성을 파악하고 구조를 판별 + +### 추상도와 불안정도 + +- 코드베이스의 균형을 나타내는 척도 +- 추상도 + - 구현 대비 추상화가 이뤄진 정도 + - 추상 요소와 구상 요소의 개수로 측정한다 +- 불안정도 + - 코드베이스가 불안정한 정도 + - 커플링 (구심, 원심) 이 높을 경우 불안정도가 올라감 + - 컴포넌트끼리 강하게 엮여 있어 하나를 수정하면 다른 컴포넌트에 영향을 미칠 확률이 높다는 뜻 + +![image03-01](./images/03_01.png) + +- 메인 시퀀스로부터의 거리 + - 추상도와 불안정도 사이의 이상적인 관계 + - x절편, y절편, 기울기 1의 직선 + - 이 선에 가까울수록 이상적이다 (컴포넌트 균형이 적절하다) +- 메인 시퀀스로부터의 거리 그래프 기준으로 + - 오른쪽 위로 치우친 부분은 추상화가 과도한 (쓸모없는) 구역 + - 사용이 어려움 + - 왼쪽 아래로 치우친 부분은 추상화가 없다시피한 (고통스러운) 구역 + - 취약하고 관리가 어려움 + +``` +논의점: 추상도, 불안정도, 거리 등의 요소가 굉장히 수학적인 요소로 보이는데, 개발에는 정답이 없듯이 컴포넌트가 추상적인지, 불안정한지 여부를 판가름하는 기준도 매우 모호할 듯하다. 추상 클래스 등 명확하게 추상적인 요소가 없는 경우 이러한 수치들을 계산하고, 아키텍처 구성에 참고할 만한 자료로 삼는 것이 과연 가능할까 의문이 든다. +``` + +### 컴포넌트 기반 분해 + +- 컴포넌트 단위의 폴더구조 및 파일로 디렉터리를 구성 및 각 코드 분리 +- 모놀리식을 분산 아키텍처로 마이그레이션할 때 도움이 된다 + +### 전술적 분기 + +- 진흙잡탕 아키텍처를 다듬을 때, 추출보다는 필요없는 것을 떼어내는 것에 중점 +- 서로간의 의존성 때문에 추출에 한계가 있는 경우 +- A팀, B팀이 서로 각각 코드베이스 사본을 복사한 후, 각자의 팀에 필요한 코드만 남기고 나머지를 삭제하는 기법 + - 이렇게 하면 각 파트별 큰 구조는 유지하면서 모놀리식 구조를 덩어리로 쪼갤 수 있다 +- 분해보다 상대적으로 쉽지만 모놀리스 코드의 흔적이 계속 남아있을 가능성이 있다 +- 개발자가 노력을 기울이지 않으면, 조금 더 가벼워졌을 뿐인 (코드 용량만 줄어든) 진흙덩어리가 될 수도 있음 + +``` +느낀점?: 마침 아주 최근에 큰 덩어리의 진흙 코드를 서비스별로 분기하는 작업을 진행했는데, 그 과정에서 덩어리를 서비스별로 복사하고 그중 필요없는 코드를 지우고 공통화할 수 있는 코드만 분리하여 덩어리를 경량화한 적이 있었음. 전술적 분기 파트를 읽으면서 해당 작업 생각이 났다. (내가 진행한 작업이 어찌보면 전술적 분기구나? 하는) + +난이도는 확실히 처음부터 작정하고 분리를 시도하는 것보다 간단한 편이고 시간도 많이 걸리지 않았지만, 덩어리 A를 분리하고 나서 덩어리 B를 작업하는 도중에 덩어리 A에 미처 덜어내지 못한 찌꺼기를 발견하는 등 코드 깎아내기에 어느 정도 익숙하지 않으면 실수하기가 쉬운 듯 하다. A 덩어리는 C, D, E 서비스를 분기할 때까지도 찌꺼기와 공통화가 덜된 요소들이 계속 발견되어 추가작업을 진행해야 했다.. 눈물.. +``` diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/05.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/05.md index e3656585..606a7227 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/05.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/05.md @@ -1,106 +1,83 @@ -## Chapter 06: 운영 데이터 분리 +## Chapter 05: 컴포넌트 기반 분해 패턴 ### 개요 -- 애플리케이션보다 훨씬 분해가 어려운 것이 데이터베이스 -- 데이터베이스를 분해해야 경계 구분이 명확해진다 - -### 데이터 분해인 - -- 데이터 분해 이유 (언제 분해해야할까?) -- 변경 관리 - - 테이블을 수정할 때 얼마나 많은 서비스에 영향을 끼치는지 - - 영향 받은 서비스를 명확히 알 수 있으면 괜찮은데, 그걸 모른 채로 배포했더니 프로덕션이 오동작하는 일도 있음 - - 데이터베이스를 적절히 분리하여 변경 관리에 이점을 얻을 수 있다 - - 자신을 소유한 서비스에만 영향을 미치게끔 독립적으로 운용 -- 커넥션 관리 - - 여러 서비스가 동일한 데이터베이스를 공유할 경우, 서비스와 연결된 커넥션 풀이 많아지면서 데이터베이스에 부하를 일으킨다 - - 커넥션이 너무 많으면 커넥션 대기가 걸림 - - 추후 서비스를 확장하게 될 경우, 커넥션이 더 늘어남을 고려해야 함 - - 데이터베이스를 분리함으로써 동시에 사용할 수 있는 커넥션 수를 늘릴 수 있다 -- 확장성 - - 서비스 응답 시간을 일정하게 유지하고, 요청량에 따라 서비스 규모를 늘리는 능력 - - 하나의 데이터베이스를 여러 서비스가 바라볼 경우, 커넥션 뿐만 아니라 처리량 부하도 심각해진다 - - 따라서 서비스 확장을 위해서는 데이터베이스 확장을 통해 처리량을 분산시키는것이 좋음 -- 내고장성 -- 여러 서비스가 하나의 데이터베이스를 공유할 경우, 해당 데이터베이스에 장애가 발생하면 이를 공유하는 모든 서비스가 영향을 받게 됨 - - 내고장성: 하나의 서비스나 데이터베이스가 고장나도, 다른 부분은 중단없이 가동시킬 수 있는 능력 - - 데이터베이스를 여러 개 두어 하나의 데이터베이스가 망가져도 다른 서비스가 문제없이 동작할수 있도록 하는게 좋다 -- 아키텍처 퀀텀 - - 어떤 경우에 데이터베이스를 분해하는 게 좋을지 알려주는 길잡이 - - 퀀텀 단위로 데이터베이스를 쪼개면 독립적인 서비스로 분리가 가능 -- 데이터베이스 타입 최적화 - - 데이터 처리 방식에 따른 분리 - -``` -논의점: 데이터 분해인에 정말 많은 요인들이 있는데, 이것들을 고려하기 수월하게 해 주는 피트니스 함수나 유틸리티는 어떤 것이 있을까? -``` - -### 데이터 통합인 - -- 데이터 통합 이유 (언제 합쳐야할까?) -- 데이터 관계 - - 데이터베이스 테이블간에도 커플링이 발생할 수 있음 - - 외래 키를 통한 연결, 저장 프로시저 등 - - 데이터베이스 분해를 통해 내고장성을 높일지, 통합을 통해 테이블 간 관계를 유지하는게 나을지 고민해야 함 -- 데이터베이스 트랜잭션 - - 서로 다른 테이블에서 발생한 에러는 같은 트랜잭션으로 묶을 수 없기 때문에 데이터의 일관성과 무결성을 보장할 수 없음 - -### 모놀리식 데이터 분해 - -- 마이그레이션 점진적 진행 과정 -- 데이터베이스 분석, 데이터 도메인 생성 - - 내부의 도메인 그룹 식별 -- 데이터 도메인에 테이블 할당 - - 테이블들을 특정 컨텍스트로 묶은 뒤, 각 데이터 도메인에 속하는 테이블들을 스키마에 할당 - - 서로 다른 도메인에 속한 테이블들 간 밀접한 커플링이 존재한다면, 이를 묶어야 함 - - synonym (일종의 심볼릭 링크와 같은 별칭) 을 이용하여 코드 분석을 용이하게 만드는 것도 좋은 방법 -- 데이터 도메인에 접속하는 데이터베이스 커넥션의 분리 - - 모든 데이터 접근이 서비스 - 스키마를 통해서만 이루어지도록 구성을 리팩토링 - - 교차 스키마 접근을 서비스 단위로 제거해야 함 - - 이 과정을 완료하여 서비스마다 데이터를 각각 소유하는 아키텍처로 전환됨 -- 개별 데이터베이스 서버로 스키마 이전 - - 위 단계에서 독립적인 접근으로 분리한 데이터 (스키마) 들을 물리적인 단일 데이터베이스 각각으로 옮김 - - 스키마를 옮길 땐 백업 후 복원하거나, 아예 스키마를 복제해서 새 데이터베이스로 커넥션 전환하는 방법이 있음 -- 독립적 데이터베이스 서버로 전환 - - 위에서 각 스키마를 이전하면, 서비스 커넥션도 전환할 수 있음 - - 하나의 서비스 덩어리를 독립적인 배포 단위로 작동시키는 것 - - 기존 큰 데이터베이스에 묶인 스키마와 커넥션을 전부 삭제하면, 이제 각 서비스는 자신의 데이터베이스를 가진 독립적인 도메인이 된다 - -### 데이터베이스 타입 선택 - -- 학습 용이성 - - 데이터베이스를 배우기 쉬운지 -- 모델링 용이성 - - 데이터 모델러가 얼마나 쉽게 도메인을 표현할 수 있는지 -- 확장성 및 처리량 - - 증가된 처리량을 데이터베이스가 얼마나 쉽게 확장 및 감당 가능한지 -- 가용성, 내분할성 - - 고가용성 구성을 지원하는지 -- 일관성 - - 항상 일관된 패러다임 지원 여부 -- 프로그래밍 언어 지원 - - 다양한 프로그래밍 언어 지원 여부 - -#### 데이터베이스 종류별 특징 - -- 관계형 디비 - - 가용성보다 일관성 중시 - - 업계 표준이라 공부할 자료가 많고 모델링도 비교적 쉽다 -- 키-값 데이터베이스 - - 관계형 디비보다 배우는 것은 까다로우나, 확장성과 내분할성 면에서 이점을 갖는다 - - 테이블 조인 등의 과정이 필요없기 때문 -- 문서형 데이터베이스 - - 사람이 값을 읽기 쉬워 배우기 쉽고 FE 등에게도 익숙한 형식 -- 컬럼형 데이터베이스 - - 확장성과 내분할성은 최고이지만 이해하기가 어려움 -- 그래프 데이터베이스 - - 어렵고, 정보가 비교적 많지 않음 - - 데이터 흐름 방향성에 따라 복잡해지기 쉽다 -- NewSQL - - 관계형 데이터베이스와 유사하여 학습이 어렵지 않음 - - SQL을 지원하고, NoSQL의 확장성과 관계형 데이터베이스의 장점을 섞은 느낌 -- 클라우드 네이티브 데이터베이스 - - 관계형 데이터베이스와 비슷하고, 클라우드에 바로 올릴 수 있다 -- 시계열 데이터베이스 - - 시계열 분석에 특화 +![04_01](./images/04_01.png) + +1. 컴포넌트 식별 및 사이징 + - 나눌 컴포넌트의 크기를 결정 +2. 공통 도메인을 갖는 컴포넌트 수집 + - 중복 가능성이 있는 로직 통합 +3. 컴포넌트 눌러펴기 + - 도메인, 서브도메인, 컴포넌트를 정리 +4. 컴포넌트 디펜던시 결정 + - 디펜던시를 다듬어 마이그레이션 실현가능성 및 작업량 결정 +5. 컴포넌트 도메인 생성 + - 컴포넌트를 애플리케이션 내부의 논리적 도메인들로 그룹핑 및 리팩터링 +6. 도메인 서비스 생성 + - 모놀리식 애플리케이션의 논리 도메인을 개별 배포된 도메인 서비스들로 이동 + - 모놀리식을 서비스 단위로 쪼개기 + +### 컴포넌트 식별 및 사이징 + +- 애플리케이션을 구성하는 컴포넌트를 식별하여 크기를 조절 +- 너무 크거나 너무 작은 컴포넌트를 찾아내는 작업 + - 큰 컴포넌트의 경우 다른 컴포넌트들과의 결합도가 높을 가능성이 높다 +- 컴포넌트 크기를 결정하는 지표 + - 문장 수 (조건문, 분기문 등, 세미콜론으로 구분) + - 파일 수 + - 이러한 수치들을 이용하여 컴포넌트의 비중 계산 + - 컴포넌트 사이즈를 일정하게 유지하기 위해 피트니스 함수나 툴을 쓰면 좋다 + - 어떤 컴포넌트가 추가되고 삭제되었는지 알려주는 툴 + - 코드베이스에서 차지하는 비중을 나타내고 임계치를 벗어나지 않게끔 돕는 툴 + - 컴포넌트가 코드베이스 컴포넌트들의 크기 평균치보다 크지 않게 알려주는 툴 + - etc + +- 사이즈는 애플리케이션 전반적으로 일정한 크기 유지가 필요함 +- 컴포넌트 식별하기 + - 컨벤션을 유지한 적절한 이름 + - 네임스페이스 (컴포넌트가 위치한 디렉터리 또는 패키지 등) + - 컴포넌트 비중 > 문장 수, 파일 수 + +- 예시에서 성한은 리포팅 컴포넌트의 비중이 지나치게 크다는 것을 발견하여 이를 적절한 세부 단위로 쪼개는 것으로 컴포넌트 크기를 고르게 만들었음 + +### 공통 도메인을 갖는 컴포넌트 수집 + +- 공통 도메인 로직을 발굴하여 단일 컴포넌트로 중앙화하는 패턴 +- 여러 서비스에서 같이 사용되는 기능을 통합해 두면, 추후 중복 서비스를 쉽게 제거할 수 있다 +- 이름이나 네임스페이스를 이용하여 구분 +- 공통 도메인 로직 통합 전후의 커플링 (결합도) 을 계산하면 컴포넌트의 비중 및 통합 필요성 여부 판단에 도움이 된다 + +### 컴포넌트 눌러펴기 + +- A 컴포넌트가 B 컴포넌트를 기반으로 생성되고, B 컴포넌트가 C 컴포넌트를 기반으로 생성되는 등 + - 예시: 설문 (ss.survey) 하위에 설문 템플릿 (ss.survey.templates) 이 존재하는 경우 + - 설문 (ss.survey) 클래스와 직접적으로 연관된 컴포넌트는 없음 + - ss.survey.templates 컴포넌트를 ss.survey 로 옮겨 합치거나, ss.survey 기능을 분해하여 ss.survey.create, ss.survey.process 등으로 확장하여 루트 네임스페이스로 만드는 방법이 있다 + - 이때 ss.survey의 공통 클래스는 고아 클래스이므로, ss.survey 하위에 있는 컴포넌트들이 가져다 쓰는 ss.survey.template 를 추가하면 된다 + +- 디렉터리 상에 리프 노드만 존재하게끔 평평하게 누르는 작업 +- 고아 클래스를 없애는 작업 + - 고아 클래스: 어떠한 컴포넌트와도 연관되지 않은, 루트 네임스페이스에 속하는 클래스 + +### 컴포넌트 디펜던시 결정 + +![dependencies](./images/04_02.png) + +- 컴포넌트 간의 커플링 (데이터가 오가는 구간) 을 분석하여, 디펜던시가 어떤 양상을 보이는지 결정하는 패턴 +- 모놀리식 어플리케이션을 분해했을 때 각 서비스간 어떠한 연관 (의존성) 을 가질지 분석하는 과정 +- 위 이미지의 경우, 컴포넌트 간의 디펜던시가 너무 커서 사실상 컴포넌트 분해가 어렵고, 다시 코딩하는게 나은 수준 +- 미리 컴포넌트 간의 결합도를 파악하는 것은 각 디펜던시를 리팩터링하고 서비스 단위로 분해하는 데에 큰 도움을 준다 +- 피트니스 함수로는 디펜던시 개수에 제한을 두거나 특정 컴포넌트간 디펜던시를 갖지 않게 막을 수 있다 + +### 컴포넌트 도메인 생성 + +- 서로 관련된 기능들을 수행하는 컴포넌트들을 그룹핑하여 도메인을 식별하는 것은 결국 서비스 기반 아키텍처에서 각 서비스의 대상을 결정하는 과정이다 +- 네임스페이스 노드로 도메인을 표현하면 좋다 +- 예를 들어, 과금 관련 컴포넌트와 고객 프로필 관련 컴포넌트를 `고객` 이라는 더 큰 도메인으로 묶어서 체계화할 수 있다 + +### 도메인 서비스 생성 + +- 컴포넌트 도메인 구조를 잘 잡았다면, 이를 각 도메인 서비스로 옮겨서 서비스 기반 아키텍처를 구축한다 +- 도메인 서비스 마이그레이션 전에 컴포넌트들을 그 도메인의 특성에 맞게 리팩터링한 후 마이그레이션을 하는 것이 좋다 + - 그렇지 않으면 한 도메인이 다른 도메인에 꾸겨들어가야 하는 불상사가 발생 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/06.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/06.md index df4f300c..e3656585 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/06.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/06.md @@ -1,45 +1,106 @@ -## Chapter 07: 서비스 세분도 +## Chapter 06: 운영 데이터 분리 ### 개요 -- 세분도: 작게 나눈 서비스들의 사이즈 정도 +- 애플리케이션보다 훨씬 분해가 어려운 것이 데이터베이스 +- 데이터베이스를 분해해야 경계 구분이 명확해진다 -### 세분도 분해인 +### 데이터 분해인 -- 서비스를 작게 나눠야 하는 이유 -- 서비스의 범위와 기능 - - 서비스가 하는 일의 크기와, 컴포넌트의 사이즈 - - 서비스로 나눠지는 기준이 사람마다 다르고, 개발자는 서비스를 최대한 작게 나누려는 성향이 있기 때문에 서비스의 범위를 꼭 고려해야 한다 -- 코드 변동성 - - 소스 코드를 변경하는 빈도 - - 자주 변경되는 기능을 영향력이 적은 단일 서비스로 묶으면 타 기능에 끼치는 영향이 작아지기 때문에 테스트에 용이 -- 확장성 + 처리량 - - 처리량을 달성하기 위해 서비스를 확장할 필요가 있음 - - 서비스를 적절히 쪼개 다양한 처리량 목표를 달성하게 할 수 있다 +- 데이터 분해 이유 (언제 분해해야할까?) +- 변경 관리 + - 테이블을 수정할 때 얼마나 많은 서비스에 영향을 끼치는지 + - 영향 받은 서비스를 명확히 알 수 있으면 괜찮은데, 그걸 모른 채로 배포했더니 프로덕션이 오동작하는 일도 있음 + - 데이터베이스를 적절히 분리하여 변경 관리에 이점을 얻을 수 있다 + - 자신을 소유한 서비스에만 영향을 미치게끔 독립적으로 운용 +- 커넥션 관리 + - 여러 서비스가 동일한 데이터베이스를 공유할 경우, 서비스와 연결된 커넥션 풀이 많아지면서 데이터베이스에 부하를 일으킨다 + - 커넥션이 너무 많으면 커넥션 대기가 걸림 + - 추후 서비스를 확장하게 될 경우, 커넥션이 더 늘어남을 고려해야 함 + - 데이터베이스를 분리함으로써 동시에 사용할 수 있는 커넥션 수를 늘릴 수 있다 +- 확장성 + - 서비스 응답 시간을 일정하게 유지하고, 요청량에 따라 서비스 규모를 늘리는 능력 + - 하나의 데이터베이스를 여러 서비스가 바라볼 경우, 커넥션 뿐만 아니라 처리량 부하도 심각해진다 + - 따라서 서비스 확장을 위해서는 데이터베이스 확장을 통해 처리량을 분산시키는것이 좋음 - 내고장성 - - 데이터베이스와 마찬가지로 하나의 도메인에 장애가 발생해도 다른 곳에 영향을 끼치지 않게끔 하는 것이 중요하다 -- 보안 - - 민감한 데이터를 다른 서비스가 접근하지 못하게 보호 - - 데이터 저장 뿐만 아니라 데이터 접근도 보안에 큰 영향을 끼친다 -- 신장성 - - 현재 기능에서 새로운 기능이 추가될 경우 리스크를 작게 만들어야 함 +- 여러 서비스가 하나의 데이터베이스를 공유할 경우, 해당 데이터베이스에 장애가 발생하면 이를 공유하는 모든 서비스가 영향을 받게 됨 + - 내고장성: 하나의 서비스나 데이터베이스가 고장나도, 다른 부분은 중단없이 가동시킬 수 있는 능력 + - 데이터베이스를 여러 개 두어 하나의 데이터베이스가 망가져도 다른 서비스가 문제없이 동작할수 있도록 하는게 좋다 +- 아키텍처 퀀텀 + - 어떤 경우에 데이터베이스를 분해하는 게 좋을지 알려주는 길잡이 + - 퀀텀 단위로 데이터베이스를 쪼개면 독립적인 서비스로 분리가 가능 +- 데이터베이스 타입 최적화 + - 데이터 처리 방식에 따른 분리 -### 세분도 통합인 +``` +논의점: 데이터 분해인에 정말 많은 요인들이 있는데, 이것들을 고려하기 수월하게 해 주는 피트니스 함수나 유틸리티는 어떤 것이 있을까? +``` -- 서비스를 합쳐서 크게 만들어야 하는 이유 -- 데이터베이스 트랜잭션 - - 데이터베이스와 비슷하게, 서로 다른 서비스끼리 데이터 공유가 잦은데 도메인이 분리되어 있을 경우 트랜잭션 적용이 어렵다 - - 이런 경우 통합하는 것이 좋다 -- 워크플로우와 코레오그래피 - - 기능간 결합도를 확인하고, 단단히 결합되어 있을 경우 전체 내고장성 보장을 위해 굳이 분리하지 않는 것도 방법 - - 데이터 일관성과 무결성을 중시한다면 서비스 통합도 대안이 된다 -- 공유 코드 - - 서비스들 간 코드를 공유해야 하는지 여부 - - 서비스가 분리되어 있을 경우 라이브러리나 코드 변경시 이를 사용하는 모든 서비스를 찾아서 같이 수정해야 함 - - 이 경우 서비스를 통합하는 게 방법일 수 있다 +### 데이터 통합인 + +- 데이터 통합 이유 (언제 합쳐야할까?) - 데이터 관계 - - 서비스 간 데이터는 공유되지 않고 엄격한 콘텍스트로 나눠져 있으므로 서비스간 통신이 잦을 경우 이 서비스를 합치는 게 나을 수도 있다 + - 데이터베이스 테이블간에도 커플링이 발생할 수 있음 + - 외래 키를 통한 연결, 저장 프로시저 등 + - 데이터베이스 분해를 통해 내고장성을 높일지, 통합을 통해 테이블 간 관계를 유지하는게 나을지 고민해야 함 +- 데이터베이스 트랜잭션 + - 서로 다른 테이블에서 발생한 에러는 같은 트랜잭션으로 묶을 수 없기 때문에 데이터의 일관성과 무결성을 보장할 수 없음 + +### 모놀리식 데이터 분해 + +- 마이그레이션 점진적 진행 과정 +- 데이터베이스 분석, 데이터 도메인 생성 + - 내부의 도메인 그룹 식별 +- 데이터 도메인에 테이블 할당 + - 테이블들을 특정 컨텍스트로 묶은 뒤, 각 데이터 도메인에 속하는 테이블들을 스키마에 할당 + - 서로 다른 도메인에 속한 테이블들 간 밀접한 커플링이 존재한다면, 이를 묶어야 함 + - synonym (일종의 심볼릭 링크와 같은 별칭) 을 이용하여 코드 분석을 용이하게 만드는 것도 좋은 방법 +- 데이터 도메인에 접속하는 데이터베이스 커넥션의 분리 + - 모든 데이터 접근이 서비스 - 스키마를 통해서만 이루어지도록 구성을 리팩토링 + - 교차 스키마 접근을 서비스 단위로 제거해야 함 + - 이 과정을 완료하여 서비스마다 데이터를 각각 소유하는 아키텍처로 전환됨 +- 개별 데이터베이스 서버로 스키마 이전 + - 위 단계에서 독립적인 접근으로 분리한 데이터 (스키마) 들을 물리적인 단일 데이터베이스 각각으로 옮김 + - 스키마를 옮길 땐 백업 후 복원하거나, 아예 스키마를 복제해서 새 데이터베이스로 커넥션 전환하는 방법이 있음 +- 독립적 데이터베이스 서버로 전환 + - 위에서 각 스키마를 이전하면, 서비스 커넥션도 전환할 수 있음 + - 하나의 서비스 덩어리를 독립적인 배포 단위로 작동시키는 것 + - 기존 큰 데이터베이스에 묶인 스키마와 커넥션을 전부 삭제하면, 이제 각 서비스는 자신의 데이터베이스를 가진 독립적인 도메인이 된다 + +### 데이터베이스 타입 선택 + +- 학습 용이성 + - 데이터베이스를 배우기 쉬운지 +- 모델링 용이성 + - 데이터 모델러가 얼마나 쉽게 도메인을 표현할 수 있는지 +- 확장성 및 처리량 + - 증가된 처리량을 데이터베이스가 얼마나 쉽게 확장 및 감당 가능한지 +- 가용성, 내분할성 + - 고가용성 구성을 지원하는지 +- 일관성 + - 항상 일관된 패러다임 지원 여부 +- 프로그래밍 언어 지원 + - 다양한 프로그래밍 언어 지원 여부 -### 적정 균형점 찾기 +#### 데이터베이스 종류별 특징 -- 분해인과 통합인을 고려하여 트레이드오프를 결정해야 함 +- 관계형 디비 + - 가용성보다 일관성 중시 + - 업계 표준이라 공부할 자료가 많고 모델링도 비교적 쉽다 +- 키-값 데이터베이스 + - 관계형 디비보다 배우는 것은 까다로우나, 확장성과 내분할성 면에서 이점을 갖는다 + - 테이블 조인 등의 과정이 필요없기 때문 +- 문서형 데이터베이스 + - 사람이 값을 읽기 쉬워 배우기 쉽고 FE 등에게도 익숙한 형식 +- 컬럼형 데이터베이스 + - 확장성과 내분할성은 최고이지만 이해하기가 어려움 +- 그래프 데이터베이스 + - 어렵고, 정보가 비교적 많지 않음 + - 데이터 흐름 방향성에 따라 복잡해지기 쉽다 +- NewSQL + - 관계형 데이터베이스와 유사하여 학습이 어렵지 않음 + - SQL을 지원하고, NoSQL의 확장성과 관계형 데이터베이스의 장점을 섞은 느낌 +- 클라우드 네이티브 데이터베이스 + - 관계형 데이터베이스와 비슷하고, 클라우드에 바로 올릴 수 있다 +- 시계열 데이터베이스 + - 시계열 분석에 특화 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/07.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/07.md new file mode 100644 index 00000000..df4f300c --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/07.md @@ -0,0 +1,45 @@ +## Chapter 07: 서비스 세분도 + +### 개요 + +- 세분도: 작게 나눈 서비스들의 사이즈 정도 + +### 세분도 분해인 + +- 서비스를 작게 나눠야 하는 이유 +- 서비스의 범위와 기능 + - 서비스가 하는 일의 크기와, 컴포넌트의 사이즈 + - 서비스로 나눠지는 기준이 사람마다 다르고, 개발자는 서비스를 최대한 작게 나누려는 성향이 있기 때문에 서비스의 범위를 꼭 고려해야 한다 +- 코드 변동성 + - 소스 코드를 변경하는 빈도 + - 자주 변경되는 기능을 영향력이 적은 단일 서비스로 묶으면 타 기능에 끼치는 영향이 작아지기 때문에 테스트에 용이 +- 확장성 + 처리량 + - 처리량을 달성하기 위해 서비스를 확장할 필요가 있음 + - 서비스를 적절히 쪼개 다양한 처리량 목표를 달성하게 할 수 있다 +- 내고장성 + - 데이터베이스와 마찬가지로 하나의 도메인에 장애가 발생해도 다른 곳에 영향을 끼치지 않게끔 하는 것이 중요하다 +- 보안 + - 민감한 데이터를 다른 서비스가 접근하지 못하게 보호 + - 데이터 저장 뿐만 아니라 데이터 접근도 보안에 큰 영향을 끼친다 +- 신장성 + - 현재 기능에서 새로운 기능이 추가될 경우 리스크를 작게 만들어야 함 + +### 세분도 통합인 + +- 서비스를 합쳐서 크게 만들어야 하는 이유 +- 데이터베이스 트랜잭션 + - 데이터베이스와 비슷하게, 서로 다른 서비스끼리 데이터 공유가 잦은데 도메인이 분리되어 있을 경우 트랜잭션 적용이 어렵다 + - 이런 경우 통합하는 것이 좋다 +- 워크플로우와 코레오그래피 + - 기능간 결합도를 확인하고, 단단히 결합되어 있을 경우 전체 내고장성 보장을 위해 굳이 분리하지 않는 것도 방법 + - 데이터 일관성과 무결성을 중시한다면 서비스 통합도 대안이 된다 +- 공유 코드 + - 서비스들 간 코드를 공유해야 하는지 여부 + - 서비스가 분리되어 있을 경우 라이브러리나 코드 변경시 이를 사용하는 모든 서비스를 찾아서 같이 수정해야 함 + - 이 경우 서비스를 통합하는 게 방법일 수 있다 +- 데이터 관계 + - 서비스 간 데이터는 공유되지 않고 엄격한 콘텍스트로 나눠져 있으므로 서비스간 통신이 잦을 경우 이 서비스를 합치는 게 나을 수도 있다 + +### 적정 균형점 찾기 + +- 분해인과 통합인을 고려하여 트레이드오프를 결정해야 함 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md deleted file mode 100644 index 28827c8b..00000000 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/09.md +++ /dev/null @@ -1,45 +0,0 @@ -## Chapter 10: 분산 데이터 액세스 - -### 개요 - -- 서비스간 통신패턴: 서비스 간 데이터를 주고받는 방식 - - 요청하는 대로 데이터를 다 줬다가는 레이턴시가 발생하므로 성능이 떨어진다 - - 또한 여러 서비스가 데이터 때문에 커플링되어 의존성이 생기기 때문에, 한 쪽을 수정할 때 다른 쪽도 수정해야 하는 불상사가 발생 - ---- - -### 컬럼 스키마 복제 패턴 - -- 컬럼을 여러 테이블에 복제해서, 다른 경계 콘텍스트에서도 가져다 쓸 수 있게 하는 방법 -- 데이터를 매번 동기화해야 함 => 일관성 유지 어려움 -- 데이터 오너십 통제 어려움 - - 복제해서 다른 서비스에 쥐어주는 순간, 해당 데이터는 내 소유가 아니기 때문 - -### 복제 캐싱 패턴 - -- 데이터를 그대로 복사하여 새 테이블에 저장하는 것이 아니라, 대신 캐싱을 하는 방법 -- 캐시는 서비스별로 고유하게 저장되기 때문에 타 서비스와 공유되지 않음 -- 다른 캐싱 패턴 - - 단일 메모리 캐싱: 각 서비스별 고유 캐시 데이터를 가지고 있음 - - 분산 캐싱: 데이터를 외부 캐시 서버에 보관, 이 덕분에 서비스간 데이터 공유가 가능 - - 캐시 데이터는 중앙으로 공유되기 때문에, 타 서비스에서 데이터를 자유롭게 업데이트 할 수 있는 것은 그대로고, 경계 콘텍스트도 무너질 수 있다 - - 중앙 분산 캐시 (각 서비스별 캐시가 공유되는 위치) 는 원격 호출을 위해 접근해야 하므로 레이턴시가 늘어나는 것도 동일하다 - - 대신 위의 스키마 복제 패턴과 동일하게, 디펜던시만 이동했을 뿐 동기화 문제에서 자유롭지 않다 -- 단점 - - 경우에 따라 복제 캐싱이 지원되지 않을 수 있다 -- 장점 - - 각 서비스별로 캐시를 갖고 있기 때문에 서로 간섭할 일이 없다 - - 또한 각 서비스별 캐시에 접근하면 되므로 데이터 액세스가 빠르다 -- 트레이드오프 - - 캐시 데이터와 시작 타이밍에 서비스가 크게 의존한다 - - 각 서비스별로 캐시에 데이터를 채우므로, 그 캐시에 접근하는 다른 서비스는 해당 주인 서비스가 먼저 시작되어야 대기 상태에서 탈출할 수 있다 - - 데이터 양이 많을 경우 실용성이 떨어진다 - - 캐시 수만큼 용량이 \*n 이 되므로 - -### 데이터 도메인 패턴 - -- 여러 서비스가 공유하는 테이블을 하나의 스키마에 집어넣어 관리 -- 서비스가 서로 디커플링되어 디펜던시 문제와 응답성, 처리량, 확장성 이슈가 해소됨 -- 여러 서비스가 동일한 테이블을 바라보기 때문에, 무결성 문제에서도 자유롭다 -- 다만 해당 스키마의 테이블 구조가 변경될 경우 다른 서비스들도 영향을 받을 수 있다 -- 서비스 오너십과 경계 콘텍스트를 엄격하게 설정하여 타 서비스가 접근해야 하면 안될 데이터들을 적절히 막는 것이 좋다 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/10.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/10.md index 2c4a3635..28827c8b 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/10.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/10.md @@ -1,61 +1,45 @@ -## Chapter 11: 분산 워크플로 관리 +## Chapter 10: 분산 데이터 액세스 ### 개요 -- 조정: 분산 아키텍처에서 도메인에 특정한 작업을 수행하고, 그와 관련된 부수적인 문제를 처리하기 위해 서비스를 조합하는 것 +- 서비스간 통신패턴: 서비스 간 데이터를 주고받는 방식 + - 요청하는 대로 데이터를 다 줬다가는 레이턴시가 발생하므로 성능이 떨어진다 + - 또한 여러 서비스가 데이터 때문에 커플링되어 의존성이 생기기 때문에, 한 쪽을 수정할 때 다른 쪽도 수정해야 하는 불상사가 발생 --- -### 오케스트레이션 통신 스타일 +### 컬럼 스키마 복제 패턴 -- 오케스트레이터 (중재자) 를 이용하여 워크플로 상태나 에러, 알림 등을 관장 -- 복잡한 워크플로를 오케스트레이션을 통해 하나의 관리자가 전담하여 관리한다 -- 에러 조건 및 경로를 다루는 것이 가장 어려운데, 오케스트레이터는 각 트랜잭션을 관리함으로써 각 서비스의 상태와 에러 여부를 관장한다 -- 장점 - - 중앙화 워크플로: 상태와 동작을 통합한 컴포넌트 운용 - - 에러 처리 - - 복원성 - - 상태 관리 -- 단점 - - 응답성 - - 내고장성 - - 확장성 - - 서비스 커플링 +- 컬럼을 여러 테이블에 복제해서, 다른 경계 콘텍스트에서도 가져다 쓸 수 있게 하는 방법 +- 데이터를 매번 동기화해야 함 => 일관성 유지 어려움 +- 데이터 오너십 통제 어려움 + - 복제해서 다른 서비스에 쥐어주는 순간, 해당 데이터는 내 소유가 아니기 때문 -``` -궁금증: ESB도 전역 오케스트레이터라는데, ESB는 서비스간 결합을 유도하기 때문에 오케스트레이션이랑 차이가 있다고 한다. 허나 그냥 오케스트레이터랑 ESB가 무엇이 다른지 이해가 안된다. 오케스트레이터 중 하나가 ESB라는게 아닌가? -``` - ---- +### 복제 캐싱 패턴 -### 코레오그래피 통신 스타일 - -- 중앙 조정을 하는 오케스트레이션과 달리, 각 서비스가 개별로 움직이는 스타일 -- 서로 통신하고 에러 처리도 한다 -- 허나 하나의 시나리오 진행 중에 서비스에서 오류가 발생할 경우, 이미 진행이 많이 되어 각 서비스를 거쳐간 상태이기 때문에 에러가 인지한 직후 이벤트를 생성해서 메시지를 브로드캐스팅해야 다른 서비스들이 볼 수 있다 -- 통신 경로가 많아질 수 밖에 없는 구조 -- 장점 - - 응답성, 확장성, 내고장성, 서비스 디커플링 - - 사실상 오케스트레이션과 반대됨 +- 데이터를 그대로 복사하여 새 테이블에 저장하는 것이 아니라, 대신 캐싱을 하는 방법 +- 캐시는 서비스별로 고유하게 저장되기 때문에 타 서비스와 공유되지 않음 +- 다른 캐싱 패턴 + - 단일 메모리 캐싱: 각 서비스별 고유 캐시 데이터를 가지고 있음 + - 분산 캐싱: 데이터를 외부 캐시 서버에 보관, 이 덕분에 서비스간 데이터 공유가 가능 + - 캐시 데이터는 중앙으로 공유되기 때문에, 타 서비스에서 데이터를 자유롭게 업데이트 할 수 있는 것은 그대로고, 경계 콘텍스트도 무너질 수 있다 + - 중앙 분산 캐시 (각 서비스별 캐시가 공유되는 위치) 는 원격 호출을 위해 접근해야 하므로 레이턴시가 늘어나는 것도 동일하다 + - 대신 위의 스키마 복제 패턴과 동일하게, 디펜던시만 이동했을 뿐 동기화 문제에서 자유롭지 않다 - 단점 - - 분산된 워크플로 - - 상태 관리 - - 에러 처리 - - 복원성 - -### 워크플로 상태 관리 - -- 코레오그래피 통신 스타일에서는 워크플로의 상태를 관장하는 대장이 따로 없다 - - 위에 오케스트레이션 방식에서는 오케스트레이터가 직접 관장했음 -- 이 경우 상태를 관장하는 방법이 다음과 같다 - - 프론트 컨트롤러: 시나리오상 가장 먼저 호출된 서비스에게 책임을 맡기기 - - 무상태 코레오그래피: 각 서비스별 스냅샷을 구축하여 워크플로 전이 상태를 유지하지 않음 -- 스탬프 커플링: 서비스 간 전송되는 메시지 계약에 워크플로 상태를 같이 넣어서 전달 - ---- - -### 오케스트레이션 <-> 코레오그래피 간 트레이드오프 - -- 에러 빈도가 낮고, 에러 시나리오가 복잡하지 않으면 코레오그래피 - - 확장성 면에선 코레오그래피가 훨씬 편하다 -- 경계 조건과 에러 조건이 너무 복잡하면 오케스트레이션 + - 경우에 따라 복제 캐싱이 지원되지 않을 수 있다 +- 장점 + - 각 서비스별로 캐시를 갖고 있기 때문에 서로 간섭할 일이 없다 + - 또한 각 서비스별 캐시에 접근하면 되므로 데이터 액세스가 빠르다 +- 트레이드오프 + - 캐시 데이터와 시작 타이밍에 서비스가 크게 의존한다 + - 각 서비스별로 캐시에 데이터를 채우므로, 그 캐시에 접근하는 다른 서비스는 해당 주인 서비스가 먼저 시작되어야 대기 상태에서 탈출할 수 있다 + - 데이터 양이 많을 경우 실용성이 떨어진다 + - 캐시 수만큼 용량이 \*n 이 되므로 + +### 데이터 도메인 패턴 + +- 여러 서비스가 공유하는 테이블을 하나의 스키마에 집어넣어 관리 +- 서비스가 서로 디커플링되어 디펜던시 문제와 응답성, 처리량, 확장성 이슈가 해소됨 +- 여러 서비스가 동일한 테이블을 바라보기 때문에, 무결성 문제에서도 자유롭다 +- 다만 해당 스키마의 테이블 구조가 변경될 경우 다른 서비스들도 영향을 받을 수 있다 +- 서비스 오너십과 경계 콘텍스트를 엄격하게 설정하여 타 서비스가 접근해야 하면 안될 데이터들을 적절히 막는 것이 좋다 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/11.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/11.md index d4150f7f..2c4a3635 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/11.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/11.md @@ -1,155 +1,61 @@ -## Chapter 12: 트랜잭셔널 사가 +## Chapter 11: 분산 워크플로 관리 ### 개요 -- 사가 패턴: 각 업데이트가 완료되면 이벤트를 발행하고, 다음 업데이트를 실행시키는 릴레이 트랜잭션 -- 만약 업데이트들 중 하나라도 실패하면, 보상 트랜잭션을 가동시켜 이전 모든 변경사항을 무로 되돌린다 +- 조정: 분산 아키텍처에서 도메인에 특정한 작업을 수행하고, 그와 관련된 부수적인 문제를 처리하기 위해 서비스를 조합하는 것 --- -### 트랜잭셔널 사가 패턴 +### 오케스트레이션 통신 스타일 -- 에픽 사가 -- 폰 태그 사가 -- 페어리테일 사가 -- 타임트래블 사가 -- 판타지 픽션 사가 -- 호러 스토리 사가 -- 패럴렐 사가 -- 앤솔로지 사가 -- 이름이 공식은 아니고 적당히 붙인듯 +- 오케스트레이터 (중재자) 를 이용하여 워크플로 상태나 에러, 알림 등을 관장 +- 복잡한 워크플로를 오케스트레이션을 통해 하나의 관리자가 전담하여 관리한다 +- 에러 조건 및 경로를 다루는 것이 가장 어려운데, 오케스트레이터는 각 트랜잭션을 관리함으로써 각 서비스의 상태와 에러 여부를 관장한다 +- 장점 + - 중앙화 워크플로: 상태와 동작을 통합한 컴포넌트 운용 + - 에러 처리 + - 복원성 + - 상태 관리 +- 단점 + - 응답성 + - 내고장성 + - 확장성 + - 서비스 커플링 ---- - -### 에픽 사가 - -- 오케스트레이티드 사가 라고도 함 -- 동기 통신 + 원자적 일관성 + 오케스트레이션 조정 -- 트랜잭션 중 하나의 호출이라도 실패할 경우, 모두 실패한 것으로 처리해 이전 상태로 되돌림 - - 성공 or 실패밖에 없다는 뜻 -- 보상 트랜잭션을 사용하여 구현 - - 분산 트랜잭션 도중 다른 서비스가 수행한 작업을 되돌리는 업데이트 - - 중재자는 요청 처리 성공여부를 모니터링하다가, 실패할 경우 다른 서비스를 보상호출 하여 중단 -- 높은 결합도 (복잡한 커플링) -- 높은 복잡도 - - 동기 호출이라 이에 대한 복잡도는 내려감 -- 응답성이 떨어짐 -- 이 패턴을 구현하기 위한 조정 및 병목은 확장성을 낮춤 - ---- - -### 폰 태그 사가 - -- 에픽 사가에서 사용하는 조정방식을 오케스트레이션 > 코레오그래피로 바꿈 - - 동기 + 원자성 + 코레오그래피 -- 텔레폰 게임 (한 사람이 다른 사람에게 비밀을 이야기하여 마지막 사람이 이를 맞추는 게임) 과 유사하여 이런 이름이 붙음 -- 오케스트레이터가 따로 없음 - - 따라서 각 서비스별로 책임 체인을 갖고 실패시 거슬러 올라갈 수 있어야 함 -- 결합도는 에픽 사가에 비해 약간 줄어듦 (코레오그래피이므로) - - 큰 차이는 없음 -- 에픽 사가보다 훨씬 복잡해짐 - - 오케스트레이터의 빈 자리를 채우기 위해 더 많은 로직이 각 서비스별로 들어가게 됨 -- 오케스트레이션이 없어졌으므로 응답성은 좋아짐 - - 허나 에러 처리에 더 많은 시간이 소요되므로 이 때문에 응답성이 낮아질 수 있음 -- 마찬가지로 오케스트레이션을 사용하지 않아 확장성이 아주 조금 좋아짐 +``` +궁금증: ESB도 전역 오케스트레이터라는데, ESB는 서비스간 결합을 유도하기 때문에 오케스트레이션이랑 차이가 있다고 한다. 허나 그냥 오케스트레이터랑 ESB가 무엇이 다른지 이해가 안된다. 오케스트레이터 중 하나가 ESB라는게 아닌가? +``` --- -### 페어리테일 사가 +### 코레오그래피 통신 스타일 -- 동기 + 최종일관성 + 오케스트레이션 -- 서비스가 잠시 중단되었을 경우, 최종 일관성을 통해 변경된 데이터를 일시 캐싱 -- 오케스트레이터가 존재는 하지만, 트랜잭션을 관리하지 않음 - - 요청, 응답, 에러처리만 - - 트랜잭션은 각 서비스가 알아서 관리 -- 동기 통신이라 이해하기 쉽고, 오케스트레이터가 있어 관리하기 쉬우며, 전체 트랜잭션이 없고 최종 일관성에 따라 서비스 각각이 수행하는 트랜잭션만 관리하면 됨 -- 결합도는 매우 높음 (동기 + 오케스트레이션) - - 단 트랜잭션이 최종 일관성으로 대체되어, 그에 따른 결합도는 약간 낮아짐 -- 복잡도가 매우 낮음 (최종일관성 + 오케스트레이션) - - 아주 간단한 조합으로만 만들어짐 -- 응답성 - - 동기 호출이지만 빠른 편 -- 확장성 - - 커플링 (결합도) 이 낮아 확장성도 좋음 - ---- - -### 타임 트래블 사가 - -- 동기 + 최종일관성 + 코레오그래피 -- 중재자가 없으므로 도메인 서비스들이 알아서 워크플로우를 관리해야 함 - - 요청을 받고, 작업 수행 후, 다음 서비스에 요청 전달 - - 각 단계가 한 방향으로, 하나의 시간적 흐름으로 순차적으로 흘러감 -- 트랜잭션이 없어 워크플로 모델링이 쉽지만, 오케스트레이터가 없으므로 각 서비스별로 워크플로 상태와 정보를 다 가지고 있어야 함 - - 워크플로가 복잡할 수록 오케스트레이터의 필요성이 증가 - - 따라서 워크플로가 단순할 때 타임트래블 사가가 적합하다 -- 결합도가 비교적 낮고 확장성이 좋음 -- 트랜잭션이 없어 복잡도가 낮음 -- 동기 호출을 사용하기 때문에 오버헤드가 발생하여 응답성은 약간 낮은 편 -- 확장성이 매우 좋음 - ---- - -### 판타지 픽션 사가 - -- 비동기 + 원자적 일관성 + 오케스트레이션 -- 에픽 사가와 비슷하지만, 비동기를 사용 - - 따라서 분산 트랜잭션을 병렬로 수행 - - 이 비동기성 때문에 중재자가 해야할 일도 복잡해진다 -- 오케스트레이터로 조정되는 워크플로가 비동기로 움직이는 것은 일을 더 복잡하게 만들기 쉽다 -- 비동기 통신 때문에 결합도는 매우 높음 => 복잡도도 높음 -- 다수의 호출에 의해 트랜잭션 조정이 이루어지므로, 하나 이상의 서비스가 실패하면 응답성도 수직 하락함 -- 트랜잭션 체제를 사용하므로 높은 확장성 얻기가 어려움 -- 단점만 잔뜩 있는데, 비동기 통신 하나로 에픽 사가의 단점을 상쇄할 수 있다는 믿음 때문에 많이 사용되는 편 - - 정말 별로라는 뜻 - ---- - -### 호러 스토리 사가 - -- 이름부터가 호러이다 -- 비동기, 원자적 일관성, 코레오그래피 사용 -- 원자적 일관성이라는 가장 엄격한 체제 아래 가장 느슨하게 만드는 비동기 통신과 코레오그래피가 어우러져 있는 매우 최악의 조합 -- 중재자가 없기 때문에, 각 서비스들은 비동기성 때문에 언제 어디서 어긋날지 모를 트랜잭션을 계속 추적하고 되돌릴 준비를 해야 한다 - - 하나의 트랜잭션 호출이 실패할 경우 해당 파트를 전부 되돌려야 하는데, 이 조건이 매우 까다롭기 때문에 에러 처리가 매우 어렵다고 할 수 있다 -- 결합도는 에픽 사가보단 낫다 (중재자를 사용하지 않으므로) -- 매우 복잡하다 -- 중재자 패턴이 아니므로 확장은 비교적 잘 된다 -- 서비스끼리 지속적으로 통신해야 하므로 좋지 않은 응답성 - ---- - -### 패럴렐 사가 - -- 비동기 통신, 최종 일관성, 오케스트레이션 -- 에픽 사가에서의 동기 통신에 기반된 트랜잭션 패턴은 성능 저하가 일어날 수밖에 없으므로, 이를 비동기와 최종일관성으로 보완 -- 중재자가 있으므로 복잡한 워크플로에 적합하다 -- 제약조건이 느슨한 대신, 각 단계에서 발생할 에러나 문제점을 중재자에 떠맡기므로, 이 부분에서의 타이밍 문제와 안정성이 떨어지게 된다 -- 결합도가 낮으면서 복잡도도 같이 낮다 -- 확장성이 매우 좋다 -- 비동기 통신 덕이 응답성도 좋다 - ---- +- 중앙 조정을 하는 오케스트레이션과 달리, 각 서비스가 개별로 움직이는 스타일 +- 서로 통신하고 에러 처리도 한다 +- 허나 하나의 시나리오 진행 중에 서비스에서 오류가 발생할 경우, 이미 진행이 많이 되어 각 서비스를 거쳐간 상태이기 때문에 에러가 인지한 직후 이벤트를 생성해서 메시지를 브로드캐스팅해야 다른 서비스들이 볼 수 있다 +- 통신 경로가 많아질 수 밖에 없는 구조 +- 장점 + - 응답성, 확장성, 내고장성, 서비스 디커플링 + - 사실상 오케스트레이션과 반대됨 +- 단점 + - 분산된 워크플로 + - 상태 관리 + - 에러 처리 + - 복원성 -### 앤솔로지 사가 +### 워크플로 상태 관리 -- 에픽 사가의 정반대 -- 비동기 통신, 최종 일관성, 코레오그래피 - - 결합도가 낮을 수밖에 없는 요소 조합 -- 중앙 조정 기능이 없기 때문에 서비스는 복잡해지지만, 그 외의 특성 면에선 좋아진다 -- 단순하면서 선형적으로 진행되는 워크플로에 적합 - - 중앙조정 기능이 없기 때문에 단순한 워크플로에 적합한 것 - - 성능이 높아야 하고, 확장성도 추구한다면 가장 적합 -- 결합도가 매우 낮은 대신, 복잡도가 매우 높다 (코레오그래피 때문) -- 확장성, 탄력성은 결합도가 낮으므로 같이 낮음 -- 응답성 높음 +- 코레오그래피 통신 스타일에서는 워크플로의 상태를 관장하는 대장이 따로 없다 + - 위에 오케스트레이션 방식에서는 오케스트레이터가 직접 관장했음 +- 이 경우 상태를 관장하는 방법이 다음과 같다 + - 프론트 컨트롤러: 시나리오상 가장 먼저 호출된 서비스에게 책임을 맡기기 + - 무상태 코레오그래피: 각 서비스별 스냅샷을 구축하여 워크플로 전이 상태를 유지하지 않음 +- 스탬프 커플링: 서비스 간 전송되는 메시지 계약에 워크플로 상태를 같이 넣어서 전달 --- -### 상태 관리와 최종 일관성 +### 오케스트레이션 <-> 코레오그래피 간 트레이드오프 -- 상태 관리와 최종 일관성은 유한 상태 기계를 통해 현재 사가 상태를 파악하고 오류를 해결하는 방법 - - 사가 상태 기계: 분산 아키텍처에서 있을 법한 모든 가능한 경로를 기술하는 패턴 - - 각 상태가 변경될 때마다 수행할 액션과 전이 상태가 등장 - - 모든 상태 전이와 그에 해당하는 액션 목록을 정리하고, 이를 토대로 코드로 구현하는 것이 좋음 - - 사가 관리 기법: 상태들을 enum화 하고 트랜잭션을 클래스로 구현하는 것 같다 +- 에러 빈도가 낮고, 에러 시나리오가 복잡하지 않으면 코레오그래피 + - 확장성 면에선 코레오그래피가 훨씬 편하다 +- 경계 조건과 에러 조건이 너무 복잡하면 오케스트레이션 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md index 9c3d8c44..d4150f7f 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/12.md @@ -1,53 +1,155 @@ -## Chapter 13: 계약 +## Chapter 12: 트랜잭셔널 사가 ### 개요 -- 계약: 종류가 다른 아키텍처 파트가 어떻게 연결될 것인지 정의한 것 - - 아키텍처의 거의 모든 부분에서 영향을 끼친다 -- 하드 파트 계약: 어떤 정보나 디펜던시를 전달하기 위해, 아키텍처의 각 파트에서 사용되는 포맷 -- 계약이란 곧 프레임워크와 라이브러리 간의 디펜던시, 통합점, 각 서비스간 통신 등 서로를 연결시키는 모든 기술들을 포괄하는 개념 - ---- - -### 엄격한 계약 vs 느슨한 계약 - -- 엄격한 계약: 이름, 타입, 순서 등 세부사항을 전부 준수하고, 모호한 부분을 남기지 않음 - - 단, 여러 아키텍처 파트에서 두루 쓰이면서 자주 변경되는 경우, 엄격한 계약에 취약점이 생길 수 있다 - - JSON 에 키, 값 쌍을 엄격하게 제한할 수 있다 -- 느슨한 계약: 커플링이 느슨한 경우 - - REST, 그래프QL 등 - - 다른 개발자가 하나의 리소스와 기능을구축하고 이 리소스를 확장한다고 해도, 특정 기능이 갑자기 문제가 생기지 않는 경우 -- 필요한 정보 외에도 갖은 정보들을 다 계약에 넣어버릴 경우, 취약점이 생기기 쉽다 - - 예를 들어, 고객의 위시리스트는 고객의 이름 식별자만 있으면 된다 - - 허나 고객의 성별, 나이 등의 정보까지 제공해버리면 안티패턴 - - 또한 해당 정보가 수정될 경우 계약이 깨지면서 위시리스트 기능까지 수정해야 할 수도 있다 -- 트레이드오프 - - 엄격한 계약 - - 계약 충실도 보장 (계약만으로 스키마 검증 가능) - - 버저닝 - - 장점이자 단점인데, 적절하지 못한 버저닝 (버전을 너무 많이 만들거나 너무 적게 만들기) 는 서비스를 더 복잡하게 만든다 - - 빌드 시 검증이 쉽다 - - 문서화하기 좋음 - - 커플링이 단단해짐 (한 쪽 변경하면 다른 쪽도 변경해야 함) - - 느슨한 계약 - - 높은 디커플링, 매우 유연함 - - 스키마 정보가 엄격하지 않으므로, 계약을 더 자유롭게 발전 가능 - - 계약 자체가 엄격하지 않으므로, 이름 - 값 쌍 누락 또는 철자 오류 등 결합이 발생할 여지가 큼 - - 피트니스 함수를 통해 느슨한 계약을 수행하는 데 필요한 정보가 모두 들어오는지 확인이 필요 -- 마이크로서비스에서는? - - 여러 서비스의 관계와 전달되는 정보, 결합도를 생각해야 한다 -- 컨슈머 주도 계약 - - 사용자가 서비스 제공자로부터 받고 싶은 정보를 계약에 넣고, 이를 토대로 빌드에 포함시켜 계약 테스트를 수행하는 기법 - - 필요에 따라 계약을 엄격하게 하거나, 느슨하게 할 수 있다 - - 자동 테스트로 테스트 가능하므로 이 부분에선 엄격할 수 있다 - - 단, 기술자가 이 절차들을 정확히 인지하고 지켜야 한다 - ---- - -### 스탬프 커플링 - -- 서비스 끼리 매우 큰 데이터를 주고받지만, 각 서비스는 그 데이터 안에서도 매우 작은 일부만 사용하는 경우 -- 위의 위시리스트 예시에서, 고객의 이름 (또는 ID) 만 있으면 되지만 모든 회원 정보를 전부 제공하는 경우? -- 데이터 때문에 계약에 과도한 커플링이 발생하면서, 전체 구조가 매우 취약해진다 -- 대역폭에 비해 너무 큰 데이터가 오고가면서 통신에 문제가 생길 수 있다 -- 코레오그래피 방식을 사용할 수 밖에 없는 경우, 스탬프 커플링을 이용하여 도메인 정보, 워크플로 상태를 계약에 넣어 전달하면 각 서비스는 이를 받아 계약 상태와 워크플로 상태를 업데이트하여 다음 서비스에 전달할 수 있다 +- 사가 패턴: 각 업데이트가 완료되면 이벤트를 발행하고, 다음 업데이트를 실행시키는 릴레이 트랜잭션 +- 만약 업데이트들 중 하나라도 실패하면, 보상 트랜잭션을 가동시켜 이전 모든 변경사항을 무로 되돌린다 + +--- + +### 트랜잭셔널 사가 패턴 + +- 에픽 사가 +- 폰 태그 사가 +- 페어리테일 사가 +- 타임트래블 사가 +- 판타지 픽션 사가 +- 호러 스토리 사가 +- 패럴렐 사가 +- 앤솔로지 사가 +- 이름이 공식은 아니고 적당히 붙인듯 + +--- + +### 에픽 사가 + +- 오케스트레이티드 사가 라고도 함 +- 동기 통신 + 원자적 일관성 + 오케스트레이션 조정 +- 트랜잭션 중 하나의 호출이라도 실패할 경우, 모두 실패한 것으로 처리해 이전 상태로 되돌림 + - 성공 or 실패밖에 없다는 뜻 +- 보상 트랜잭션을 사용하여 구현 + - 분산 트랜잭션 도중 다른 서비스가 수행한 작업을 되돌리는 업데이트 + - 중재자는 요청 처리 성공여부를 모니터링하다가, 실패할 경우 다른 서비스를 보상호출 하여 중단 +- 높은 결합도 (복잡한 커플링) +- 높은 복잡도 + - 동기 호출이라 이에 대한 복잡도는 내려감 +- 응답성이 떨어짐 +- 이 패턴을 구현하기 위한 조정 및 병목은 확장성을 낮춤 + +--- + +### 폰 태그 사가 + +- 에픽 사가에서 사용하는 조정방식을 오케스트레이션 > 코레오그래피로 바꿈 + - 동기 + 원자성 + 코레오그래피 +- 텔레폰 게임 (한 사람이 다른 사람에게 비밀을 이야기하여 마지막 사람이 이를 맞추는 게임) 과 유사하여 이런 이름이 붙음 +- 오케스트레이터가 따로 없음 + - 따라서 각 서비스별로 책임 체인을 갖고 실패시 거슬러 올라갈 수 있어야 함 +- 결합도는 에픽 사가에 비해 약간 줄어듦 (코레오그래피이므로) + - 큰 차이는 없음 +- 에픽 사가보다 훨씬 복잡해짐 + - 오케스트레이터의 빈 자리를 채우기 위해 더 많은 로직이 각 서비스별로 들어가게 됨 +- 오케스트레이션이 없어졌으므로 응답성은 좋아짐 + - 허나 에러 처리에 더 많은 시간이 소요되므로 이 때문에 응답성이 낮아질 수 있음 +- 마찬가지로 오케스트레이션을 사용하지 않아 확장성이 아주 조금 좋아짐 + +--- + +### 페어리테일 사가 + +- 동기 + 최종일관성 + 오케스트레이션 +- 서비스가 잠시 중단되었을 경우, 최종 일관성을 통해 변경된 데이터를 일시 캐싱 +- 오케스트레이터가 존재는 하지만, 트랜잭션을 관리하지 않음 + - 요청, 응답, 에러처리만 + - 트랜잭션은 각 서비스가 알아서 관리 +- 동기 통신이라 이해하기 쉽고, 오케스트레이터가 있어 관리하기 쉬우며, 전체 트랜잭션이 없고 최종 일관성에 따라 서비스 각각이 수행하는 트랜잭션만 관리하면 됨 +- 결합도는 매우 높음 (동기 + 오케스트레이션) + - 단 트랜잭션이 최종 일관성으로 대체되어, 그에 따른 결합도는 약간 낮아짐 +- 복잡도가 매우 낮음 (최종일관성 + 오케스트레이션) + - 아주 간단한 조합으로만 만들어짐 +- 응답성 + - 동기 호출이지만 빠른 편 +- 확장성 + - 커플링 (결합도) 이 낮아 확장성도 좋음 + +--- + +### 타임 트래블 사가 + +- 동기 + 최종일관성 + 코레오그래피 +- 중재자가 없으므로 도메인 서비스들이 알아서 워크플로우를 관리해야 함 + - 요청을 받고, 작업 수행 후, 다음 서비스에 요청 전달 + - 각 단계가 한 방향으로, 하나의 시간적 흐름으로 순차적으로 흘러감 +- 트랜잭션이 없어 워크플로 모델링이 쉽지만, 오케스트레이터가 없으므로 각 서비스별로 워크플로 상태와 정보를 다 가지고 있어야 함 + - 워크플로가 복잡할 수록 오케스트레이터의 필요성이 증가 + - 따라서 워크플로가 단순할 때 타임트래블 사가가 적합하다 +- 결합도가 비교적 낮고 확장성이 좋음 +- 트랜잭션이 없어 복잡도가 낮음 +- 동기 호출을 사용하기 때문에 오버헤드가 발생하여 응답성은 약간 낮은 편 +- 확장성이 매우 좋음 + +--- + +### 판타지 픽션 사가 + +- 비동기 + 원자적 일관성 + 오케스트레이션 +- 에픽 사가와 비슷하지만, 비동기를 사용 + - 따라서 분산 트랜잭션을 병렬로 수행 + - 이 비동기성 때문에 중재자가 해야할 일도 복잡해진다 +- 오케스트레이터로 조정되는 워크플로가 비동기로 움직이는 것은 일을 더 복잡하게 만들기 쉽다 +- 비동기 통신 때문에 결합도는 매우 높음 => 복잡도도 높음 +- 다수의 호출에 의해 트랜잭션 조정이 이루어지므로, 하나 이상의 서비스가 실패하면 응답성도 수직 하락함 +- 트랜잭션 체제를 사용하므로 높은 확장성 얻기가 어려움 +- 단점만 잔뜩 있는데, 비동기 통신 하나로 에픽 사가의 단점을 상쇄할 수 있다는 믿음 때문에 많이 사용되는 편 + - 정말 별로라는 뜻 + +--- + +### 호러 스토리 사가 + +- 이름부터가 호러이다 +- 비동기, 원자적 일관성, 코레오그래피 사용 +- 원자적 일관성이라는 가장 엄격한 체제 아래 가장 느슨하게 만드는 비동기 통신과 코레오그래피가 어우러져 있는 매우 최악의 조합 +- 중재자가 없기 때문에, 각 서비스들은 비동기성 때문에 언제 어디서 어긋날지 모를 트랜잭션을 계속 추적하고 되돌릴 준비를 해야 한다 + - 하나의 트랜잭션 호출이 실패할 경우 해당 파트를 전부 되돌려야 하는데, 이 조건이 매우 까다롭기 때문에 에러 처리가 매우 어렵다고 할 수 있다 +- 결합도는 에픽 사가보단 낫다 (중재자를 사용하지 않으므로) +- 매우 복잡하다 +- 중재자 패턴이 아니므로 확장은 비교적 잘 된다 +- 서비스끼리 지속적으로 통신해야 하므로 좋지 않은 응답성 + +--- + +### 패럴렐 사가 + +- 비동기 통신, 최종 일관성, 오케스트레이션 +- 에픽 사가에서의 동기 통신에 기반된 트랜잭션 패턴은 성능 저하가 일어날 수밖에 없으므로, 이를 비동기와 최종일관성으로 보완 +- 중재자가 있으므로 복잡한 워크플로에 적합하다 +- 제약조건이 느슨한 대신, 각 단계에서 발생할 에러나 문제점을 중재자에 떠맡기므로, 이 부분에서의 타이밍 문제와 안정성이 떨어지게 된다 +- 결합도가 낮으면서 복잡도도 같이 낮다 +- 확장성이 매우 좋다 +- 비동기 통신 덕이 응답성도 좋다 + +--- + +### 앤솔로지 사가 + +- 에픽 사가의 정반대 +- 비동기 통신, 최종 일관성, 코레오그래피 + - 결합도가 낮을 수밖에 없는 요소 조합 +- 중앙 조정 기능이 없기 때문에 서비스는 복잡해지지만, 그 외의 특성 면에선 좋아진다 +- 단순하면서 선형적으로 진행되는 워크플로에 적합 + - 중앙조정 기능이 없기 때문에 단순한 워크플로에 적합한 것 + - 성능이 높아야 하고, 확장성도 추구한다면 가장 적합 +- 결합도가 매우 낮은 대신, 복잡도가 매우 높다 (코레오그래피 때문) +- 확장성, 탄력성은 결합도가 낮으므로 같이 낮음 +- 응답성 높음 + +--- + +### 상태 관리와 최종 일관성 + +- 상태 관리와 최종 일관성은 유한 상태 기계를 통해 현재 사가 상태를 파악하고 오류를 해결하는 방법 + - 사가 상태 기계: 분산 아키텍처에서 있을 법한 모든 가능한 경로를 기술하는 패턴 + - 각 상태가 변경될 때마다 수행할 액션과 전이 상태가 등장 + - 모든 상태 전이와 그에 해당하는 액션 목록을 정리하고, 이를 토대로 코드로 구현하는 것이 좋음 + - 사가 관리 기법: 상태들을 enum화 하고 트랜잭션을 클래스로 구현하는 것 같다 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/13.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/13.md index e4459439..9c3d8c44 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/13.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/13.md @@ -1,47 +1,53 @@ -## Chapter 14: 분석 데이터 관리 +## Chapter 13: 계약 ### 개요 -- 운영 데이터와 분석 데이터를 분리하려면? - - 두 종류의 데이터는 용도가 완전히 다르므로 +- 계약: 종류가 다른 아키텍처 파트가 어떻게 연결될 것인지 정의한 것 + - 아키텍처의 거의 모든 부분에서 영향을 끼친다 +- 하드 파트 계약: 어떤 정보나 디펜던시를 전달하기 위해, 아키텍처의 각 파트에서 사용되는 포맷 +- 계약이란 곧 프레임워크와 라이브러리 간의 디펜던시, 통합점, 각 서비스간 통신 등 서로를 연결시키는 모든 기술들을 포괄하는 개념 --- -### 데이터 웨어하우스 - -- 모든 어플리케이션이 모놀리식일 때의 이야기 -- 데이터 웨어하우스 패턴을 통해 쿼리 가능한 분석 데이터를 제공하려고 했다 -- 운영 데이터들이 개별 데이터베이스들에 각각 들어있으므로, 이를 한번에 쿼리하고 분석값을 내놓는 것은 어렵기 때문에, 분석용 데이터는 웨어하우스로 추출 -- 데이터 웨어하우스는 데이터를 반정규화 하여 처리 속도를 높이고, 쿼리를 단순하게 한다 -- 각 디비별 내장 매커니즘을 사용하여 스키마를 웨어하우스용 스키마로 변환해야 하는데, 스키마가 변경되면 이걸 반복해야 하므로 변경 관리가 어렵다 -- 데이터가 웨어하우스에 머무르는 구조라, 모든 분석은 웨어하우스가 전담한다 - - 따라서 데이터 분석자도 데이터 웨어하우스를 바라보고 사용한다 - - 분석을 위해서는 도메인 지식이 필요 -- 단점 - - 통합 취약성: 특정 도메인 변경 시 관련 스키마도 함께 변경해야 한다 - - 웨어하우스 간에 온갖 데이터가 복잡하게 엮여있어, 이를 분석하기 위해 높은 도메인 지식과 모든 분야의 사람들이 달려들어서 분석과 데이터 변경을 도와야 한다 - - 대체 스키마 구축을 통해 시스템이 점점 복잡해진다 - - 아무튼 매우 복잡한 것에 비해 비즈니스적 가치는 떨어져서, 실패한 방식이 되었다 - - 유지보수도 매우 비쌌고, 병목 유발, 등등 +### 엄격한 계약 vs 느슨한 계약 + +- 엄격한 계약: 이름, 타입, 순서 등 세부사항을 전부 준수하고, 모호한 부분을 남기지 않음 + - 단, 여러 아키텍처 파트에서 두루 쓰이면서 자주 변경되는 경우, 엄격한 계약에 취약점이 생길 수 있다 + - JSON 에 키, 값 쌍을 엄격하게 제한할 수 있다 +- 느슨한 계약: 커플링이 느슨한 경우 + - REST, 그래프QL 등 + - 다른 개발자가 하나의 리소스와 기능을구축하고 이 리소스를 확장한다고 해도, 특정 기능이 갑자기 문제가 생기지 않는 경우 +- 필요한 정보 외에도 갖은 정보들을 다 계약에 넣어버릴 경우, 취약점이 생기기 쉽다 + - 예를 들어, 고객의 위시리스트는 고객의 이름 식별자만 있으면 된다 + - 허나 고객의 성별, 나이 등의 정보까지 제공해버리면 안티패턴 + - 또한 해당 정보가 수정될 경우 계약이 깨지면서 위시리스트 기능까지 수정해야 할 수도 있다 +- 트레이드오프 + - 엄격한 계약 + - 계약 충실도 보장 (계약만으로 스키마 검증 가능) + - 버저닝 + - 장점이자 단점인데, 적절하지 못한 버저닝 (버전을 너무 많이 만들거나 너무 적게 만들기) 는 서비스를 더 복잡하게 만든다 + - 빌드 시 검증이 쉽다 + - 문서화하기 좋음 + - 커플링이 단단해짐 (한 쪽 변경하면 다른 쪽도 변경해야 함) + - 느슨한 계약 + - 높은 디커플링, 매우 유연함 + - 스키마 정보가 엄격하지 않으므로, 계약을 더 자유롭게 발전 가능 + - 계약 자체가 엄격하지 않으므로, 이름 - 값 쌍 누락 또는 철자 오류 등 결합이 발생할 여지가 큼 + - 피트니스 함수를 통해 느슨한 계약을 수행하는 데 필요한 정보가 모두 들어오는지 확인이 필요 +- 마이크로서비스에서는? + - 여러 서비스의 관계와 전달되는 정보, 결합도를 생각해야 한다 +- 컨슈머 주도 계약 + - 사용자가 서비스 제공자로부터 받고 싶은 정보를 계약에 넣고, 이를 토대로 빌드에 포함시켜 계약 테스트를 수행하는 기법 + - 필요에 따라 계약을 엄격하게 하거나, 느슨하게 할 수 있다 + - 자동 테스트로 테스트 가능하므로 이 부분에선 엄격할 수 있다 + - 단, 기술자가 이 절차들을 정확히 인지하고 지켜야 한다 --- -### 데이터 레이크 +### 스탬프 커플링 -- 데이터 웨어하우스의 중앙화 모델과 파이프라인은 그대로 -- 변환 후 적재 방식을, 적재 후 변환 방식으로 바꿈 - - 스키마 변환 필요성이 줄어들어, 데이터가 있는 그대로 저장됨 - - 이 데이터들을 분석가들이 필요한 형태로 가공하여 응답해주는 것 -- 이 중에서 필요한 데이터를 골라내기가 어렵다 -- 민감정보가 같이 저장되므로, 사생활 침해의 여지가 있다 -- 기술 분할에 초점을 둠 (요즘 대세는 도메인 분할) - ---- - -### 데이터 메시 - -- 분석 데이터를 탈중앙화 방식으로 접근하고 관리 -- 도메인 오너십: 각 데이터별로 출처가 되거나 일급 컨슈머가 되는 서비스들이 데이터를 소유하고 관리한다 -- 데이터를 프로덕트로 서비스하는 개념을 도입하였고, 데이터 프로덕트 퀀텀을 통해 데이터를 적절하게 찾아내고 이해하기 쉽게끔 관리한다 -- 도메인 팀이 데이터를 관리할 수 있는 셀프 서비스 플랫폼을 두고 있음 -- 데이터 프로덕트 퀀텀 +- 서비스 끼리 매우 큰 데이터를 주고받지만, 각 서비스는 그 데이터 안에서도 매우 작은 일부만 사용하는 경우 +- 위의 위시리스트 예시에서, 고객의 이름 (또는 ID) 만 있으면 되지만 모든 회원 정보를 전부 제공하는 경우? +- 데이터 때문에 계약에 과도한 커플링이 발생하면서, 전체 구조가 매우 취약해진다 +- 대역폭에 비해 너무 큰 데이터가 오고가면서 통신에 문제가 생길 수 있다 +- 코레오그래피 방식을 사용할 수 밖에 없는 경우, 스탬프 커플링을 이용하여 도메인 정보, 워크플로 상태를 계약에 넣어 전달하면 각 서비스는 이를 받아 계약 상태와 워크플로 상태를 업데이트하여 다음 서비스에 전달할 수 있다 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/14.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/14.md index e98e08c4..e4459439 100644 --- a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/14.md +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/14.md @@ -1,52 +1,47 @@ -### Chapter 15: 자신만의 트레이드오프 분석 +## Chapter 14: 분석 데이터 관리 ### 개요 -- 책에서 살펴본 분산 아키텍처들과 각 트레이드오프를 고려하여 적재적소에 사용하는 스킬이 필요하겠다 -- 다음 3단계를 거침 - - 어느 파트가 서로 연관되어 있는지 확인 (연관된 차원 확인) - - 어떻게 서로 결합되어 있는지 확인 - - 상호 의존적 시스템의 변경 영향도 파악 후 트레이드오프 파악 +- 운영 데이터와 분석 데이터를 분리하려면? + - 두 종류의 데이터는 용도가 완전히 다르므로 --- -### 서로 연관된 차원 확인 - -- 커플링 - - X를 변경하면 그 때문에 Y도 변경해야 할까? 를 생각하면 된다 -- 결합점 분석 - - 결합점을 식별하면, 각 특성들을 조합하여 적절한 아키텍처를 찾아내면 된다 - - 동기 / 비동기 여부, 일관성 방식, 오케스트레이션 / 코레오그래피 - - 결합도, 복잡도, 응답성 / 가용성, 확장성 / 탄력성 - - 각 패턴을 분석하고, 특성을 비교하면 몇 가지 특징이 보인다 - - 결합도와 확장성 / 탄력성은 반비례한다 - - 결합도가 높아질 수록 확장성은 떨어짐 - - 응답성 / 가용성과 결합도 또한 어느정도 반비례한다 - - 여러 차원을 조합해보면서 의미를 파악하기 위해, 경우의 수 매트릭스를 작성하는 것도 좋다 -- 트레이드오프 평가 - - if 시나리오를 반복하여 주어진 상황에서의 각 특성 선택 시 트레이드오프를 고민한다 - -### 트레이드오프 기법 - -- 정성적 분석 vs 정량적 분석 - - 각 표들은 전부 정성적 분석에 근거한 자료들이다 - - 대량의 데이터에 통계적 분석 기법을 동원하여 정량적 분석도 가능할 것 -- MECE 리스트 - - 상호 배제, 전체 포괄 - - 상호 배제: 비교 대상간 서로 기능이 겹치지 않아야 한다 - - 다른 부분은 무시하고 특정 기능만 비교한다는 전제가 있어야 함 - - 전체 포괄: 의사 결정 과정에서 모든 가능성을 짚어보고, 명백한 기능은 빠트리면 안됨 -- 콘텍스트 왜곡의 함정 - - 트레이드오프 검토 시에는 콘텍스트에 따라 의사 결정을 해야 한다 - - 그렇지 않으면 트레이드오프 분석 결과가 외부 요인에 막대한 영향을 받게 되므로 - - 분석 결과에 특정한 부가 콘텍스트가 결여되어 있다면, 실제 적용 시 무용지물이 된다 - - 의사 결정 콘텍스트를 정확하게 좁혀가면 아키텍트가 생각해야 할 것들이 줄고, 설계가 단순해진다 - - 만약에? 게임을 반복하여 아키텍처 차원간 영향을 꼼꼼히 고려해야 한다 -- 모델과 연관된 도메인 케이스 - - 도메인 동인을 추가하여 아키텍트가 가능한 방안을 걸러내고, 트레이드오프에 집중하는 데에 도움이 된다 -- 차고 넘치는 증거보다 한마디 결론이 낫다 - - 트레이드오프 분석에 온갖 정보를 수집하려고 하려는 사람이 있는데, 정보의 양 때문에 질이 묻힐 가능성이 있다 - - 중요한 핵심 주제로만 좁히는 것이 낫다 -- 터무니없는 말과 에반젤리즘은 금물 - - 어떠한 신기술이 좋아보인다고 해서 너무 매몰되지 말라는 뜻 - - 장점과 단점을 정직하게 평가한 자료를 이용하여 검토해야 한다 +### 데이터 웨어하우스 + +- 모든 어플리케이션이 모놀리식일 때의 이야기 +- 데이터 웨어하우스 패턴을 통해 쿼리 가능한 분석 데이터를 제공하려고 했다 +- 운영 데이터들이 개별 데이터베이스들에 각각 들어있으므로, 이를 한번에 쿼리하고 분석값을 내놓는 것은 어렵기 때문에, 분석용 데이터는 웨어하우스로 추출 +- 데이터 웨어하우스는 데이터를 반정규화 하여 처리 속도를 높이고, 쿼리를 단순하게 한다 +- 각 디비별 내장 매커니즘을 사용하여 스키마를 웨어하우스용 스키마로 변환해야 하는데, 스키마가 변경되면 이걸 반복해야 하므로 변경 관리가 어렵다 +- 데이터가 웨어하우스에 머무르는 구조라, 모든 분석은 웨어하우스가 전담한다 + - 따라서 데이터 분석자도 데이터 웨어하우스를 바라보고 사용한다 + - 분석을 위해서는 도메인 지식이 필요 +- 단점 + - 통합 취약성: 특정 도메인 변경 시 관련 스키마도 함께 변경해야 한다 + - 웨어하우스 간에 온갖 데이터가 복잡하게 엮여있어, 이를 분석하기 위해 높은 도메인 지식과 모든 분야의 사람들이 달려들어서 분석과 데이터 변경을 도와야 한다 + - 대체 스키마 구축을 통해 시스템이 점점 복잡해진다 + - 아무튼 매우 복잡한 것에 비해 비즈니스적 가치는 떨어져서, 실패한 방식이 되었다 + - 유지보수도 매우 비쌌고, 병목 유발, 등등 + +--- + +### 데이터 레이크 + +- 데이터 웨어하우스의 중앙화 모델과 파이프라인은 그대로 +- 변환 후 적재 방식을, 적재 후 변환 방식으로 바꿈 + - 스키마 변환 필요성이 줄어들어, 데이터가 있는 그대로 저장됨 + - 이 데이터들을 분석가들이 필요한 형태로 가공하여 응답해주는 것 +- 이 중에서 필요한 데이터를 골라내기가 어렵다 +- 민감정보가 같이 저장되므로, 사생활 침해의 여지가 있다 +- 기술 분할에 초점을 둠 (요즘 대세는 도메인 분할) + +--- + +### 데이터 메시 + +- 분석 데이터를 탈중앙화 방식으로 접근하고 관리 +- 도메인 오너십: 각 데이터별로 출처가 되거나 일급 컨슈머가 되는 서비스들이 데이터를 소유하고 관리한다 +- 데이터를 프로덕트로 서비스하는 개념을 도입하였고, 데이터 프로덕트 퀀텀을 통해 데이터를 적절하게 찾아내고 이해하기 쉽게끔 관리한다 +- 도메인 팀이 데이터를 관리할 수 있는 셀프 서비스 플랫폼을 두고 있음 +- 데이터 프로덕트 퀀텀 diff --git a/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/15.md b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/15.md new file mode 100644 index 00000000..e98e08c4 --- /dev/null +++ b/2026/Fundamentals_of_Software_Architecture_2nd_Edition/chichoon/15.md @@ -0,0 +1,52 @@ +### Chapter 15: 자신만의 트레이드오프 분석 + +### 개요 + +- 책에서 살펴본 분산 아키텍처들과 각 트레이드오프를 고려하여 적재적소에 사용하는 스킬이 필요하겠다 +- 다음 3단계를 거침 + - 어느 파트가 서로 연관되어 있는지 확인 (연관된 차원 확인) + - 어떻게 서로 결합되어 있는지 확인 + - 상호 의존적 시스템의 변경 영향도 파악 후 트레이드오프 파악 + +--- + +### 서로 연관된 차원 확인 + +- 커플링 + - X를 변경하면 그 때문에 Y도 변경해야 할까? 를 생각하면 된다 +- 결합점 분석 + - 결합점을 식별하면, 각 특성들을 조합하여 적절한 아키텍처를 찾아내면 된다 + - 동기 / 비동기 여부, 일관성 방식, 오케스트레이션 / 코레오그래피 + - 결합도, 복잡도, 응답성 / 가용성, 확장성 / 탄력성 + - 각 패턴을 분석하고, 특성을 비교하면 몇 가지 특징이 보인다 + - 결합도와 확장성 / 탄력성은 반비례한다 + - 결합도가 높아질 수록 확장성은 떨어짐 + - 응답성 / 가용성과 결합도 또한 어느정도 반비례한다 + - 여러 차원을 조합해보면서 의미를 파악하기 위해, 경우의 수 매트릭스를 작성하는 것도 좋다 +- 트레이드오프 평가 + - if 시나리오를 반복하여 주어진 상황에서의 각 특성 선택 시 트레이드오프를 고민한다 + +### 트레이드오프 기법 + +- 정성적 분석 vs 정량적 분석 + - 각 표들은 전부 정성적 분석에 근거한 자료들이다 + - 대량의 데이터에 통계적 분석 기법을 동원하여 정량적 분석도 가능할 것 +- MECE 리스트 + - 상호 배제, 전체 포괄 + - 상호 배제: 비교 대상간 서로 기능이 겹치지 않아야 한다 + - 다른 부분은 무시하고 특정 기능만 비교한다는 전제가 있어야 함 + - 전체 포괄: 의사 결정 과정에서 모든 가능성을 짚어보고, 명백한 기능은 빠트리면 안됨 +- 콘텍스트 왜곡의 함정 + - 트레이드오프 검토 시에는 콘텍스트에 따라 의사 결정을 해야 한다 + - 그렇지 않으면 트레이드오프 분석 결과가 외부 요인에 막대한 영향을 받게 되므로 + - 분석 결과에 특정한 부가 콘텍스트가 결여되어 있다면, 실제 적용 시 무용지물이 된다 + - 의사 결정 콘텍스트를 정확하게 좁혀가면 아키텍트가 생각해야 할 것들이 줄고, 설계가 단순해진다 + - 만약에? 게임을 반복하여 아키텍처 차원간 영향을 꼼꼼히 고려해야 한다 +- 모델과 연관된 도메인 케이스 + - 도메인 동인을 추가하여 아키텍트가 가능한 방안을 걸러내고, 트레이드오프에 집중하는 데에 도움이 된다 +- 차고 넘치는 증거보다 한마디 결론이 낫다 + - 트레이드오프 분석에 온갖 정보를 수집하려고 하려는 사람이 있는데, 정보의 양 때문에 질이 묻힐 가능성이 있다 + - 중요한 핵심 주제로만 좁히는 것이 낫다 +- 터무니없는 말과 에반젤리즘은 금물 + - 어떠한 신기술이 좋아보인다고 해서 너무 매몰되지 말라는 뜻 + - 장점과 단점을 정직하게 평가한 자료를 이용하여 검토해야 한다