서비스는 아키텍처에서 특별한 위치를 차지하는가? 마틴은 서비스에 대한 오해를 지적한다.
서비스에 대한 흔한 오해
마이크로서비스가 인기를 얻으면서 많은 오해가 생겼다.
flowchart TB
subgraph Misconceptions [흔한 오해]
M1[서비스는 디커플링된다]
M2[서비스는 독립 개발/배포 가능하다]
M3[마이크로서비스 = 좋은 아키텍처]
end
오해 1: 서비스는 디커플링된다
네트워크로 분리되어 있으니 디커플링된 것인가?
flowchart LR
SA[Service A] -->|HTTP| SB[Service B]
subgraph Reality [현실]
R1[공유 데이터 = 결합]
R2[인터페이스 변경 = 양쪽 영향]
R3[네트워크 오류 처리 필요]
end
| |
실제 결합 요소:
| 결합 유형 | 설명 | 영향 |
|---|---|---|
| 데이터 결합 | 같은 DB 공유 | 스키마 변경 시 함께 변경 |
| API 결합 | 서비스 간 API 호출 | 인터페이스 변경 시 소비자 영향 |
| 의미 결합 | 같은 개념(Customer 등) 공유 | 비즈니스 로직 변경 시 영향 |
오해 2: 서비스는 독립 개발/배포된다
실제로는:
flowchart TB
subgraph SharedThings [공유하는 것들]
SCHEMA[데이터 스키마]
API[API 계약]
MSG[메시지 형식]
end
CHANGE[변경] --> SharedThings
SharedThings --> S1[Service A 수정]
SharedThings --> S2[Service B 수정]
SharedThings --> S3[Service C 수정]
| |
| 공유 항목 | 변경 시 영향 |
|---|---|
| 데이터 스키마 | 모든 서비스 함께 변경 |
| API 계약 | 모든 소비자 영향 |
| 메시지 형식 | 모든 구독자 영향 |
| 공유 라이브러리 | 모든 사용처 재배포 |
택시 집계 예제
마틴은 택시 배차 시스템을 예로 든다.
초기 설계
flowchart LR
subgraph Microservices [마이크로서비스 아키텍처]
TF[TaxiFinder
택시 찾기]
TS[TaxiSelector
택시 선택]
TD[TaxiDispatcher
택시 배차]
end
USER[사용자] --> TF --> TS --> TD --> TAXI[택시]
각 서비스가 독립적으로 보인다…
새 요구사항: “고양이 운송 서비스 추가”
flowchart TB
REQ[새 요구사항:
고양이 운송 서비스]
TF[TaxiFinder
- 고양이 허용 차량 필터]
TS[TaxiSelector
- 고양이 운송료 계산]
TD[TaxiDispatcher
- 고양이 알림 전송]
REQ --> TF
REQ --> TS
REQ --> TD
모든 서비스가 변경 필요! 왜?
| |
“서비스가 횡단 관심사를 공유하기 때문에, 기능이 여러 서비스에 걸쳐 흩어진다.”
서비스 vs 아키텍처 경계
중요한 통찰: 서비스는 프로세스 경계이지, 아키텍처 경계가 아니다.
flowchart TB
subgraph Service [하나의 서비스]
CTRL[Controller
UI 어댑터]
UC[Use Case
비즈니스 로직]
GW[Gateway
데이터 어댑터]
CTRL --> UC --> GW
end
subgraph Inside [서비스 내부에도 경계 필요]
B1[UI ↔ 비즈니스]
B2[비즈니스 ↔ 데이터]
end
서비스 안에서도 Clean Architecture
| |
서비스의 진짜 가치
서비스가 제공하는 진짜 가치:
flowchart TB
subgraph RealValue [서비스의 진짜 가치]
SCALE[확장성
여러 인스턴스]
TEAM[팀 독립성
팀별 서비스]
TECH[기술 다양성
다른 언어/DB]
DEPLOY[배포 유연성
독립 배포 가능]
end
| 가치 | 설명 |
|---|---|
| 확장성 | 필요한 서비스만 인스턴스 추가 |
| 팀 독립성 | 각 팀이 자신의 서비스 소유 |
| 기술 다양성 | 서비스별 다른 기술 스택 가능 |
| 배포 유연성 | 전체 재배포 없이 일부만 |
하지만…
flowchart LR
VALUE[이런 가치들]
MUST["반드시 서비스여야얻는 건 아니다"]
VALUE --> MUST
- 확장성: 컴포넌트 분리로도 가능
- 팀 독립성: 모듈 분리로도 가능
- 기술 다양성: 플러그인으로도 가능
결론: 서비스와 아키텍처
| |
핵심 요약
| 오해 | 진실 |
|---|---|
| 서비스 = 디커플링 | 공유 데이터/API로 결합됨 |
| 서비스 = 독립 배포 | 공유 요소 변경 시 함께 배포 |
| 서비스 = 아키텍처 경계 | 프로세스 경계일 뿐 |
| 마이크로서비스 = 좋은 아키텍처 | 내부 아키텍처가 더 중요 |
“서비스는 프로세스 경계이지, 아키텍처 경계가 아니다. 서비스 안에서도 Clean Architecture가 필요하다.” — Robert C. Martin
![Featured image of post [Clean Architecture] 37. 서비스: 아키텍처 경계인가?](/post/cleanarchitecture/37-services-architecture-boundaries-microservices/wordcloud_hu_353ca2dc30131fe.png)
![[Clean Architecture] 35. 레이어와 경계](/post/cleanarchitecture/35-layers-and-boundaries-practical-setup/wordcloud_hu_cbbe4cbe47ba9693.png)
![[Clean Architecture] 36. 메인 컴포넌트](/post/cleanarchitecture/36-main-component-lowest-level-policy/wordcloud_hu_60ce8590c56aed0e.png)
![[Clean Architecture] 37. 서비스: 아키텍처 경계인가?](/post/cleanarchitecture/37-services-architecture-boundaries-microservices/wordcloud_hu_717de3c0940ae951.png)
![[Clean Architecture] 38. 테스트 경계](/post/cleanarchitecture/38-test-boundary-testing-as-system-part/wordcloud_hu_8cf965efc2badb46.png)
![[Clean Architecture] 39. 클린 임베디드 아키텍처](/post/cleanarchitecture/39-clean-embedded-architecture-hardware-separation/wordcloud_hu_f80f190279d491eb.png)
![[Clean Architecture] 28. 경계 해부학: 모놀리스에서 서비스까지](/post/cleanarchitecture/28-boundary-anatomy-monolith-to-services/wordcloud_hu_cbdfd79295eecd4.png)
![[Clean Architecture] 26. 독립성: 유스케이스, 운영, 개발, 배포](/post/cleanarchitecture/26-independence-usecase-operation-development/wordcloud_hu_4f6373b2a6991347.png)
![[Clean Architecture] 27. 경계: 선 긋기와 플러그인 아키텍처](/post/cleanarchitecture/27-boundaries-drawing-lines-plugin-architecture/wordcloud_hu_fc36676e3ba6ff35.png)
![[Clean Architecture] 34. 부분적 경계](/post/cleanarchitecture/34-partial-boundaries-cost-benefit-balance/wordcloud_hu_466cf7f5f276e60b.png)
![[Clean Architecture] 03. 헥사고날 아키텍처 (Ports and Adapters)](/post/cleanarchitecture/03-hexagonal-architecture-ports-adapters/wordcloud_hu_cb3987382ba39fc1.png)