Apache CouchDB는 HTTP API와 JSON 문서를 기반으로 하는 분산 NoSQL 데이터베이스다. "웹을 위한 데이터베이스"를 표방하며, 오프라인 우선(offline-first) 동기화와 MVCC(Multi-Version Concurrency Control)가 특징이다.
핵심 특징
| 항목 | 설명 |
|---|
| 저장 형식 | JSON 문서 |
| API | RESTful HTTP (curl 사용 가능) |
| 동시성 | MVCC (잠금 없음) |
| 복제 | 멀티마스터 (양방향) |
| 인덱스 | MapReduce Views, Mango Query |
| 오프라인 | PouchDB와 자동 동기화 |
HTTP API 사용
bash
# 데이터베이스 생성
curl -X PUT http://admin:password@localhost:5984/blog
# 문서 삽입
curl -X POST http://admin:password@localhost:5984/blog -H "Content-Type: application/json" -d '{
"title": "CouchDB 소개",
"author": "홍길동",
"tags": ["nosql", "database"],
"published": true
}'
# 응답: {"ok":true,"id":"abc123","rev":"1-xyz"}
# 문서 조회
curl http://admin:password@localhost:5984/blog/abc123
# 문서 업데이트 (rev 필수)
curl -X PUT http://admin:password@localhost:5984/blog/abc123 -d '{"_rev":"1-xyz","title":"수정된 제목","author":"홍길동"}'
# 모든 문서 조회
curl http://admin:password@localhost:5984/blog/_all_docs?include_docs=true
MapReduce 뷰 (Design Document)
javascript
// 디자인 문서: 인덱스 정의
{
"_id": "_design/articles",
"views": {
"by_author": {
"map": "function(doc) { if(doc.author) emit(doc.author, doc.title); }",
"reduce": "_count"
},
"published": {
"map": "function(doc) { if(doc.published) emit(doc._id, null); }"
}
}
}
// 쿼리
// GET /blog/_design/articles/_view/by_author?key="홍길동"
Mango 쿼리 (SQL 유사)
javascript
// POST /blog/_find
{
"selector": {
"author": "홍길동",
"published": true,
"created": { "$gt": "2024-01-01" }
},
"fields": ["_id", "title", "created"],
"sort": [{ "created": "desc" }],
"limit": 10
}
// 인덱스 생성 (성능)
// POST /blog/_index
{
"index": { "fields": ["author", "created"] },
"name": "author-date-idx"
}
PouchDB 오프라인 동기화
javascript
import PouchDB from 'pouchdb';
// 로컬 DB
const localDB = new PouchDB('local_blog');
// 원격 CouchDB
const remoteDB = new PouchDB('http://admin:pass@localhost:5984/blog');
// 양방향 실시간 동기화
localDB.sync(remoteDB, {
live: true, // 실시간
retry: true // 연결 끊겨도 재시도
}).on('change', (info) => {
console.log('동기화 변경:', info);
}).on('error', (err) => {
console.error('동기화 오류:', err);
});
// 오프라인에서도 읽기/쓰기 가능
await localDB.put({ _id: 'new-doc', title: '오프라인 작성' });
관련 문서