데이터베이스 (Database)
JSON 데이터베이스 CRUD API입니다. 모든 메서드는 tableId (tbl_xxx 형식, 콘솔에서 발급)를 첫 인자로 받습니다.
데이터 모델
각 row는 DataItem 형태로 반환됩니다:
interface DataItem {
id: string // row ID
data: Record<string, unknown> // 실제 사용자 필드 (콘솔에서 정의한 컬럼)
created_at: string
updated_at: string
}📌 사용자 필드는
row.data.title처럼data객체 안에 들어있습니다.row.title은 동작하지 않습니다.
Create (생성)
단일 생성
const created = await cb.database.createData('tbl_xxx', {
data: {
name: '홍길동',
email: '[email protected]',
age: 30
}
})
// created: { id, data, created_at, updated_at }
console.log(created.id) // 생성된 row 의 UUID📌
createData는 201 Created 와 함께 생성된 row(DataItem) 를 그대로 반환합니다. 후속 publish/navigate/캐시 업데이트에created.id를 바로 사용할 수 있습니다.
벌크 생성
const result = await cb.database.createMany('tbl_xxx', [
{ data: { name: 'User 1', email: '[email protected]' } },
{ data: { name: 'User 2', email: '[email protected]' } },
{ data: { name: 'User 3', email: '[email protected]' } }
])
// result: { created: DataItem[], total: 3, success: 3 }📌
createMany는BulkCreateResponse—{ created, total, success, failed? }— 형태로 응답합니다. 개별 row 의 ID 는result.created[i].id로 접근하세요.
Read (조회)
페이지네이션 조회
const result = await cb.database.getData('tbl_xxx', {
limit: 20,
offset: 0
})
console.log(result.data) // DataItem[]
console.log(result.total_count) // 전체 row 개수💡
[email protected]부터FetchDataResponse가 서버 wire 포맷과 동일한{ data, total_count }로 정정되었습니다.1.3.x이하 사용자는 타입 경고를 무시하거나(result as any).data로 접근해야 했습니다 — 업그레이드하세요.
조건 조회 (queryData)
where, orderBy, select 등이 필요할 때는 queryData 를 사용합니다.
const adults = await cb.database.queryData('tbl_xxx', {
where: {
age: { $gte: 18 },
is_active: true
},
orderBy: 'created_at',
orderDirection: 'desc',
limit: 10,
offset: 0
})💡
getData는where/select/exclude가 포함되면 내부적으로queryData를 호출합니다. 두 메서드를 굳이 구분하지 않아도 됩니다.
단일 조회 (id)
const row = await cb.database.getDataById('tbl_xxx', 'row_123')
console.log(row.data)쿼리 연산자
| 연산자 | 설명 | 예시 |
|---|---|---|
$eq | 같음 | { age: { $eq: 30 } } |
$ne | 같지 않음 | { status: { $ne: 'deleted' } } |
$gt | 초과 | { age: { $gt: 18 } } |
$gte | 이상 | { age: { $gte: 18 } } |
$lt | 미만 | { age: { $lt: 65 } } |
$lte | 이하 | { age: { $lte: 65 } } |
$in | 포함 | { role: { $in: ['admin', 'user'] } } |
$nin | 미포함 | { role: { $nin: ['guest'] } } |
$like | LIKE 패턴 | { name: { $like: '%김%' } } |
Update (수정)
부분 업데이트입니다. 전달한 필드만 수정되고 나머지는 유지됩니다.
const updated = await cb.database.updateData('tbl_xxx', 'row_123', {
data: { name: '김철수', age: 31 }
})Delete (삭제)
단일 삭제
await cb.database.deleteData('tbl_xxx', 'row_123')조건 삭제
const result = await cb.database.deleteWhere('tbl_xxx', {
is_active: false
})
console.log('삭제된 개수:', result.deleted_count)⚠️ SDK 타입(
DeleteWhereResponse)은{ deleted: number }라고 선언되어 있지만, 백엔드는{ deleted_count: number, failed_count?: number }를 반환합니다. 런타임에는 위 예제의result.deleted_count가 정답이며, TypeScript 가 빨간 줄을 그으면(result as any).deleted_count로 캐스팅하세요.
Aggregate / Search / Geo
// MongoDB 스타일 집계
const stats = await cb.database.aggregate('tbl_xxx', [
{ $group: { _id: '$category', count: { $sum: 1 } } },
{ $sort: { count: -1 } }
])
console.log(stats.data) // Record<string, unknown>[] — 집계 결과 row 들
console.log(stats.execution_time_ms) // 서버 처리 시간 (ms)
// 전문 검색
const found = await cb.database.search(
'tbl_xxx',
'검색어',
['title', 'content'], // 검색 대상 필드
{ limit: 10 }
)
console.log(found.results) // SearchResult[] (id, data, score)
console.log(found.total_count)
// 지리 쿼리 (near / within / polygon 중 하나)
const nearby = await cb.database.geoQuery(
'tbl_xxx',
'location',
{
near: {
center: { latitude: 37.5, longitude: 127.0 },
max_distance: 1000 // 미터
}
},
{ limit: 20 }
)
console.log(nearby.results) // GeoResult[] (id, data, distance)Bulk / Batch / Transaction
// 여러 작업을 한 번에 (원자성 보장 X)
await cb.database.batch([
{ type: 'create', table_id: 'tbl_a', data: { name: '...' } },
{ type: 'update', table_id: 'tbl_b', doc_id: 'row_1', data: { count: 2 } },
{ type: 'delete', table_id: 'tbl_c', doc_id: 'row_2' }
])
// 트랜잭션 (원자성 보장)
await cb.database.transaction(
// reads — 트랜잭션 내에서 읽을 row들
[{ table_id: 'tbl_a', doc_id: 'row_1' }],
// writes — 조건부 쓰기
[{
type: 'update',
table_id: 'tbl_a',
doc_id: 'row_1',
data: { count: 2 },
precondition: { exists: true }
}]
)Realtime (실시간 동기화)
데이터 변경을 WebSocket으로 실시간 수신할 수 있습니다. 자세한 내용은 실시간 (Realtime) 를 참고하세요.
await cb.database.connectRealtime({ /* options */ })
const isConnected = cb.database.isRealtimeConnected()