본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 11. 2. · 17 Views
Microservices 디자인 패턴 완벽 가이드
마이크로서비스 아키텍처의 핵심 디자인 패턴을 실전 코드로 배웁니다. API Gateway부터 Circuit Breaker까지 실무에서 바로 활용 가능한 패턴들을 다룹니다.
들어가며
이 글에서는 Microservices 디자인 패턴 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- API_Gateway_패턴
- Circuit_Breaker_패턴
- Service_Discovery_패턴
- Event_Driven_Architecture
- Saga_패턴
- BFF_Backend_For_Frontend
- Sidecar_패턴
- Strangler_Fig_패턴
- Database_Per_Service
- CQRS_Command_Query_Responsibility_Segregation
- Bulkhead_패턴
- Health_Check_패턴
1. API Gateway 패턴
개요
모든 클라이언트 요청을 단일 진입점으로 라우팅하고, 인증/로깅/라우팅을 중앙에서 관리하는 패턴입니다.
코드 예제
class APIGateway {
async route(req: Request): Promise<Response> {
await this.authenticate(req);
const service = this.getTargetService(req.url);
return await service.handle(req);
}
}
설명
클라이언트는 여러 마이크로서비스 대신 API Gateway 하나만 호출하면 됩니다. Gateway가 요청을 적절한 서비스로 라우팅합니다.
2. Circuit Breaker 패턴
개요
장애가 발생한 서비스로의 요청을 차단하여 연쇄 장애를 방지하고, 주기적으로 복구를 시도하는 패턴입니다.
코드 예제
class CircuitBreaker {
private failureCount = 0;
async call(fn: Function) {
if (this.failureCount > 5) throw new Error('Circuit Open');
try { return await fn(); }
catch(e) { this.failureCount++; throw e; }
}
}
설명
연속 실패가 임계값을 넘으면 Circuit이 열려 추가 요청을 차단합니다. 시스템 전체의 안정성을 보호합니다.
3. Service Discovery 패턴
개요
서비스 인스턴스들을 자동으로 찾고 등록하여, 동적으로 변하는 서비스 위치를 관리하는 패턴입니다.
코드 예제
class ServiceRegistry {
private services = new Map<string, string[]>();
register(name: string, url: string) {
this.services.get(name)?.push(url) ?? this.services.set(name, [url]);
}
discover(name: string) { return this.services.get(name); }
}
설명
서비스가 시작되면 자신을 레지스트리에 등록하고, 다른 서비스는 레지스트리를 조회하여 필요한 서비스를 찾습니다.
4. Event Driven Architecture
개요
서비스 간 직접 호출 대신 이벤트를 발행하고 구독하여 느슨한 결합을 구현하는 패턴입니다.
코드 예제
class EventBus {
private handlers = new Map<string, Function[]>();
publish(event: string, data: any) {
this.handlers.get(event)?.forEach(h => h(data));
}
subscribe(event: string, handler: Function) {
this.handlers.set(event, [...(this.handlers.get(event) || []), handler]);
}
}
설명
주문 서비스가 '주문완료' 이벤트를 발행하면, 재고/결제/배송 서비스가 독립적으로 반응합니다.
5. Saga 패턴
개요
분산 트랜잭션을 여러 단계의 로컬 트랜잭션으로 분할하고, 실패 시 보상 트랜잭션으로 롤백하는 패턴입니다.
코드 예제
class OrderSaga {
async execute(order: Order) {
try {
await paymentService.charge(order);
await inventoryService.reserve(order);
} catch(e) {
await paymentService.refund(order);
}
}
}
설명
결제 후 재고 확보 실패 시 자동으로 결제를 취소합니다. 분산 환경에서 데이터 일관성을 유지합니다.
6. BFF Backend For Frontend
개요
각 프론트엔드(웹, 모바일)를 위한 전용 백엔드를 두어 클라이언트별 최적화된 API를 제공하는 패턴입니다.
코드 예제
class WebBFF {
async getDashboard(userId: string) {
const [user, orders, stats] = await Promise.all([
userService.get(userId),
orderService.list(userId),
analyticsService.getStats(userId)
]);
return { user, orders, stats };
}
}
설명
웹용 BFF는 대시보드에 필요한 모든 데이터를 한 번에 조합하여 반환합니다. 모바일 BFF는 다른 구조로 응답할 수 있습니다.
7. Sidecar 패턴
개요
각 서비스 옆에 보조 컨테이너를 배치하여 로깅, 모니터링, 프록시 등의 공통 기능을 제공하는 패턴입니다.
코드 예제
class ServiceWithSidecar {
constructor(
private mainService: Service,
private logger: LoggerSidecar,
private metrics: MetricsSidecar
) {}
async handle(req: Request) {
this.metrics.record('request');
return await this.mainService.process(req);
}
}
설명
메인 서비스는 비즈니스 로직에만 집중하고, Sidecar가 로깅/메트릭 수집을 담당합니다. 관심사를 명확히 분리합니다.
8. Strangler Fig 패턴
개요
레거시 시스템을 점진적으로 마이크로서비스로 전환하기 위해 새 기능을 서서히 추가하는 패턴입니다.
코드 예제
class StranglerRouter {
async route(req: Request) {
if (this.isNewFeature(req.url)) {
return await newMicroservice.handle(req);
}
return await legacySystem.handle(req);
}
}
설명
새 기능은 마이크로서비스로 구현하고, 기존 기능은 레거시 시스템이 처리합니다. 점진적으로 레거시를 대체합니다.
9. Database Per Service
개요
각 마이크로서비스가 자신만의 독립적인 데이터베이스를 가지는 패턴으로 서비스 간 결합도를 낮춥니다.
코드 예제
class OrderService {
private db = new OrderDatabase();
async create(order: Order) {
await this.db.insert(order);
await eventBus.publish('order.created', order);
}
}
class InventoryService {
private db = new InventoryDatabase();
}
설명
주문 서비스와 재고 서비스가 각자의 DB를 사용합니다. 데이터는 이벤트로 공유하여 독립성을 유지합니다.
10. CQRS Command Query Responsibility Segregation
개요
데이터 쓰기(Command)와 읽기(Query)를 분리하여 각각을 독립적으로 최적화하는 패턴입니다.
코드 예제
class OrderCommandService {
async createOrder(order: Order) {
await writeDB.insert(order);
await eventBus.publish('order.created', order);
}
}
class OrderQueryService {
async getOrder(id: string) { return readDB.findById(id); }
}
설명
쓰기는 트랜잭션 DB를, 읽기는 최적화된 읽기 전용 DB를 사용합니다. 읽기/쓰기 성능을 독립적으로 스케일링할 수 있습니다.
11. Bulkhead 패턴
개요
시스템을 독립적인 구획으로 나누어 한 구획의 장애가 전체로 확산되지 않도록 격리하는 패턴입니다.
코드 예제
class BulkheadExecutor {
private pools = {
critical: new ThreadPool(10),
normal: new ThreadPool(5)
};
async execute(task: Task) {
const pool = task.priority === 'critical' ? this.pools.critical : this.pools.normal;
return pool.run(task);
}
}
설명
중요한 요청과 일반 요청을 별도의 스레드 풀로 처리합니다. 일반 요청 폭주가 중요 요청에 영향을 주지 않습니다.
12. Health Check 패턴
개요
각 서비스의 상태를 주기적으로 점검하여 비정상 인스턴스를 자동으로 제거하는 패턴입니다.
코드 예제
class HealthCheckEndpoint {
async check(): Promise<HealthStatus> {
const dbOk = await this.checkDatabase();
const cacheOk = await this.checkCache();
return { status: dbOk && cacheOk ? 'UP' : 'DOWN', dbOk, cacheOk };
}
}
설명
로드 밸런서가 /health 엔드포인트를 호출하여 서비스 상태를 확인합니다. 'DOWN' 응답 시 해당 인스턴스를 제외합니다.
마치며
이번 글에서는 Microservices 디자인 패턴 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#Microservices #APIGateway #CircuitBreaker #ServiceDiscovery #EventDriven
댓글 (0)
함께 보면 좋은 카드 뉴스
Istio 설치와 구성 완벽 가이드
Kubernetes 환경에서 Istio 서비스 메시를 설치하고 구성하는 방법을 초급 개발자도 쉽게 이해할 수 있도록 실무 스토리와 비유로 풀어낸 가이드입니다. istioctl 설치부터 사이드카 주입까지 단계별로 학습합니다.
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.
마이크로서비스 배포 완벽 가이드
Kubernetes를 활용한 마이크로서비스 배포의 핵심 개념부터 실전 운영까지, 초급 개발자도 쉽게 따라할 수 있는 완벽 가이드입니다. 실무에서 바로 적용 가능한 배포 전략과 노하우를 담았습니다.
관찰 가능한 마이크로서비스 완벽 가이드
마이크로서비스 환경에서 시스템의 상태를 실시간으로 관찰하고 모니터링하는 방법을 배웁니다. Resilience4j, Zipkin, Prometheus, Grafana, EFK 스택을 활용하여 안정적이고 관찰 가능한 시스템을 구축하는 실전 가이드입니다.