---
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;
```
