Azure Cosmos DB (RU, 파티션 키, 일관성)
Cosmos DB 의 API 선택, 요청 단위(RU)와 처리량 모드(프로비저닝, 자동 크기 조정, 서버리스), 가장 중요한 파티션 키 설계와 20 GB 논리 파티션 한도, 다섯 가지 일관성 수준, 전역 분산, 429 대응, 2025-11 GA 가 된 Azure DocumentDB 와 Cosmos DB in Fabric 을 정리합니다.
API 고르기
| API | 데이터 모델 | 고르는 경우 |
|---|---|---|
| NoSQL | JSON 문서, SQL 비슷한 쿼리 | 새 앱의 기본. 새 기능(벡터 검색, 전체 텍스트 검색)이 가장 먼저 들어옴 |
| MongoDB (RU) | MongoDB 와이어 프로토콜 | 기존 MongoDB 앱을 RU 모델로 |
| Cassandra | 와이드 컬럼 | 기존 Cassandra 앱 |
| Gremlin | 그래프 | 그래프 탐색 |
| Table | 키 값 | Azure Table Storage 에서 이전 |
MongoDB 호환이 필요하지만 RU 모델보다 vCore 기반 클러스터가 익숙하다면 Azure DocumentDB 를 봅니다. 예전 이름이 Azure Cosmos DB for MongoDB (vCore) 였던 서비스로, Ignite 2025 에서 새 이름으로 GA 가 발표되었습니다.
요청 단위 (RU)
Cosmos DB 의 모든 작업은 RU(Request Unit) 로 비용이 매겨집니다. 1 KB 문서를 ID 와 파티션 키로 한 건 읽는 비용이 약 1 RU 이고, 쓰기는 더 비싸고, 인덱스가 많을수록 쓰기 RU 가 늘어납니다. 응답 헤더 x-ms-request-charge 로 작업마다 실제 RU 를 볼 수 있습니다.
| 처리량 모드 | 과금 | 맞는 경우 |
|---|---|---|
| 프로비저닝 (수동) | 정한 RU/s 를 시간당 | 꾸준하고 예측 가능한 부하 |
| 자동 크기 조정 (autoscale) | 최대 RU/s 의 10%~100% 사이에서 그 시간 최대치로 | 들쭉날쭉한 부하. 운영 기본 추천 |
| 서버리스 | 쓴 RU 만큼 | 개발, 작은 앱, 간헐적 트래픽. 단일 리전 |
무료 계층을 켠 계정(구독당 하나)은 처음 1,000 RU/s 와 25 GB 가 평생 무료입니다. 처리량은 데이터베이스(컨테이너들이 공유) 또는 컨테이너 단위로 줄 수 있습니다.
파티션 키: 가장 중요한 결정
컨테이너의 데이터는 파티션 키 값별로 논리 파티션에 나뉘고, 논리 파티션들이 물리 파티션에 배치됩니다. 컨테이너를 만든 뒤에는 파티션 키를 바꿀 수 없습니다(새 컨테이너로 옮겨야 함).
좋은 파티션 키의 조건입니다.
- 카디널리티가 높음: 값이 아주 많아서 데이터와 요청이 고르게 퍼짐 (예:
userId,tenantId). - 가장 잦은 쿼리의 필터에 들어감: 단일 파티션 쿼리는 싸고 빠르며, 파티션 키 없는 쿼리는 모든 파티션에 퍼져 비쌉니다.
- 논리 파티션 하나가 20 GB 를 넘지 않음: 한 논리 파티션의 저장 한도는 20 GB 입니다.
tenantId하나에 데이터가 몰리는 SaaS 라면 문제입니다.
이 조건을 하나의 속성으로 못 맞추면 계층적 파티션 키(최대 3단계, 예: /tenantId, /userId, /sessionId)를 씁니다. 큰 테넌트도 20 GB 한도를 넘어서 나뉘고, 테넌트 단위 쿼리는 여전히 효율적으로 라우팅됩니다.
from azure.cosmos import CosmosClient, PartitionKey
from azure.identity import DefaultAzureCredential
client = CosmosClient("https://cosmos-shop-prod.documents.azure.com", DefaultAzureCredential())
db = client.get_database_client("shop")
orders = db.create_container_if_not_exists(
id="orders",
partition_key=PartitionKey(path=["/tenantId", "/userId"], kind="MultiHash"),
)
item = orders.read_item(item="order-1001", partition_key=["contoso", "user-42"])
일관성 수준
| 수준 | 보장 | 비용, 지연 |
|---|---|---|
| Strong | 항상 최신 커밋 읽기 | 가장 비쌈. 다중 리전 쓰기와 함께 못 씀 |
| Bounded staleness | 정한 버전 수나 시간만큼만 뒤처짐 | |
| Session (기본) | 내 세션 안에서는 내가 쓴 것을 읽음 | 대부분 앱에 적당 |
| Consistent prefix | 순서는 지키되 늦을 수 있음 | |
| Eventual | 언젠가 수렴 | 가장 쌈 |
계정 기본값은 Session 이고 요청 단위로 더 약하게 낮출 수 있습니다. Strong 과 Bounded staleness 는 읽기에 RU 가 두 배 정도 듭니다.
전역 분산과 가용성
- 계정에 리전을 추가하면 데이터가 자동으로 복제됩니다. 읽기 리전을 앱 가까이 두고, SDK 의
preferred_locations를 설정합니다. - 다중 리전 쓰기를 켜면 모든 리전에서 쓰기가 되고 충돌 해결 정책(마지막 쓰기 우선 또는 사용자 지정)이 필요합니다.
- 리전 안에서는 가용성 영역을 켜서 영역 장애에 대비합니다. 계정을 만들 때 리전별로 정합니다.
- 백업은 주기적(기본) 또는 연속 백업(7일, 30일 특정 시점 복원)이 있습니다.
429 와 비용 문제
429 Too Many Requests 는 지정한 RU/s 를 넘었다는 뜻입니다. SDK 가 자동 재시도하므로 가끔 나오는 것은 정상이지만, 지속되면 원인을 찾습니다.
| 원인 | 확인 | 해결 |
|---|---|---|
| 전체 RU 부족 | 정규화된 RU 사용률이 계속 100% | RU/s 상향, 자동 크기 조정 |
| 핫 파티션 | 특정 파티션 키 범위만 100% | 파티션 키 재설계, 계층적 파티션 키 |
| 비싼 쿼리 | 쿼리당 RU 가 큼 | 파티션 키 필터 추가, 인덱싱 정책 조정 |
| 불필요한 인덱스 | 쓰기 RU 가 큼 | 인덱싱 정책에서 안 쓰는 경로 제외 |
진단 설정으로 CDBDataPlaneRequests, CDBPartitionKeyRUConsumption 같은 테이블을 Log Analytics 에 보내면 어느 작업, 어느 파티션이 RU 를 쓰는지 KQL 로 볼 수 있습니다.
2025~2026 변화
| 항목 | 상태 |
|---|---|
| Azure DocumentDB (MongoDB 호환, vCore) | GA (Ignite 2025) |
| Cosmos DB in Microsoft Fabric, Cosmos DB 미러링 | GA (Ignite 2025) |
| 플릿 풀 (여러 계정이 RU/s 공유) | GA (Ignite 2025) |
| 시맨틱 재순위(semantic reranking) | Ignite 2025 에 PrPr |
NoSQL API 의 벡터 검색(DiskANN 인덱스)과 전체 텍스트 검색을 쓰면 RAG 의 저장소로 Cosmos DB 를 바로 쓸 수 있습니다. 검색 품질이 중요하면 Azure AI Search와 비교합니다.