0. 들어가며
앞선 글에서 우리는 모놀리식 아키텍처에서 시작하여 모듈형 모놀리스, 클린 아키텍처, 헥사고날 아키텍처로 이어지는 아키텍처의 진화 과정을 살펴보았다. 이러한 중간 단계들은 결국 더 높은 수준의 유연성과 확장성을 추구하기 위한 과정이었다. 그렇다면 이러한 진화의 최종 목적지는 어디일까? 많은 조직이 현재 주목하고 있는 방향이 바로 마이크로서비스 아키텍처(MSA)다.
마이크로서비스 아키텍처는 단순히 기술적인 변화만을 의미하지 않는다. 이는 조직 구조, 개발 프로세스, 배포 전략, 심지어 사고방식까지 변화시키는 패러다임 전환에 가깝다. 하지만 모든 조직이 MSA를 도입해야 하는 것은 아니다. 오히려 잘못된 상황에서 MSA를 도입하면 '분산 모놀리스'라는 최악의 상황에 빠질 수 있다.
이번 글에서는 마이크로서비스 아키텍처의 정의와 장단점을 명확히 이해하고, 어떤 상황에서 MSA를 도입해야 하는지 판단하는 기준을 살펴본다. 또한 MSA의 가장 중요한 첫 단계인 서비스 분해(Decomposition) 전략에 대해 상세히 알아보고, 실제 이커머스 도메인을 어떻게 분해할 수 있는지 예시를 통해 살펴볼 것이다.
1. Microservice Architecture 정의
1.1. 마이크로서비스란 무엇인가?
마이크로서비스 아키텍처는 하나의 애플리케이션을 여러 개의 작은 독립적인 서비스로 분할하는 아키텍처 스타일이다. 각 서비스는 특정 비즈니스 기능을 담당하며, 독립적으로 개발, 배포, 확장될 수 있다.
공식적인 정의 (Martin Fowler & James Lewis):
"마이크로서비스 아키텍처는 단일 애플리케이션을 작은 서비스들의 모음으로 개발하는 접근 방식이다. 각 서비스는 자체 프로세스에서 실행되며, 가벼운 통신 메커니즘(보통 HTTP 기반 API)을 통해 상호작용한다. 이 서비스들은 비즈니스 역량을 중심으로 구축되며, 완전히 자동화된 배포 기계에 의해 독립적으로 배포된다. 이러한 서비스들을 중앙 집중식 관리가 거의 없으며, 서로 다른 프로그래밍 언어와 데이터 저장 기술을 사용할 수 있다."
1.2. 마이크로서비스의 핵심 특징
비즈니스 역량 중심의 모델링
- 기술 계층(프레젠테이션, 비즈니스, 데이터)이 아닌 비즈니스 기능 단위로 서비스가 구성된다.
- 예: '사용자 관리 서비스', '주문 처리 서비스', '결제 서비스'
분산된 데이터 관리
- 각 서비스는 자체 데이터베이스를 소유한다.
- 다른 서비스의 데이터베이스에 직접 접근할 수 없다.
- 서비스 간 데이터 공유는 API를 통해서만 이루어진다.
독립적인 배포
- 각 서비스는 다른 서비스와 독립적으로 배포될 수 있다.
- 하나의 서비스를 변경해도 전체 시스템을 재배포할 필요가 없다.
- 롤백도 서비스 단위로 가능하다.
기술 스택의 다양성
- 서비스별로 최적화된 기술 스택을 선택할 수 있다.
- 예: 검색 서비스는 Elasticsearch, 결제 서비스는 관계형 데이터베이스
인프라 자동화
- 컨테이너(Docker), 오케스트레이션(Kubernetes), CI/CD 파이프라인이 필수적이다.
- 수동으로 수십 개의 서비스를 관리하는 것은 불가능하다.
2. 마이크로서비스의 장점과 단점
2.1. 장점
1. 독립적인 개발과 배포
각 서비스를 담당하는 팀은 자신의 서비스를 독립적으로 개발하고 배포할 수 있다. 이는 개발 속도를 획기적으로 높여준다.
// 팀 A는 주문 서비스를 개발 중
@RestController
@RequestMapping("/orders")
public class OrderController {
// 팀 A만 이 코드를 관리
}
// 팀 B는 결제 서비스를 개발 중 (완전히 독립적)
@RestController
@RequestMapping("/payments")
public class PaymentController {
// 팀 B만 이 코드를 관리
}
팀 간 충돌이 줄어들고, 각 팀은 자신의 일정에 따라 릴리즈할 수 있다.
2. 기술 스택의 다양성
서비스의 특성에 맞는 최적의 기술을 선택할 수 있다.
[검색 서비스] → Elasticsearch (전문 검색에 최적화)
[추천 서비스] → Python + TensorFlow (ML에 강점)
[주문 서비스] → Java + MariaDB (트랜잭션 안정성)
[실시간 알림] → Node.js + WebSocket (비동기 I/O)
3. 탄력적 확장
필요한 서비스만 선택적으로 확장할 수 있어 리소스 효율성이 높다.
# docker-compose.yml
services:
order-service:
deploy:
replicas: 5 # 주문 트래픽이 많아서 5개 인스턴스
user-service:
deploy:
replicas: 2 # 사용자 관리는 상대적으로 적게
product-service:
deploy:
replicas: 3 # 상품 조회는 중간 수준
4. 장애 격리
하나의 서비스 장애가 전체 시스템으로 전파되지 않는다.
[시나리오] 결제 서비스에 장애 발생
❌ 모놀리스: 결제 모듈 장애 → 전체 애플리케이션 중단
✅ MSA: 결제 서비스 장애 → 주문 생성 불가, 하지만 상품 조회는 정상 동작
5. 조직 구조와의 일치
Conway의 법칙에 따라 조직 구조를 반영한 아키텍처를 구성할 수 있다.
[조직 구조]
└── 이커머스 개발본부
├── 주문팀 → 주문 서비스 담당
├── 결제팀 → 결제 서비스 담당
├── 상품팀 → 상품 카탈로그 서비스 담당
└── 고객팀 → 사용자 서비스 담당
2.2. 단점
1. 분산 시스템의 복잡성
네트워크 통신, 장애 처리, 트랜잭션 관리 등 분산 시스템 고유의 복잡성이 추가된다.
// 모놀리스: 간단한 메서드 호출
Order order = orderRepository.findById(orderId);
User user = userRepository.findByUserId(order.getUserId());
// MSA: 네트워크 호출
Order order = orderService.getOrder(orderId);
User user = userServiceClient.getUser(order.getUserId());
// ↑ 네트워크 지연, 타임아웃, 회로 차단기, 재시도 로직 등 필요
2. 운영 오버헤드
모니터링, 로깅, 추적을 위한 인프라가 추가로 필요하다.
모놀리스: 1개 서비스 모니터링
MSA: 20개 서비스 × 3개 인스턴스 = 60개 프로세스 모니터링
3. 데이터 일관성 문제
분산 트랜잭션을 보장하기 어려워 최종 일관성(Eventual Consistency)을 수용해야 한다.
// 모놀리스: ACID 트랜잭션 보장
@Transactional
public void createOrder(Order order) {
orderRepository.save(order); // 주문 저장
inventoryRepository.decreaseStock(); // 재고 차감
paymentRepository.processPayment(); // 결제 처리
// 모두 성공하거나 모두 실패
}
// MSA: 각 서비스별 로컬 트랜잭션, 전체 일관성은 SAGA 패턴으로
public void createOrder(Order order) {
orderService.createOrder(order); // 1. 주문 생성
// ↑ 여기서 실패하면? 재고는? 결제는?
inventoryService.decreaseStock(); // 2. 재고 차감
paymentService.processPayment(); // 3. 결제 처리
}
4. 테스트 복잡성
서비스 간 의존 관계로 인한 통합 테스트가 어려워진다.
단위 테스트: 각 서비스 내부만 테스트 (쉬움)
통합 테스트: 여러 서비스 연동 테스트 (어려움)
E2E 테스트: 전체 시스템 테스트 (매우 어려움)
5. 초기 개발 비용 증가
분산 시스템 구축에 필요한 인프라와 설계에 더 많은 초기 투자가 필요하다.
3. 언제 MSA를 쓰면 안 되는가
3.1. MSA 도입을 피해야 하는 상황
1. 소규모 팀 (1-5명)
소규모 팀이 여러 서비스를 관리하는 것은 오히려 생산성을 떨어뜨린다.
❌ 잘못된 예: 3명의 개발자가 10개의 마이크로서비스 관리
✅ 올바른 선택: 모놀리스로 시작, 필요시 모듈화
2. 스타트업 초기 단계
제품-시장 적합성(Product-Market Fit)을 찾기 전에는 빠른 개발과 피벗이 더 중요하다.
스타트업 생존 공식: 속도 > 확장성
MSA는 속도를 희생하고 확장성을 얻는 트레이드오프
3. 단순한 CRUD 애플리케이션
복잡한 비즈니스 로직이 없는 단순한 애플리케이션은 모놀리스가 적합하다.
블로그, 간단한 게시판, 명함 관리 앱 → 모놀리스로 충분
4. 분산 시스템 운영 경험이 부족한 팀
MSA는 분산 시스템에 대한 깊은 이해를 요구한다. 경험 없이 도입하면 실패 확률이 높다.
필요한 역량:
- 컨테이너(Docker)와 오케스트레이션(Kubernetes)
- CI/CD 파이프라인 구축
- 분산 로깅, 모니터링, 추적
- 장애 처리와 회복 탄력성(Resilience) 패턴
- DevOps 문화
3.2. 의사결정 매트릭스
| 상황 | 모놀리스 | MSA |
| 팀 규모 1-5명 | ✅ | ❌ |
| 팀 규모 20명 이상 (여러 팀) | ❌ | ✅ |
| 스타트업 (초기 단계) | ✅ | ❌ |
| 대기업 (복잡한 도메인) | ❌ | ✅ |
| 단순 CRUD 애플리케이션 | ✅ | ❌ |
| 높은 확장성 요구사항 | ❌ | ✅ |
| 빠른 개발 속도 필요 | ✅ | ❌ |
| 다양한 기술 도입 필요 | ❌ | ✅ |
| 분산 시스템 경험 부족 | ✅ | ❌ |
4. Decomposition 전략
4.1. 서비스 분해의 핵심 원칙
좋은 서비스 분해의 기준:
- 높은 응집도(High Cohesion): 하나의 서비스는 관련된 기능들로 구성
- 낮은 결합도(Low Coupling): 서비스 간 의존성 최소화
- 비즈니스 도메인 반영: 조직의 비즈니스 구조를 반영
- 독립적 배포 가능: 각 서비스는 다른 서비스와 독립적으로 배포 가능
4.2. 분산 모놀리스의 함정
분산 모놀리스는 분산 시스템의 복잡성은 그대로 가지면서, 모놀리스의 단점까지 갖는 최악의 조합이다.
분산 모놀리스의 증상:
- 서비스 간 동기식 호출이 체인처럼 연결됨
- 하나의 트랜잭션이 여러 서비스를 거침
- 데이터베이스가 서비스 간에 공유됨 (논리적 분리만 되어 있을 뿐)
- 서비스를 독립적으로 배포할 수 없음 (함께 배포해야 함)
- 작은 변경이 여러 서비스에 영향을 미침
분산 모놀리스를 피하는 방법:
- 서비스 간 통신은 가능하면 비동기 이벤트 기반으로
- 데이터베이스는 물리적으로 분리 (다른 인스턴스, 다른 스키마)
- 서비스 경계는 비즈니스 도메인에 기반하여 설정
- API 계약(Contract)을 엄격히 정의하고 버전 관리
4.3. 분해 전략 1: 비즈니스 역량 중심 분해
비즈니스 역량(Business Capability)은 조직이 비즈니스 가치를 창출하기 위해 수행하는 활동이나 기능을 의미한다.
이커머스의 비즈니스 역량 예시:
- 상품 관리 (Product Management)
- 주문 관리 (Order Management)
- 결제 처리 (Payment Processing)
- 고객 관리 (Customer Management)
- 배송 관리 (Shipping Management)
- 재고 관리 (Inventory Management)
- 마케팅/프로모션 (Marketing & Promotion)
분해 단계:
- 비즈니스 역량 도출
- 역량 간 의존성 분석
- 서비스 경계 설정
- API 설계
4.4. 분해 전략 2: 하위 도메인 중심 분해 (DDD)
Domain-Driven Design(DDD)에서는 전체 비즈니스 도메인을 여러 개의 하위 도메인(Subdomain)으로 나눈다.
하위 도메인의 유형:
- 핵심 도메인(Core Domain): 비즈니스의 경쟁 우위를 결정짓는 가장 중요한 부분
- 예: 이커머스의 추천 엔진, 쿠팡의 로켓배송 시스템
- 지원 서브도메인(Supporting Subdomain): 핵심 도메인을 지원하는 부분
- 예: 재고 관리, 주문 처리
- 일반 서브도메인(Generic Subdomain): 모든 비즈니스에 공통적인 부분
- 예: 사용자 인증, 이메일 발송, 로깅
바운디드 컨텍스트(Bounded Context):
하위 도메인을 실제 구현으로 매핑한 것이 바운디드 컨텍스트다. 각 바운디드 컨텍스트는 독립적인 모델과 구현을 가지며, 명확한 경계를 가진다.
// 주문 컨텍스트 - '주문'의 의미
@BoundedContext(name = "order")
public class Order {
private OrderId id;
private CustomerId customerId;
private List<OrderLine> orderLines;
private Money totalAmount;
private ShippingAddress shippingAddress; // 배송지 정보 포함
}
// 결제 컨텍스트 - '주문'의 의미 (단순화됨)
@BoundedContext(name = "payment")
public class Payment {
private PaymentId id;
private OrderReference orderId; // 참조만 가짐
private Money amount;
private PaymentStatus status;
// 배송지 정보 없음
}
동일한 "주문"이라는 용어라도 컨텍스트에 따라 다른 의미를 가질 수 있다.
4.5. 분해 전략 3: 변경률 기반 분해
변경되는 빈도와 패턴에 따라 서비스를 분리하는 전략이다.
변경률이 높은 기능:
- 비즈니스 규칙이 자주 바뀌는 부분
- A/B 테스트를 자주 수행하는 부분
- 실험적인 기능
변경률이 낮은 기능:
- 안정적인 비즈니스 로직
- 규제나 컴플라이언스 관련 기능
변경률이 다른 기능들은 서로 다른 서비스로 분리하는 것이 좋다.
5. 서비스 분해 시 고려사항
5.1. 트랜잭션 경계
분산 환경에서는 ACID 트랜잭션을 보장하기 어렵다. 따라서 트랜잭션 경계를 어떻게 설정할지 고민해야 한다.
고려사항:
- 하나의 비즈니스 트랜잭션이 몇 개의 서비스를 거치는가?
- 강한 일관성이 필요한가, 최종 일관성으로 충분한가?
- 실패 시 보상 트랜잭션을 어떻게 구현할 것인가?
예시: 주문 생성 트랜잭션
[잘못된 설계] - 하나의 트랜잭션이 4개 서비스에 걸침
주문 생성 → 재고 차감 → 결제 처리 → 배송 생성
(실패 시 복잡한 보상 로직 필요)
[개선된 설계] - SAGA 패턴으로 분리
1. 주문 생성 (PENDING 상태)
2. 재고 차감 요청 (비동기)
3. 재고 차감 완료 → 결제 처리 요청
4. 결제 완료 → 배송 생성 요청
각 단계 실패 시 보상 이벤트 발생
5.2. 데이터 일관성
데이터베이스가 분리되면 데이터 일관성 유지가 어려워진다.
고려사항:
- 서비스 간 데이터 중복을 허용할 것인가?
- 참조 무결성을 어떻게 유지할 것인가?
- 데이터 동기화에 지연이 발생해도 되는가?
예시: 사용자 정보 변경
[문제] 사용자가 주소를 변경하면, 주문 서비스에도 반영되어야 하는가?
[해결 방안 1] - 이벤트 기반 동기화
UserService: UserAddressChanged 이벤트 발행
OrderService: 이벤트 구독 후 관련 주문의 배송지 정보 업데이트
[해결 방안 2] - API 기반 조회 (CQRS)
OrderService는 배송지 정보를 저장하지 않고,
주문 조회 시 UserService API를 호출하여 실시간 조회
5.3. 통신 오버헤드
서비스가 세분화될수록 네트워크 통신이 증가한다.
고려사항:
- 너무 잦은 서비스 호출이 발생하지 않는가?
- 배치 처리나 벌크 API가 필요한가?
- API Gateway에서 응답을 조합(Aggregation)할 것인가?
예시: 주문 상세 조회
[문제] 주문 조회 시 상품 정보, 사용자 정보, 배송 정보가 모두 필요하다면?
[해결 방안 1] - API Gateway에서 조합
1. 클라이언트 → API Gateway: /orders/{id}/detail
2. API Gateway → OrderService: 주문 정보 조회
3. API Gateway → ProductService: 상품 정보 조회
4. API Gateway → UserService: 사용자 정보 조회
5. API Gateway가 응답을 조합하여 반환
[해결 방안 2] - GraphQL 도입
클라이언트가 필요한 필드만 질의하면 Gateway가 처리
5.4. 서비스 경계의 진화
서비스 경계는 한 번 정해지면 영원한 것이 아니다. 시간이 지나면서 시스템의 요구사항이 변하고, 도메인에 대한 이해도 깊어지면서 경계를 재조정해야 할 수 있다.
분리(Split)가 필요한 상황:
- 특정 기능의 변경 빈도가 현저히 높은 경우
- 특정 기능의 확장 요구사항이 다른 기능과 다른 경우
- 팀이 분리되어 독립적으로 개발해야 하는 경우
통합(Merge)이 필요한 상황:
- 두 서비스 간 호출이 너무 잦은 경우
- 분리로 인한 오버헤드가 이점보다 큰 경우
- 두 서비스가 항상 함께 배포되어야 하는 경우 (분산 모놀리스 증상)
6. E-commerce 서비스 분해 예시
6.1. 도메인 분석
핵심 도메인 (Core Domain):
- 개인화 추천 엔진 (차별화 요소)
- 동적 가격 책정 (경쟁 우위)
지원 서브도메인 (Supporting):
- 주문 처리
- 재고 관리
- 결제 처리
일반 서브도메인 (Generic):
- 사용자 관리
- 인증/인가
- 알림 발송
- 로깅/모니터링
6.2. 서비스 식별 결과
┌─────────────────────────────────────────────────────────────┐
│ E-commerce MSA 아키텍처 │
├─────────────────────────────────────────────────────────────┤
│ │
│ [API Gateway] │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Core Services │ │
│ ├──────────────────┬──────────────────┬────────────────┤ │
│ │ Order Service │ Product Service │ User Service │ │
│ │ - 주문 생성 │ - 상품 카탈로그 │ - 회원가입 │ │
│ │ - 주문 조회 │ - 카테고리 │ - 로그인 │ │
│ │ - 주문 이력 │ - 상품 검색 │ - 프로필 │ │
│ ├──────────────────┼──────────────────┼────────────────┤ │
│ │ Payment Service │ Inventory Service│ Cart Service │ │
│ │ - 결제 승인 │ - 재고 관리 │ - 장바구니 │ │
│ │ - 환불 │ - 재고 차감 │ - 위시리스트 │ │
│ │ - 정산 │ - 재고 복원 │ │ │
│ └──────────────────┴──────────────────┴────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Supporting Services │ │
│ ├──────────────────┬──────────────────┬────────────────┤ │
│ │ Review Service │ Promotion Serv. │ Shipping Serv.│ │
│ │ - 리뷰 작성 │ - 쿠폰 발행 │ - 배송 추적 │ │
│ │ - 평점 │ - 프로모션 │ - 배송사 연동 │ │
│ └──────────────────┴──────────────────┴────────────────┘ │
│ ↓ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Common/Infrastructure Services │ │
│ ├──────────────────┬──────────────────┬────────────────┤ │
│ │ Notification │ Authentication │ Logging/Audit │ │
│ │ - 이메일 │ - JWT 발급 │ - 로그 수집 │ │
│ │ - SMS │ - OAuth │ - 감사 추적 │ │
│ │ - 푸시 │ - 권한 관리 │ │ │
│ └──────────────────┴──────────────────┴────────────────┘ │
└─────────────────────────────────────────────────────────────┘
6.3. 각 서비스의 책임과 경계
1. Order Service (주문 서비스)
// 주문 서비스의 책임
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
@PostMapping
public OrderResponse createOrder(@RequestBody CreateOrderRequest request) {
// 주문 생성
// - 재고 확인 (Inventory Service 호출)
// - 결제 처리 (Payment Service 호출)
// - 배송 정보 생성 (Shipping Service 호출)
}
@GetMapping("/{orderId}")
public OrderResponse getOrder(@PathVariable String orderId) {
// 주문 조회
}
@PostMapping("/{orderId}/cancel")
public void cancelOrder(@PathVariable String orderId) {
// 주문 취소
// - 재고 복원 (Inventory Service)
// - 결제 취소 (Payment Service)
}
}
2. Product Service (상품 서비스)
@RestController
@RequestMapping("/api/v1/products")
public class ProductController {
@GetMapping
public Page<ProductResponse> getProducts(@RequestParam int page, @RequestParam int size) {
// 상품 목록 조회 (페이징)
}
@GetMapping("/{productId}")
public ProductResponse getProduct(@PathVariable String productId) {
// 상품 상세 조회
}
@GetMapping("/search")
public List<ProductResponse> searchProducts(@RequestParam String keyword) {
// 상품 검색
}
}
3. Inventory Service (재고 서비스)
@RestController
@RequestMapping("/api/v1/inventory")
public class InventoryController {
@GetMapping("/{productId}")
public StockResponse getStock(@PathVariable String productId) {
// 재고 조회
}
@PostMapping("/deduct")
public void deductStock(@RequestBody DeductStockRequest request) {
// 재고 차감 (주문 시)
}
@PostMapping("/restore")
public void restoreStock(@RequestBody RestoreStockRequest request) {
// 재고 복원 (주문 취소 시)
}
}
4. Payment Service (결제 서비스)
@RestController
@RequestMapping("/api/v1/payments")
public class PaymentController {
@PostMapping
public PaymentResponse processPayment(@RequestBody PaymentRequest request) {
// 결제 처리
}
@PostMapping("/{paymentId}/refund")
public void refundPayment(@PathVariable String paymentId, @RequestBody RefundRequest request) {
// 환불 처리
}
}
6.4. 서비스 간 통신 정의
동기식 통신 (필요한 경우)
# Order Service가 Inventory Service 호출
GET /api/v1/inventory/{productId} # 재고 확인
POST /api/v1/inventory/deduct # 재고 차감
비동기식 통신 (이벤트 기반)
// Order Service가 발행하는 이벤트
public class OrderEvents {
@Value
public static class OrderPlaced {
String orderId;
String userId;
List<OrderItem> items;
Money total;
Instant occurredAt;
}
@Value
public static class OrderCancelled {
String orderId;
String reason;
Instant occurredAt;
}
}
// Inventory Service가 구독
@KafkaListener(topics = "order-placed")
public void handleOrderPlaced(OrderPlacedEvent event) {
// 재고 차감 처리
}
// Payment Service가 구독
@KafkaListener(topics = "order-placed")
public void handleOrderPlaced(OrderPlacedEvent event) {
// 결제 처리 시작
}
6.5. 분해 평가
| 서비스 | 응집도 | 결합도 | 독립성 | 비고 |
| Order Service | 높음 | 중간 | 중간 | 여러 서비스와 통신 필요 |
| Product Service | 높음 | 낮음 | 높음 | 독립적 운영 가능 |
| User Service | 높음 | 낮음 | 높음 | 독립적 운영 가능 |
| Payment Service | 높음 | 중간 | 높음 | 외부 PG사 연동 |
| Inventory Service | 높음 | 중간 | 중간 | Order와 강한 연관 |
| Cart Service | 높음 | 낮음 | 높음 | 독립적 운영 가능 |
7. 정리: 서비스 분해 체크리스트
7.1. 서비스 분해 전 확인사항
- 비즈니스 역량이 명확히 식별되었는가?
- 핵심 도메인과 지원 도메인이 구분되었는가?
- 팀 구조와 Conway의 법칙을 고려했는가?
- 트랜잭션 경계가 명확한가?
- 데이터 일관성 요구사항이 정의되었는가?
- 통신 오버헤드를 감당할 수 있는가?
7.2. 서비스 분해 후 확인사항
- 각 서비스가 높은 응집도를 가지는가?
- 서비스 간 결합도가 충분히 낮은가?
- 각 서비스를 독립적으로 배포할 수 있는가?
- API 계약(Contract)이 명확히 정의되었는가?
- 장애 격리가 가능한가?
- 분산 모놀리스 증상은 없는가?
7.3. 다음 단계로
이 글에서는 마이크로서비스 아키텍처의 기본 개념과 서비스 분해 전략을 살펴보았다. 서비스 경계를 올바르게 설정하는 것이 MSA 성공의 첫 걸음이다. 다음 글에서는 분해된 서비스들이 실제로 어떻게 통신해야 하는지에 대해 알아볼 것이다. 동기 통신 방식(REST, gRPC, GraphQL)과 API Gateway 패턴, BFF 패턴 등 실무에서 가장 많이 사용되는 통신 전략을 살펴보겠다.
'MSA > MSA 아키텍처' 카테고리의 다른 글
| [BASIC #4] 비동기 통신과 Event-Driven Architecture (0) | 2026.03.02 |
|---|---|
| [BASIC #3] MSA 동기 통신 전략과 API Gateway 패턴 (0) | 2026.03.02 |
| [BASIC #1] 마이크로서비스 아키텍처의 이해: Monolithic에서 MSA까지 (0) | 2026.03.02 |
| [5] EDA (0) | 2025.10.20 |
| [4] SAGA 패턴 (0) | 2025.10.20 |
