--- globs: src/app/api/**/*.ts --- # API Route 코딩 규칙 ## 인증 체크 모든 핸들러 첫 줄에 세션 검증 필수: ```typescript const user = await getSession(); if (!user) return NextResponse.json({ success: false }, { status: 401 }); ``` ## import 순서 1. `next/server` (NextRequest, NextResponse) 2. `@/lib/session` (getSession) 3. `@/lib/db` (queryRows, queryOne, execute) 4. `@/lib/utils` (createObjectId, checkNull 등) 5. 기타 (`@/lib/auth`, `@/lib/encrypt` — login 전용) ## 동적 SQL 파라미터 ```typescript const conditions: string[] = ["1=1"]; const params: unknown[] = []; let idx = 1; if (body.field) { conditions.push(`TABLE.COLUMN = $${idx++}`); params.push(body.field); } // LIKE: conditions.push(`COLUMN LIKE '%' || $${idx++} || '%'`); const sql = `SELECT ... WHERE ${conditions.join(" AND ")} ORDER BY regdate DESC`; const rows = await queryRows(sql, params); ``` ## SQL alias 대문자 PostgreSQL은 따옴표 없는 alias를 소문자로 반환한다. 대문자 유지하려면 큰따옴표 필수: ```sql SELECT id AS "OBJID", name AS "USER_NAME" -- O (대문자 유지) SELECT id AS OBJID -- X (소문자 objid로 반환) ``` ## 응답 형식 - 목록 조회: `{ RESULTLIST: rows, TOTAL_CNT: rows.length }` - 단순 조회: `{ success: true, data: rows }` - 저장/수정: `{ success: true }` 또는 `{ success: true, objId: newId }` - 오류: `{ success: false, message: "..." }` + HTTP 400/401/500 ## 에러 처리 ```typescript try { // 비즈니스 로직 } catch (error) { console.error("설명:", error); return NextResponse.json({ success: false, message: "처리 중 오류가 발생했습니다." }, { status: 500 }); } ``` ## INSERT/UPDATE 구분 `actionType` 필드로 분기: ```typescript const { actionType } = body; if (actionType === "regist") { const newId = createObjectId(); await execute(`INSERT INTO ...`, [...]); } else { await execute(`UPDATE ... WHERE OBJID = $${idx}`, [...]); } ``` ## SQL 공통 패턴 - 삭제 플래그: `COALESCE(IS_DEL, 'N') != 'Y'` - 날짜 포맷: `TO_CHAR(regdate, 'YYYY-MM-DD')` - 기본 정렬: `ORDER BY regdate DESC` - objId 타입 변환: `objid::text AS "OBJID"`