

타입 | 설명 | 예시 |
String | 문자열 | 이름, 이메일, 설명 |
Number | 숫자 | 나이, 가격, 수량 |
Boolean | 참/거짓 | 완료 여부, 활성화 상태 |
Date | 날짜/시간 | 생성일, 마감일 |
Array | 배열 | 태그 목록, 파일 목록 |
Object | 객체 | 주소 (시/구/동), 설정 정보 |
ObjectId | 참조 ID | 다른 테이블 참조 |
{
"fieldName": "email",
"type": "String",
"required": true, // 필수 필드
"unique": true, // 고유 값 (중복 불가)
"default": "user@example.com", // 기본값
"minLength": 5, // 최소 길이
"maxLength": 100, // 최대 길이
"pattern": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$" // 정규식
}"사용자 테이블에 이메일 필드 추가해줘.
필수 항목이고, 중복되면 안 돼.
이메일 형식이 맞는지 검증도 필요해.""배달 앱 만들려고 해.
음식점 정보(이름, 주소, 전화번호)랑
메뉴(이름, 가격, 카테고리)를 저장해야 해.
한 음식점은 여러 메뉴를 가질 수 있어."// restaurants 테이블
{
"_id": ObjectId,
"name": String,
"address": String,
"phone": String
}
// menus 테이블
{
"_id": ObjectId,
"restaurantId": ObjectId, // restaurants 테이블 참조
"name": String,
"price": Number,
"category": String
}"학생 관리 앱 만들려고 해.
학생 정보(이름, 학번)와 수업 정보(수업명, 교수명)를 저장하고,
한 학생은 여러 수업을 들을 수 있고, 한 수업은 여러 학생이 들을 수 있어."// students 테이블
{
"_id": ObjectId,
"name": String,
"studentId": String
}
// courses 테이블
{
"_id": ObjectId,
"courseName": String,
"professor": String
}
// enrollments 테이블 (중간 테이블)
{
"_id": ObjectId,
"studentId": ObjectId, // students 테이블 참조
"courseId": ObjectId, // courses 테이블 참조
"enrolledAt": Date
}"상품 테이블 만들어줘.
상태는 '판매중', '품절', '단종' 중 하나만 가능해야 해."{
"status": {
"type": "String",
"enum": ["판매중", "품절", "단종"],
"default": "판매중"
}
}역할 | 설명 | 기본 권한 |
admin | 관리자 | CRUD 모두 가능 |
user | 일반 사용자 | CRUD 모두 가능 |
self |
"공지사항 테이블 만들어줘.
관리자는 작성/수정/삭제 가능하고,
일반 사용자는 보기만 가능하게 해줘.""게시글 테이블 만들어줘.
누구나 글을 쓰고 볼 수 있지만,
수정과 삭제는 본인이 쓴 글만 가능하게 해줘."// 현재 사용자 ID로 필터링
const filters = JSON.stringify({ createdBy: currentUser.id });
await apiClient.get(`/data/posts?andFilters=${encodeURIComponent(filters)}`);"사용자를 이메일로 검색할 때 느린데 빠르게 해줘.""회원가입할 때 같은 이메일로 여러 번 가입되는 문제가 있어. 막아줘."**쿼리 최적화 팁**
### 1. 필요한 필드만 조회하기
❌ **나쁜 예:**
```
// 모든 필드 조회 (불필요한 데이터 전송)
const users = await apiClient.get('/data/users');
```
✅ **좋은 예:**
```
// 필요한 필드만 지정 (API에서 지원 예정)
// 현재는 프론트엔드에서 필터링
const users = await apiClient.get('/data/users');
const userNames = users.data.data.items.map(u => ({ id: u._id, name: u.name }));
```
### 2. 페이지네이션 활용
❌ **나쁜 예:**
```
// 모든 데이터 한 번에 조회
const todos = await apiClient.get('/data/todos');
```
✅ **좋은 예:**
```
// 페이지 단위로 조회
const todos = await apiClient.get('/data/todos?page=1&limit=20');
```
### 3. 서버 사이드 필터링 사용
❌ **나쁜 예:**
```
// 클라이언트에서 필터링 (모든 데이터 전송)
const allTodos = await apiClient.get('/data/todos');
const completed = allTodos.data.data.items.filter(t => t.completed);
```
✅ **좋은 예:**
```
// 서버에서 필터링 (필요한 데이터만 전송)
const filters = JSON.stringify({ completed: true });
const completed = await apiClient.get(`/data/todos?andFilters=${encodeURIComponent(filters)}`);
```
### 4. 인덱스가 있는 필드로 정렬
✅ **좋은 예:**
```
// createdAt에는 시스템 인덱스가 있음
const latest = await apiClient.get('/data/todos?sortBy=createdAt&sortDirection=desc');
```"사용자를 이름과 나이로 함께 검색할 때 빠르게 해줘."인덱스명 | 필드 | 용도 |
_id_ | _id | Primary Key, 레코드 조회 |
idx_createdAt_desc | createdAt | 생성일 기준 정렬 |
idx_updatedAt_desc | updatedAt | 수정일 기준 정렬 |
idx_createdBy | createdBy | 생성자별 조회 |
// 모든 필드 조회 (불필요한 데이터 전송)
const users = await apiClient.get('/data/users');// 필요한 필드만 지정 (API에서 지원 예정)
// 현재는 프론트엔드에서 필터링
const users = await apiClient.get('/data/users');
const userNames = users.data.data.items.map(u => ({ id: u._id, name: u.name }));// 모든 데이터 한 번에 조회
const todos = await apiClient.get('/data/todos');// 페이지 단위로 조회
const todos = await apiClient.get('/data/todos?page=1&limit=20');// 클라이언트에서 필터링 (모든 데이터 전송)
const allTodos = await apiClient.get('/data/todos');
const completed = allTodos.data.data.items.filter(t => t.completed);// 서버에서 필터링 (필요한 데이터만 전송)
const filters = JSON.stringify({ completed: true });
const completed = await apiClient.get(`/data/todos?andFilters=${encodeURIComponent(filters)}`);// createdAt에는 시스템 인덱스가 있음
const latest = await apiClient.get('/data/todos?sortBy=createdAt&sortDirection=desc');const items = [
{ title: "할 일 1", completed: false },
{ title: "할 일 2", completed: false },
{ title: "할 일 3", completed: false }
];
// 순차 처리
for (const item of items) {
await todosApi.create(item);
}
// 또는 병렬 처리
await Promise.all(items.map(item => todosApi.create(item)));"todos 테이블에 dueDate 필드 추가해줘."// 기존 데이터는 deadline, 새 데이터는 dueDate 사용
const todos = await todosApi.list(userId);
const normalized = todos.map(t => ({
...t,
dueDate: t.dueDate || t.deadline // fallback 처리
}));"todos 테이블에서 deadline 필드 삭제해줘."# Claude Code
cat ~/.claude/logs/mcp.log
# Cursor
cat ~/.cursor/logs/mcp.log# Claude Code
cat ~/.claude/settings.local.json
# 올바른 형식인지 확인
{
"mcpServers": {
"mcp-bkend": {
"type": "http",
"url": "https://api.bkend.ai/mcp",
"headers": {
"X-Organization-Id": "your_org_id",
"X-Api-Key": "your_api_key"
}
}
}
}# 설정 파일 권한 확인
ls -la ~/.claude/settings.local.json
# 읽기 권한이 없다면
chmod 644 ~/.claude/settings.local.json{
"Authorization": "Bearer {access_token}",
"X-Project-Id": "{project_id}",
"X-Environment": "dev",
"Content-Type": "application/json"
}// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'https://api-enduser.bkend.ai',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});"test라는 이름으로 간단한 테이블 만들어줘. title 필드 하나만."