--- description: globs: alwaysApply: true --- # 데이터베이스 가이드 ## 데이터베이스 설정 ### PostgreSQL 연결 - **드라이버**: `pg` (node-postgres) - **설정 파일**: `backend-node/src/config/database.ts` - **환경 변수**: `backend-node/.env` (DATABASE_URL) ### 연결 풀 사용 ```typescript import { Pool } from 'pg'; const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 20, idleTimeoutMillis: 30000, }); ``` ## 쿼리 패턴 ### 기본 CRUD ```typescript // SELECT const result = await pool.query( 'SELECT * FROM example_table WHERE company_code = $1 ORDER BY created_at DESC', [companyCode] ); // INSERT const result = await pool.query( 'INSERT INTO example_table (company_code, name) VALUES ($1, $2) RETURNING *', [companyCode, name] ); // UPDATE const result = await pool.query( 'UPDATE example_table SET name = $1, updated_at = NOW() WHERE id = $2 AND company_code = $3 RETURNING *', [name, id, companyCode] ); // DELETE const result = await pool.query( 'DELETE FROM example_table WHERE id = $1 AND company_code = $2 RETURNING id', [id, companyCode] ); ``` ### 트랜잭션 처리 ```typescript const client = await pool.connect(); try { await client.query('BEGIN'); await client.query('INSERT INTO ...', [params]); await client.query('UPDATE ...', [params]); await client.query('COMMIT'); } catch (e) { await client.query('ROLLBACK'); throw e; } finally { client.release(); } ``` ### 동적 조건 처리 ```typescript const conditions: string[] = ['company_code = $1']; const params: any[] = [companyCode]; let paramIndex = 2; if (searchText) { conditions.push(`name ILIKE $${paramIndex}`); params.push(`%${searchText}%`); paramIndex++; } if (status) { conditions.push(`status = $${paramIndex}`); params.push(status); paramIndex++; } const query = `SELECT * FROM example_table WHERE ${conditions.join(' AND ')} ORDER BY created_at DESC`; const result = await pool.query(query, params); ``` ## 주요 테이블 구조 ### 메뉴 관리 - **menu_info**: 메뉴 정보 - **menu_auth_group**: 메뉴 권한 그룹 - **auth_group**: 권한 그룹 정보 ### 사용자 관리 - **user_info**: 사용자 정보 - **dept_info**: 부서 정보 - **user_auth**: 사용자 권한 ### 코드 관리 - **code_info**: 공통 코드 - **code_category**: 코드 카테고리 ## 마이그레이션 마이그레이션 파일은 `db/migrations/` 디렉토리에 순번으로 관리: ``` db/migrations/ ├── 001_initial_schema.sql ├── 002_add_company_code.sql ├── ... └── 1021_create_numbering_audit_log.sql ``` ## 성능 최적화 ### 인덱스 활용 ```sql CREATE INDEX idx_example_company_code ON example_table(company_code); CREATE INDEX idx_user_dept ON user_info(dept_code); ``` ### 페이징 처리 ```typescript const query = ` SELECT * FROM example_table WHERE company_code = $1 ORDER BY created_at DESC LIMIT $2 OFFSET $3 `; const result = await pool.query(query, [companyCode, limit, offset]); ``` ### 슬로우 쿼리 확인 ```sql SELECT query, mean_time, calls FROM pg_stat_statements ORDER BY mean_time DESC; ```