CQRS

 

📚 CQRS 

Command Query Responsibility Segregation 패턴 

🎯 학습 목표

  • 목표 1: CQRS가 왜 필요한 패턴인지를 \"단일 모델의 한계\" 맥락에서 자신의 언어로 설명할 수 있다.
  • 목표 2: CQRS는 4단계 스펙트럼이 있다는 사실을 이해하고, 자신의 도메인에 적합한 단계를 판단할 수 있다.
  • 목표 3: CQRS와 NoSQL이 결합된 표준 아키텍처를 그림으로 그릴 수 있고, 결과적 일관성의 함정을 설명할 수 있다.                   

📖 사전 지식      

깊은 분산 시스템 경험은 필요하지 않습니다.
RDBMS를 평소에 쓰시면서 SELECT, INSERT, JOIN 정도가 익숙하시면 충분합니다. HTTP API 설계 경험도 있으시면 좋습니다. 이벤트나 메시지 브로커는 이름만 들어보셨어도 괜찮습니다.


1왜 모델을 둘로 나누는가

1.1 우리에게 익숙한 풍경부터

여러분이 처음 백엔드 개발을 시작했을 때를 생각해 보시기 바랍니다. 사용자 정보를 관리하는 코드를 작성하라는 요청을 받으면 보통 이렇게 하지 않으셨나요? 먼저 RDBMS에 users 테이블을 하나 만듭니다. 그리고 애플리케이션 코드에 User 클래스를 만듭니다. 회원가입을 받을 때도 이 객체를 쓰고, 마이페이지만 볼 때도 같은 객체를 씁니다. INSERT, SELECT, UPDATE, DELETE, 그러니까 CRUD라고 부르는 네 가지 연산이 모두 이 단일 모델을 중심으로 이루어집니다.

이 방식은 사실 굉장히 잘 작동합니다. 다만 어느 순간부터 이 모델이 깨지기 시작하는 지점이 있는데, 그 지점이 무엇인지를 먼저 잘 이해해야 CQRS가 왜 등장했는지를 자연스럽게 받아들일 수 있습니다.

1.2 첫 번째 통증: 읽기와 쓰기가 다른 속도로 자랍니다

전자상거래 서비스를 한번 머릿속에 그려 봅시다. 주문이 한 번 들어올 때 그 주문에 대한 조회는 수십 번에서 수백 번까지 일어난다는 점입니다.

📊 수치로 보는 부하 비대칭

가상의 중대형 쇼핑몰 기준:
• 일일 주문: 50만 건 → 초당 약 6 TPS
• 일일 주문 조회: 5천만 건 → 초당 약 580 TPS
읽기/쓰기 비율: 약 100:1

이 100배 차이의 부하를 같은 단일 데이터베이스가 모두 감당해야 합니다. 서비스가 자라면 세 가지 통증이 차례로 나타납니다:

① JOIN 폭발

마이페이지 주문 내역 화면 하나를 그리려면 orders, order_items, products, users, shipping_addresses, payments, shipments처럼 6~8개 테이블을 JOIN해야 합니다.

② 잠금 경합

쓰기가 늘수록 dead tuple이 쌓이고 AUTOVACUUM 작업이 자주 돌며, 인덱스 재구성이나 트리거 실행처럼 공유 락이 필요한 작업이 읽기/쓰기 모두에 영향을 줍니다.

③ 스키마 변경 비용

마케팅팀에서 \"적립금 사용액도 보여주세요\" 요청 하나에 며칠짜리 마이그레이션이 따릅니다. 백필이 며칠씩 걸리고, 락이 걸리거나 성능이 저하될 수 있습니다.

⚠️ 핵심 통찰

이 세 가지 통증이 모두 같은 뿌리에서 나옵니다. \"쓰기 작업과 읽기 작업이 본질적으로 다른 일인데, 같은 모델을 공유하기 때문에 서로를 방해한다\"는 사실입니다.

1.3 두 번째 통증: 한 모델이 두 가지 일을 동시에 해야 합니다

같은 \"주문\" 객체를 두 시점에서 보겠습니다:

  • 주문 버튼 클릭 시: 재고 확인 → 결제 승인 → 도메인 규칙 검증 → 저장.
    가장 중요한 것은 \"정합성\"입니다.
  • 주문 내역 화면 조회 시: 사용자 이름, 상품 이미지, 배송 상태 등 의미 있는 화면.
    가장 중요한 것은 \"표현\"입니다.

같은 Order 클래스가 이 두 가지 책임을 동시에 짊어지면 어떻게 될까요? 시간이 지날수록 클래스가 비대해지고, 어느 쪽 책임도 깔끔하게 수행하지 못합니다.

class Order { // 쓰기 시점 필드 private Long orderId; private Long userId; private List<OrderItem> items; private OrderStatus status; // 읽기 화면 요구사항이 늘어날 때마다 추가되는 필드들 private String userName; // ?! private String firstProductImage; // ?! private String trackingStatus; // ?! private BigDecimal pointsUsed; // ?! // ... 40개 이상의 필드 }

비즈니스 규칙 코드와 화면 표현 코드가 한 파일 안에서 부딪치는 모습입니다. 이런 클래스를 객체지향 설계에서는 \"신 객체(God Object)\"라고 부릅니다.

1.4 그래서 우리가 풀어야 할 질문

쓰기와 읽기를 분리하면 무엇이 좋아지고, 무엇이 어려워질까? — 이 질문이 CQRS 패턴의 출발점입니다

2CQRS 개념 이해

2.1 CQRS는 무엇을 의미하는가

Command Query Responsibility Segregation. \"명령과 질의의 책임 분리\"입니다.

이 패턴은 Greg Young이 2010년경에 처음 제안했고, Martin Fowler가 2011년에 자기 블로그에 정리해서 널리 알려졌습니다.

\"어떤 정보를 갱신할 때 사용하는 모델과 같은 정보를 읽을 때 사용하는 모델을 서로 다르게 둘 수 있다. 어떤 상황에서는 이 분리가 가치가 있다. 다만 대부분의 시스템에서 CQRS는 위험한 복잡도를 추가한다는 점을 경계해야 한다.\" — Martin Fowler, 2011

✓ 핵심 정의

데이터를 갱신할 때 쓰는 모델과 읽을 때 쓰는 모델을 굳이 같게 둘 필요가 없다.

2.2 어디서 왔는가: CQS 원칙

CQRS는 그 이전부터 객체지향 설계 쪽에서 통용되던 CQS (Command-Query Separation) 원칙에서 진화한 것입니다. Bertrand Meyer가 제안했지요.

구분 적용 범위 분리 단위
CQS (Bertrand Meyer) 단일 객체 메서드
CQRS (Greg Young) 시스템/아키텍처 모델 (선택적으로 DB까지)

2.3 Command와 Query는 무엇이 다른가

구분 Command Query
의도 상태 변경 정보 조회
부수효과 있음 없음
반환값 없거나 성공/실패만 데이터
예시 PlaceOrder, CancelSubscription GetOrdersByUser, SearchProducts
책임 도메인 규칙 검증 응답 최적화

나쁜 예 — 섞여 있는 경우

// ❌ 주문하면서 주문 내역까지 같이 반환 public OrderDetailDto placeOrderAndReturnDetail(PlaceOrderRequest req) { Order order = new Order(req); order.validateStock(); order.chargePayment(); orderRepository.save(order); // 응답을 만들려고 다시 JOIN 쿼리를 침 return orderQueryService.fetchFullDetail(order.getId()); }

좋은 예 — 분리된 경우

// ✅ Command - 상태 변경에만 집중 public OrderId placeOrder(PlaceOrderCommand cmd) { Order order = Order.create(cmd); order.validateStock(); order.chargePayment(); orderRepository.save(order); return order.getId(); } // ✅ Query - 조회에만 집중 public OrderDetailView getOrderDetail(OrderId orderId) { return orderReadModel.findByOrderId(orderId); }

2.4 가장 가벼운 형태: DB는 하나

CQRS라고 하면 곧바로 DB 두 개를 떠올리는 분들이 많습니다. 그렇지 않습니다!

💡 가장 가벼운 CQRS

DB는 그냥 하나입니다.
단지 애플리케이션 코드에서 쓰기 쪽 모델과 읽기 쪽 모델만 나눠 둡니다. 도메인 객체와 DTO를 명확히 분리하고, Command Service와 Query Service를 따로 두는 것만으로도 출발할 수 있습니다. CQRS를 처음 도입하실 때는 이 단계에서 충분한 가치를 얻을 수 있습니다.

2.5 CQRS는 스위치가 아니라 스펙트럼입니다

CQRS는 켜고 끄는 스위치가 아니라 적용 강도의 스펙트럼입니다.

단계 구성 일관성 적합 도메인
1단계 모델만 분리, DB는 하나 강한 일관성 사내 시스템, B2B 백오피스
2단계 읽기 복제본 활용 약한 결과적 일관성 콘텐츠 서비스, 대시보드
3단계 RDBMS + NoSQL 분리 결과적 일관성 전자상거래, 소셜 피드
4단계 Event Sourcing 결합 이벤트 기반 금융, 의료 (감사 추적 필수)

⚠️ 점진적 도입 권장

단계는 위로 올라갈수록 한 번 도입하면 되돌리기 어렵습니다. 무작정 3, 4단계부터 시작하는 것은 매우 위험합니다. 1단계에서 시작해서 통증이 명확하게 드러날 때 한 단계씩 올려가는 점진적 도입이 강력하게 권장됩니다.

2.6 흔한 오해 세 가지

❌ 틀린 주장들

  • \"CQRS는 데이터베이스가 항상 두 개다\" — 단계 1, 2는 아닙니다
  • \"CQRS는 Event Sourcing이 필수다\" — 두 패턴은 독립적입니다
  • \"CQRS는 마이크로서비스에만 쓴다\" — 모놀리식 안에서도 적용 가능합니다

3NoSQL 기초

3.1 왜 NoSQL을 다루는가

이 자료의 종착점은 \"CQRS + NoSQL\"입니다. CQRS의 단계 3 이상에서 읽기 측 DB로 NoSQL이 자주 선택되는데, 왜 그런지를 이해하려면 NoSQL이 무엇인지 짧게 다지고 갑니다.

3.2 NoSQL이란 무엇인가

NoSQL은 단일한 기술의 이름이 아닙니다. RDBMS가 아닌 데이터베이스들을 묶어 부르는 우산 개념입니다.

유형 대표 제품 주된 사용처
Document MongoDB, Couchbase 비정규화된 문서, 화면 단위 응답
Key-Value Redis, DynamoDB 캐시, 세션, 빠른 조회
Wide-Column Cassandra, HBase 대규모 시계열, 분석
Graph Neo4j, Neptune 관계 중심 데이터, 소셜 그래프

3.3 RDBMS와의 결정적 차이

항목 RDBMS NoSQL
스키마 사전 정의·강제 유연·동적
확장 수직 확장 중심 수평 확장 친화
트랜잭션 ACID 제품별 다양, 보통 약함
조인 강력 제한적/미지원
일관성 강한 일관성 결과적 일관성

✓ 핵심 기억

NoSQL은 RDBMS의 대체재가 아니라 보완재입니다. RDBMS는 일관성과 정합성을 책임지고, NoSQL은 유연한 스키마와 수평 확장을 책임집니다.

3.4 CAP 정리

CAP 정리: 분산 시스템은 다음 세 가지를 동시에 만족할 수 없다는 주장입니다.

  • Consistency (일관성): 모든 노드가 같은 시점에 같은 데이터를 봄
  • Availability (가용성): 모든 요청이 응답을 받음
  • Partition tolerance (분할 내성): 네트워크 장애에도 시스템이 계속 동작

분산 환경에서 P는 사실상 필수이므로, 실제 선택은 C와 A 사이의 트레이드오프가 됩니다. NoSQL은 보통 가용성을 우선하고 일관성을 약하게 가져갑니다.

3.5 결과적 일관성 (Eventual Consistency)

즉시 일관성: 단일 RDBMS에서 쓰기를 한 직후 같은 데이터를 읽으면 새로 쓴 값을 봅니다. \"쓴 직후 읽으면 새 값\"이라는 약속입니다.

결과적 일관성: CQRS 단계 3 이상에서는 쓰기 측과 읽기 측이 서로 다른 시스템입니다. 쓰기가 일어난 후 변경이 읽기 측에 반영되기까지 시간이 걸립니다. \"지금 당장은 다를 수 있지만, 충분한 시간이 지나면 결국 같아진다\"는 약속입니다.

📍 일관성 갭 (Consistency Gap)

t0 (쓰기) → t1 (이벤트 발행) → t2 (Projector 갱신) → t3 (조회 가능)
t0부터 t2까지의 구간이 일관성 갭입니다. 정상 상황에서는 약 50~100ms 정도입니다.

문제 상황:

  • 사용자가 매우 빠른 액션(주문 직후 마이페이지 이동)をする場合
  • Projector나 Kafka 컨슈머에 지연이 생기는 경우 → 갭이 수 초~분 단위로 늘어남

4CQRS + NoSQL 결합 아키텍처

4.1 왜 NoSQL을 읽기 모델에 두는가

이유 해결하는 통증
스키마 유연성 새 필드 추가 시 마이그레이션 거의 불필요
수평 확장 읽기 트래픽 폭증 시 노드 추가 대응
비정규화 친화 JOIN이 필요 없어짐

✓ 핵심 정신

\"쓰기는 정규화, 읽기는 비정규화\"
이 한 줄이 CQRS + NoSQL의 핵심입니다.

4.2 표준 결합 아키텍처

세 영역으로 깔끔하게 나뉩니다:

  • 왼쪽 (쓰기 영역): Command API → Write DB (RDBMS)
  • 가운데 (이벤트 버스): 도메인 이벤트 → Kafka → Projector
  • 아래쪽 (읽기 영역): Query API ← Read DB (NoSQL)

흐름을 따라가 봅시다:

  1. 쓰기: 클라이언트 → Command API → 도메인 검증 → Write DB 저장 (ACID)
  2. 이벤트: Write DB → 도메인 이벤트 → Kafka
  3. 읽기 갱신: Kafka → Projector → Read DB 비정규화 문서 작성
  4. 조회: 클라이언트 → Query API → Read DB 단일 페치 → 응답

4.3 쓰기 측의 책임

쓰기 측이 정합성의 영역입니다:

  • ① 도메인 규칙 검증 (재고, 결제, 권한)
  • ② ACID 트랜잭션 보장
  • ③ 도메인 이벤트의 신뢰성 있는 발행

Outbox 패턴

이벤트 발행의 함정을 해결합니다. 트랜잭션 안에서 도메인 데이터와 이벤트를 같이 저장해 두고, 별도 프로세스가 그 이벤트를 발행하는 방식입니다.

// ✅ Outbox 패턴 - 같은 트랜잭션 안에서 저장 @Transactional public void placeOrder(PlaceOrderCommand cmd) { Order order = Order.create(cmd); orderRepository.save(order); // Outbox에 이벤트 기록 outboxRepository.save(new OutboxEvent( \"Order\", order.getId(), \"OrderPlaced\", toJson(order) )); } // 별도 워커가 주기적으로 Outbox 폴링 후 발행 List<OutboxEvent> pending = outboxRepository.findUnpublished(); for (OutboxEvent event : pending) { kafkaProducer.send(event); outboxRepository.markPublished(event.getId()); }

4.4 읽기 측의 책임

읽기 측이 조회 최적화의 영역입니다:

  • ① 화면 단위로 비정규화된 문서 유지
  • ② 조회 요청에 빠르게 응답
  • ③ 새 화면 요구사항에 유연하게 대응

읽기 모델은 데이터베이스 이론에서 말하는 구체화된 뷰(Materialized View)의 개념과 같습니다.

4.5 동기화 메커니즘 두 가지

방식 장점 단점
애플리케이션 이벤트 발행 도메인 의미가 풍부한 이벤트 가능 애플리케이션 코드에 책임 추가
CDC (Change Data Capture) 애플리케이션 코드 수정 불필요 도메인 의미가 빈약 (데이터 레벨)

4.6 Event Sourcing — 짧은 만남

Event Sourcing: 상태를 직접 저장하는 게 아니라, 상태가 변경된 사건(이벤트)들을 시간순으로 저장하는 방식입니다.

// 일반 저장 방식 - 현재 잔액만 저장 AccountTable: balance = 75,000원 // Event Sourcing - 사건들을 시간순으로 저장 EventStore: seq=1, AccountOpened { initial: 0 } seq=2, Deposited { amount: 50000 } seq=3, Withdrawn { amount: 5000 } seq=4, Deposited { amount: 30000 } seq=5, Withdrawn { amount: 0, fee: 1000 } // 현재 잔액 = 0 + 50000 - 5000 + 30000 - 1000 = 74,000

⚠️ CQRS와 Event Sourcing은 독립적입니다

CQRS를 도입한다고 Event Sourcing이 자동으로 따라오지 않습니다. CQRS의 단계 3까지는 일반적인 RDBMS와 NoSQL만으로 충분히 구현됩니다. Event Sourcing은 그 자체로 학습과 운영 비용이 큰 별개의 결정입니다.


5설계 사례

5.1 사례 1 — 전자상거래 주문 시스템

비즈니스 컨텍스트

  • 일일 주문: 50만 건 (평균 6 TPS, 피크 60~100 TPS)
  • 일일 주문 조회: 5천만 건 (평균 580 TPS, 피크 5,000~10,000 TPS)
  • 읽기/쓰기 비율: 100:1

데이터 모델 비교

쓰기 측 — PostgreSQL (정규화)

CREATE TABLE orders ( order_id BIGINT PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES users(user_id), total_amount DECIMAL(12,2) NOT NULL, status VARCHAR(20) NOT NULL ); CREATE TABLE order_items ( order_item_id BIGINT PRIMARY KEY, order_id BIGINT NOT NULL REFERENCES orders(order_id), product_id BIGINT NOT NULL REFERENCES products(product_id), quantity INT NOT NULL, unit_price DECIMAL(10,2) NOT NULL ); -- 마이페이지 화면을 그리려면? SELECT o.order_id, o.created_at, u.name, p.name, oi.quantity FROM orders o JOIN users u ON o.user_id = u.user_id JOIN order_items oi ON oi.order_id = o.order_id JOIN products p ON p.product_id = oi.product_id WHERE o.user_id = ? ORDER BY o.created_at DESC; -- 4-way JOIN!

읽기 측 — MongoDB (비정규화)

{ \"_id\": \"order_20260526_000123\", \"user\": { \"user_id\": 4521, \"name\": \"김수강\" }, \"items\": [ { \"product_id\": 9912, \"product_name\": \"기계식 키보드\", \"thumbnail_url\": \"https://cdn.example.com/p/9912.jpg\", \"quantity\": 1, \"unit_price\": 149000 } ], \"total_amount\": 149000, \"status\": \"DELIVERED\", \"created_at\": \"2026-05-26T10:14:00Z\" }
// 조회는 이렇게 끝! db.orders.find({ \"user.user_id\": 4521 }) .sort({ created_at: -1 }) .limit(20);

트레이드오프 — 결과적 일관성이 만드는 함정

⚠️ 시나리오

사용자가 주문 완료 버튼을 누르고 곧바로 마이페이지로 이동했습니다. 그런데 방금 주문한 게 안 보입니다. 왜? Write DB에는 저장됐지만 MongoDB 갱신이 아직 완료되지 않았기 때문입니다.

해결 옵션:

  • 낙관적 UI 업데이트: Command 응답으로 받은 데이터로 화면을 먼저 채우고, 백그라운드 동기화를 기다림
  • Command 응답에 화면 필수 데이터를 함께 담기: 클라이언트가 별도 조회 없이 화면 구성
  • 단기 폴링: 주문 직후 짧은 시간 Query API를 폴링해서 동기화 완료 확인

5.2 사례 2 — 소셜 피드 시스템

비즈니스 컨텍스트

  • 일일 활성 사용자: 1천만 명
  • 1인당 게시물 작성: 1~2건/일
  • 1인당 타임라인 조회: 50~100회/일
  • 읽기/쓰기 비율: 100~200:1

Fan-out on Write

핵심 통찰: \"조회 시점이 아니라 작성 시점에 미리 계산해 둔다\"

  1. 사용자가 게시물 작성 → Posts DB에 원본 저장
  2. Posts DB가 `PostCreated` 이벤트 발행
  3. Fan-out Worker가 팔로워 모든 사람의 타임라인에 게시물 ID push
  4. 팔로워가 자기 타임라인 조회 → 자기 캐시 한 번만 페치

Fan-out 전략 비교

전략 쓰기 시점 조회 시점 적합 사용자
Fan-out on Write 팔로워 N명 캐시에 복사 O(N) 자기 캐시 1회 페치 O(1) 일반 사용자
Fan-out on Read 작업 없음 팔로우 목록 조회 + 게시물 머지 셀러브리티 (팔로워 수백만)
하이브리드 일반 계정은 on-write, 셀러브리티는 on-read 두 결과 머지 대형 서비스 표준

데이터 모델 — Redis Sorted Set

// 키 구조 KEY: timeline:user:4521 // Sorted Set - 시간 역순 정렬 ZADD timeline:user:4521 1716703200 post_99000 ZADD timeline:user:4521 1716701850 post_98745 ZADD timeline:user:4521 1716700800 post_98712 // 조회 ZREVRANGE timeline:user:4521 0 49

한계와 절충

  • 저장 공간 폭발: 평균 팔로워 100명이면 100배 저장 공간. 최근 500개만 유지하고 그 너머는 동적 계산
  • 셀러브리티 문제: 팔로워 천만 명 = 천만 번 push. 임계치(예: 100만) 이상은 Fan-out on Read로
  • 캐시 일관성: 삭제 시 모든 사본 갱신은 비현실적. hydrate 시점에 원본 확인 후 필터링

6안티패턴과 적용 기준

⚠️ 가장 중요한 메시지

\"패턴을 배우는 것보다 쓰지 말아야 할 때를 아는 것이 더 중요합니다.\"
CQRS는 모든 시스템에 적용해야 하는 트렌드가 아닙니다. 잘못 적용하면 시스템을 오히려 더 어렵게 만듭니다.

6.1 언제 CQRS를 쓰면 안 되는가

❌ CQRS 도입을 피해야 할 시나리오

  • 단순한 CRUD 도메인: 화면이 데이터를 거의 그대로 보여주고 도메인 규칙이 단순한 경우
  • 즉시 일관성이 필수인 도메인: 잔액, 재고 표시처럼 사용자가 즉시 정확한 값을 보아야 하는 경우
  • 소규모 팀: 분산 시스템 운영 경험이 없는 작은 팀에게 단계 3 이상은 부담 과중
  • 충분히 복잡하지 않은 도메인: CRUD 이상의 비즈니스 규칙이 없다면 복잡도만 더함

6.2 실제 실패 사례 세 가지

패턴 상황 결과
\"트렌드라 도입했다\" 10명 스타트업이 단순 CRUD에 단계 3 도입 개발 속도 50% 감소, 6개월 후 단계 1로 롤백
\"시스템 전체에 일괄 적용\" 모든 Bounded Context에 CQRS 적용 결제 도메인에 결과적 일관성 → 사용자 혼란
\"운영 역량 없이 단계 4\" 인프라팀 없는 서비스에 Event Sourcing 도입 이벤트 스키마 깨지자 과거 재생 실패, 복구 며칠 소요

6.3 Martin Fowler의 경고

\"CQRS는 시스템 전체가 아니라 시스템의 특정 부분(DDD 용어로 BoundedContext)에만 사용되어야 한다. 특히 CQRS가 소프트웨어 시스템을 심각한 어려움에 빠뜨린 사례들을 봐 왔다.\" — Martin Fowler

6.4 도입 체크리스트

✓ CQRS 도입 검토 시 6가지 질문

  • 읽기:쓰기 비율이 10:1 이상 비대칭인가?
  • 조회 요구사항이 정규화로 풀리지 않는가?
  • 결과적 일관성을 UX 측면에서 수용 가능한가?
  • 운영 인력이 메시지 브로커와 다중 저장소를 다룰 수 있는가?
  • 도메인이 CRUD 이상으로 충분히 복잡한가?
  • CQRS 적용 범위를 단일 Bounded Context로 한정 가능한가?

🎯 판정 기준

4개 이상에 \"예\"라고 답할 수 있을 때만 도입을 고려하세요. 그보다 적으면 단일 모델로 충분한 경우가 대부분입니다.


📝 자가 평가

평가 1. CQRS가 왜 필요한가?

친구가 \"CQRS가 뭐고 왜 쓰는 거야?\"라고 묻는다고 가정합니다. 3분 안에 설명해 주세요.

좋은 답변: 단일 모델 CRUD의 한계를 짚을 수 있어야 함 (부하 비대칭, 모델 책임 충돌 등). CQRS의 한 줄 정의 포함. 적합/부적합 경우 구분.

평가 2. CQRS 4단계 스펙트럼 자가 적용

현재 다루고 있거나 익숙한 시스템 하나를 떠올려 보세요. 어느 단계가 적합할까요?

좋은 답변: 도메인의 읽기/쓰기 비율과 복잡도를 평가했어야 함. 4단계 중 하나 선택 + 이유. 도입 안 함도 좋은 답.

평가 3. 표준 아키텍처 그리기

종이에 CQRS + NoSQL 표준 아키텍처를 그려 보세요. 결과적 일관성이 만드는 함정 한 가지를 적어 보세요.

좋은 답변: 쓰기/이벤트/읽기 세 영역 분리. 화살표 방향 정확. 일관성 갭과 UX 함정 설명.


 

'스파르타 심화 과정' 카테고리의 다른 글

RAG 이해하기  (0) 2026.06.09
모니터링과 부하테스트  (0) 2026.06.02
spring 과제  (0) 2026.04.21
4/20 Spring 기초(2) 특강  (0) 2026.04.20
spring 특강 1  (0) 2026.04.20