61 lines
4.8 KiB
Markdown
61 lines
4.8 KiB
Markdown
---
|
|
category: Unified
|
|
tags: [Architecture, Design Patterns, CQRS, Microservices, DDD]
|
|
title: CQRS (Command Query Responsibility Segregation)
|
|
description: 데이터의 상태를 변경하는 명령(Command)과 데이터를 조회하는 쿼리(Query)의 책임을 논리적 또는 물리적으로 분리하는 아키텍처 패턴
|
|
last_updated: 2026-05-02
|
|
---
|
|
|
|
# CQRS (Command Query Responsibility Segregation)
|
|
|
|
## 📌 Brief Summary
|
|
**CQRS(Command Query Responsibility Segregation)**는 시스템에서 데이터를 읽는 작업(Query)과 데이터를 쓰는 작업(Command)을 분리하는 아키텍처 패턴입니다. 복잡한 비즈니스 로직을 처리하는 쓰기 모델과 빠른 성능이 필요한 읽기 모델을 분리함으로써, 각각에 최적화된 데이터베이스 기술과 코드를 사용할 수 있게 합니다. 특히 도메인 주도 설계(DDD)와 이벤트 기반 아키텍처(EDA) 환경에서 성능 병목을 해결하고 시스템의 복잡성을 낮추는 핵심 전략으로 활용됩니다.
|
|
|
|
---
|
|
|
|
## 📖 Core Content
|
|
|
|
### 1. 근본 원리: 책임의 완벽한 분리
|
|
* **Command (명령):** 시스템의 상태를 변경합니다. 데이터의 무결성과 비즈니스 규칙을 보장해야 하므로 무거운 객체 지향 모델이나 ORM(TypeORM, Prisma 등)을 사용하여 트랜잭션을 엄격히 관리합니다. 리턴 값으로 데이터를 반환하지 않습니다.
|
|
* **Query (조회):** 상태를 변경하지 않고 데이터만 반환합니다. 복잡한 비즈니스 로직을 생략하고, 조인이나 뷰에 최적화된 가벼운 SQL 쿼리 빌더(Slonik, Kysely 등)를 사용하여 성능을 극대화합니다.
|
|
|
|
### 2. 하이브리드 패턴 (Hybrid Approach)
|
|
단일 데이터베이스를 사용하더라도 코드 레벨에서 읽기와 쓰기의 모델을 분리하는 방식입니다. 이는 물리적 분리로 인한 복잡성을 피하면서도 코드의 응집도를 높일 수 있어 NestJS와 같은 프레임워크 실무에서 매우 효과적입니다.
|
|
|
|
### 3. 이벤트 소싱(Event Sourcing)과의 결합
|
|
CQRS는 종종 상태의 최종 형태가 아닌 상태를 변경시킨 모든 '이벤트'를 순차적으로 저장하는 이벤트 소싱과 함께 사용됩니다. 쓰기 모델에서 이벤트가 발생하면, 이를 비동기적으로 읽기 모델(Read Model)에 동기화하여 고도로 최적화된 뷰(View)를 생성합니다.
|
|
|
|
---
|
|
|
|
## ⚖️ Trade-offs & Caveats
|
|
|
|
### ✅ Benefits
|
|
* **독립적인 스케일링:** 읽기 작업이 압도적으로 많은 시스템에서 읽기 데이터베이스와 인프라만 별도로 확장할 수 있습니다.
|
|
* **모델 단순화:** 쓰기 로직에 복잡한 조회용 DTO가 섞이는 것을 방지하여 도메인 모델(Entity)을 순수하게 유지할 수 있습니다.
|
|
* **보안 및 권한 분리:** 데이터를 변경하는 권한과 읽는 권한을 시스템 아키텍처 레벨에서 원천적으로 분리할 수 있습니다.
|
|
|
|
### ⚠️ Challenges
|
|
* **시스템 복잡도 폭발:** 두 개의 서로 다른 모델(또는 데이터베이스)을 관리해야 하므로 코드량과 인프라 설정이 크게 증가합니다. 단순한 CRUD 앱에는 치명적인 오버엔지니어링(Overkill)입니다.
|
|
* **결과적 일관성 (Eventual Consistency):** 물리적 분리 시 쓰기 모델의 변경 사항이 읽기 모델에 동기화되기까지 시간 지연(Latency)이 발생할 수 있습니다. 이로 인해 사용자가 방금 수정한 데이터를 즉시 보지 못하는 UX 문제가 발생할 수 있습니다.
|
|
|
|
---
|
|
|
|
## 🔗 Knowledge Connections
|
|
|
|
### Related Concepts
|
|
* [[Event_Sourcing]]: CQRS와 짝을 이루어 상태 변경 내역을 이벤트 스트림으로 저장하고 읽기 모델을 구축하는 패턴입니다.
|
|
* [[Domain_Driven_Design]]: 복잡한 도메인 로직을 구현하는 쓰기 모델(Command)을 설계할 때 기반이 되는 방법론입니다.
|
|
* [[Hexagonal_Architecture]]: 비즈니스 코어에 영향을 주지 않고 읽기/쓰기 어댑터를 분리 장착할 수 있는 구조적 템플릿입니다.
|
|
|
|
### Practical Application Contexts
|
|
* **High-Traffic Read Heavy Systems:** 상품 상세 페이지나 SNS 타임라인처럼 조회 트래픽이 쓰기 트래픽보다 수백 배 많은 시스템.
|
|
* **Implementation:** NestJS의 CQRS 모듈을 활용하여 CommandBus와 QueryBus로 트래픽 흐름을 제어합니다.
|
|
|
|
---
|
|
|
|
## 💡 Adjacent Topics
|
|
* [[Microservices_Architecture]]: 각 마이크로서비스 내 데이터 일관성 한계를 극복하기 위해 CQRS와 이벤트를 통한 비동기 통신을 적극 차용합니다.
|
|
* [[Event_Driven_Architecture]]: 모듈 간 횡단 관심사(cross-cutting)를 분리하고 메시지 브로커를 통해 이벤트를 파이프라인으로 연결합니다.
|
|
|
|
---
|
|
*Last updated: 2026-05-02* |