Azure Cosmos DB는 전 세계 어디서나 빠르게 데이터를 읽고 쓸 수 있는 NoSQL 데이터베이스입니다. AZ-204 시험에서는 SDK로 데이터를 조작하는 방법, 파티션 키 설계, 5가지 일관성 수준, 변경 피드, 서버 측 프로그래밍이 핵심입니다.
SDK: 계층 구조로 데이터에 접근하기
Cosmos DB SDK를 처음 접하면 클래스 이름이 많아 헷갈릴 수 있습니다. 쉽게 이해하려면 회사 조직도를 떠올려 보세요. 본사(CosmosClient) 아래에 부서(Database)가 있고, 부서 아래에 팀(Container)이 있으며, 팀원 한 명 한 명이 바로 항목(Item)입니다.
| 클래스 | 역할 | 비유 | |--------|------|------| | CosmosClient | Cosmos DB 계정 전체에 연결 | 본사 대표 전화 | | DatabaseProxy | 특정 데이터베이스 참조 | 특정 부서 | | ContainerProxy | 특정 컨테이너(컬렉션) 참조 | 특정 팀 | | ItemProxy | 개별 문서(JSON 데이터) | 팀원 한 명 |
SDK를 사용하면 연결 문자열 하나로 이 계층을 순서대로 내려가며 데이터를 다룹니다.
CRUD 작업 기본 패턴
연결: CosmosClient(endpoint, credential) 데이터베이스 참조: client.get_database_client("mydb") 컨테이너 참조: db.get_container_client("mycontainer") 항목 생성: container.create_item(body={"id": "1", "pk": "user1", ...}) 항목 읽기: container.read_item(item="1", partition_key="user1") 항목 수정: container.upsert_item(body={...}) 항목 삭제: container.delete_item(item="1", partition_key="user1") 쿼리: container.query_items(query="SELECT * FROM c WHERE c.type = 'order'", ...)
모든 읽기/쓰기 작업에는 RU(Request Unit) 비용이 발생합니다. 1KB 항목 읽기는 약 1 RU, 쓰기는 더 많은 RU를 소비합니다.
파티션 키: 데이터를 나누는 기준
파티션 키는 Cosmos DB가 데이터를 여러 서버에 나누어 저장할 때 사용하는 기준입니다. 도서관을 생각해 보세요. 책을 "가나다" 순으로 분류하면 특정 글자로 시작하는 책들이 한 선반에 몰릴 수 있습니다. 반면 "장르별"로 분류하면 각 선반에 균등하게 나뉩니다. Cosmos DB도 마찬가지입니다.
좋은 파티션 키의 조건을 반드시 기억해야 합니다.
| 조건 | 설명 | 예시 | |------|------|------| | 높은 카디널리티 | 고유한 값이 많을수록 좋음 | 사용자 ID, 주문 ID | | 균등 분산 | 특정 값에 데이터가 몰리지 않아야 함 | 도시, 카테고리 | | 쿼리와 일치 | 자주 필터링하는 필드와 일치 | 쿼리에서 WHERE 절 필드 |
나쁜 파티션 키 예시도 알아야 합니다.
날짜(Date): 특정 날짜에 데이터가 몰림 (핫 파티션 문제) 부울(Boolean): true/false 두 가지뿐이라 파티션이 2개로만 나뉨 고정 카테고리: 값의 종류가 너무 적으면 부하가 특정 파티션에 집중
파티션 키는 항목 생성 후 변경할 수 없으므로, 처음 설계할 때 신중하게 선택해야 합니다.
일관성 수준 5가지: 속도와 정확성의 균형
분산 데이터베이스에서는 전 세계 여러 서버에 데이터가 복제됩니다. 서울에서 데이터를 쓰면 도쿄나 뉴욕 서버에도 같은 데이터가 전달되어야 합니다. 문제는 이 전달에 시간이 걸린다는 점입니다. 일관성 수준은 "얼마나 최신 데이터를 보장하느냐"와 "얼마나 빠르게 응답하느냐"의 균형을 조절하는 설정입니다.
뉴스 속보를 예로 들겠습니다. 사건이 발생했을 때 어떤 매체는 정확성을 위해 검증 후 보도하고, 어떤 매체는 빠르게 보도하지만 나중에 수정합니다.
| 일관성 수준 | 보장 내용 | 성능 | 사용 사례 | |------------|---------|------|---------| | Strong (강함) | 항상 최신 데이터 보장. 쓰기 후 모든 복제본에 반영될 때까지 읽기 차단 | 가장 느림 | 금융 거래, 재고 관리 | | Bounded Staleness (제한된 부실) | 최대 K개 버전 또는 T초 이내의 데이터 보장 | 느림 | 리더보드, 예약 시스템 | | Session (세션) | 같은 세션 내에서는 항상 자신이 쓴 데이터를 읽음 (기본값) | 중간 | 쇼핑 카트, 사용자 프로필 | | Consistent Prefix (일관된 접두사) | 순서는 보장하지만 최신성은 보장 안 함 | 빠름 | SNS 피드, 댓글 | | Eventual (최종) | 언젠가는 일치하지만 즉시 보장 없음 | 가장 빠름 | 좋아요 수, 조회수 |
시험에서 가장 자주 묻는 것은 Session이 기본값이라는 점과 각 수준의 특징입니다.
!Cosmos DB 일관성 수준 5가지
변경 피드: 실시간 이벤트 처리
변경 피드(Change Feed)는 Cosmos DB 컨테이너에서 발생하는 변경 사항을 실시간으로 스트리밍하는 기능입니다. 편의점 CCTV를 생각해 보세요. 누군가가 상품을 집어들거나 계산하는 순간을 실시간으로 녹화하고, 다른 시스템(재고 관리, 보안)이 이를 즉시 처리할 수 있습니다.
변경 피드의 특징을 반드시 기억해야 합니다.
지원하는 작업: 삽입(INSERT)과 업데이트(UPDATE)만 감지 지원하지 않는 작업: 삭제(DELETE)는 기본적으로 감지되지 않음 (TTL 활용 필요) 처리 방식: Azure Functions 트리거, Change Feed Processor 라이브러리 활용 사례: 실시간 알림, 이벤트 소싱, 캐시 무효화, 분석 파이프라인
Azure Functions와 연동
Cosmos DB 트리거를 사용하면 컨테이너에 새 항목이 추가되거나 기존 항목이 변경될 때 자동으로 함수가 실행됩니다. 예를 들어 주문이 들어오는 순간 재고를 자동으로 차감하는 워크플로를 코드 없이 구성할 수 있습니다.
서버 측 프로그래밍: 데이터베이스 안에서 실행되는 로직
Cosmos DB는 데이터베이스 서버 안에서 직접 코드를 실행하는 세 가지 메커니즘을 지원합니다. 마치 공장의 조립 라인처럼, 데이터가 있는 곳에서 바로 처리하면 네트워크를 오갈 필요가 없어 효율적입니다.
저장 프로시저 (Stored Procedure)
여러 작업을 하나의 트랜잭션으로 묶어 실행합니다. 은행 송금을 예로 들면, A 계좌에서 출금하고 B 계좌에 입금하는 두 작업이 반드시 함께 성공하거나 함께 실패해야 합니다. 저장 프로시저는 이런 원자적 작업을 보장합니다.
JavaScript로 작성 같은 파티션 키 내에서만 트랜잭션 보장 실패 시 전체 롤백
트리거 (Trigger)
항목 생성/수정/삭제 전후에 자동으로 실행되는 코드입니다.
Pre-trigger: 항목이 저장되기 전에 실행 (유효성 검사, 데이터 정규화) Post-trigger: 항목이 저장된 후에 실행 (로그 기록, 알림 발송)
UDF (User-Defined Function, 사용자 정의 함수)
SQL 쿼리 안에서 호출할 수 있는 커스텀 함수입니다. 예를 들어 세금 계산 로직을 UDF로 만들면 쿼리에서 직접 호출할 수 있습니다. 트랜잭션을 지원하지 않으며 읽기 전용입니다.
| 종류 | 트랜잭션 | 실행 시점 | 용도 | |------|---------|---------|------| | 저장 프로시저 | 지원 | 명시적 호출 | 원자적 다중 작업 | | Pre-trigger | 미지원 | 쓰기 작업 전 | 유효성 검사, 정규화 | | Post-trigger | 미지원 | 쓰기 작업 후 | 로그, 알림 | | UDF | 미지원 | 쿼리 내 호출 | 커스텀 계산 로직 |
시험 핵심 정리
"CosmosClient → Database → Container → Item" -- SDK 계층 구조 (순서 암기 필수)
"파티션 키로 날짜, 부울 사용" -- 나쁜 예 (핫 파티션 발생)
"높은 카디널리티 + 균등 분산" -- 좋은 파티션 키 조건
"기본 일관성 수준" -- Session
"항상 최신 데이터 보장, 가장 느림" -- Strong
"언젠가는 일치, 가장 빠름" -- Eventual
"변경 피드가 감지하는 것" -- 삽입과 업데이트만 (삭제는 기본 미지원)
"원자적 다중 작업, 트랜잭션 보장" -- 저장 프로시저
"쓰기 전 유효성 검사" -- Pre-trigger
"쿼리 안에서 커스텀 계산" -- UDF (트랜잭션 미지원)