> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 데이터베이스 연결

> DB 연결 문제 해결하기

Sonamu에서 자주 발생하는 데이터베이스 연결 관련 문제와 해결 방법을 다룹니다.

## DB 연결 리소스 누수

### 증상

```bash theme={null}
Error: remaining connection slots are reserved for non-replication superuser connections
```

또는

```bash theme={null}
Error: too many connections for database
```

장시간 개발 서버를 실행하거나, Fixture 작업을 반복할 때 발생합니다.

### 원인

DB 연결을 생성한 후 에러가 발생하면 `destroy()`가 호출되지 않아 연결이 정리되지 않고 누적됩니다.

**문제가 있던 코드 패턴:**

```typescript theme={null}
const db = createKnexInstance(config);

// 여러 작업 수행
await db.raw("SELECT ...");
await db.raw("UPDATE ..."); // 여기서 에러 발생

await db.destroy(); // 도달하지 못함
```

### 해결 방법

#### 1. try-finally 패턴 사용

```typescript theme={null}
const db = createKnexInstance(config);

try {
  await db.raw("SELECT ...");
  await db.raw("UPDATE ...");
  return result;
} finally {
  await db.destroy(); // 에러 발생 여부와 관계없이 실행
}
```

#### 2. 여러 DB 연결 정리

```typescript theme={null}
const sourceDB = createKnexInstance(sourceConfig);
const targetDB = createKnexInstance(targetConfig);

try {
  // 작업 수행
  const data = await sourceDB.select("*").from("users");
  await targetDB.insert(data).into("users");
  return data;
} finally {
  await targetDB.destroy();
  await sourceDB.destroy();
}
```

#### 3. 현재 연결 수 확인

PostgreSQL에서 현재 연결 상태를 확인하려면:

```sql theme={null}
SELECT
  datname,
  count(*) as connections,
  max_conn
FROM pg_stat_activity
JOIN pg_database ON pg_stat_activity.datname = pg_database.datname
WHERE pg_database.datname = 'your_database_name'
GROUP BY datname, max_conn;
```

### 예방 방법

* DB 연결을 직접 생성하는 경우 반드시 try-finally 사용
* BaseModel의 메서드를 사용하면 자동으로 연결 관리됨
* Fixture 작업 시 FixtureManager의 메서드 사용 (자동 정리 포함)

## 연결 설정 오류

### 증상

```bash theme={null}
Error: connect ECONNREFUSED 127.0.0.1:5432
```

### 원인

1. PostgreSQL 서버가 실행되지 않음
2. `.env` 파일의 DB 설정이 잘못됨
3. 포트 번호가 틀림

### 해결 방법

#### 1. PostgreSQL 실행 확인

```bash theme={null}
# macOS (Homebrew)
brew services list
brew services start postgresql

# Linux (systemd)
sudo systemctl status postgresql
sudo systemctl start postgresql
```

#### 2. 연결 정보 확인

`.env` 파일 확인:

```bash theme={null}
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your_password
DB_NAME=your_database
```

#### 3. 수동 연결 테스트

```bash theme={null}
psql -h localhost -p 5432 -U postgres -d your_database
```

성공하면 비밀번호 입력 후 psql 프롬프트가 나타납니다.

## 타임아웃 오류

### 증상

```bash theme={null}
Error: Timeout acquiring a connection. The pool is probably full.
```

### 원인

1. DB 연결 풀이 고갈됨
2. 장시간 실행되는 쿼리가 연결을 점유
3. 연결 풀 설정이 너무 작음

### 해결 방법

#### 1. 연결 풀 설정 조정

`sonamu.config.ts`:

```typescript theme={null}
export default {
  database: {
    miomock: {
      host: "localhost",
      port: 5432,
      user: "postgres",
      password: "password",
      database: "miomock",
      pool: {
        min: 2,
        max: 10, // 기본값보다 증가
        acquireTimeoutMillis: 30000, // 타임아웃 증가
        idleTimeoutMillis: 30000,
      },
    },
  },
} satisfies SonamuConfig;
```

#### 2. 장시간 쿼리 확인

```sql theme={null}
-- 현재 실행 중인 쿼리 확인
SELECT
  pid,
  now() - query_start as duration,
  query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY duration DESC;

-- 특정 쿼리 종료
SELECT pg_cancel_backend(pid);  -- 부드럽게 종료
SELECT pg_terminate_backend(pid);  -- 강제 종료
```

#### 3. 트랜잭션 미정리 확인

```sql theme={null}
-- 오래된 트랜잭션 확인
SELECT
  pid,
  now() - xact_start as duration,
  state,
  query
FROM pg_stat_activity
WHERE xact_start IS NOT NULL
ORDER BY duration DESC;
```

## 권한 오류

### 증상

```bash theme={null}
Error: permission denied for table users
```

### 해결 방법

```sql theme={null}
-- 데이터베이스 소유자 확인
SELECT d.datname, u.usename
FROM pg_database d
JOIN pg_user u ON d.datdba = u.usesysid
WHERE d.datname = 'your_database';

-- 스키마 권한 부여
GRANT ALL ON SCHEMA public TO your_user;

-- 테이블 권한 부여
GRANT ALL ON ALL TABLES IN SCHEMA public TO your_user;

-- 시퀀스 권한 부여
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO your_user;
```

## 테스트 환경 DB 충돌

### 증상

```bash theme={null}
Error: database "miomock_test" already exists
```

또는

```bash theme={null}
Error: database "miomock_test" is being accessed by other users
```

### 원인

* 이전 테스트가 정상 종료되지 않아 테스트 DB가 남아있음
* 여러 테스트 프로세스가 동시에 실행됨

### 해결 방법

#### 1. 테스트 DB 강제 삭제

```bash theme={null}
# 모든 연결 종료 후 DB 삭제
psql -U postgres -c "
  SELECT pg_terminate_backend(pid)
  FROM pg_stat_activity
  WHERE datname = 'miomock_test' AND pid <> pg_backend_pid();
"

psql -U postgres -c "DROP DATABASE IF EXISTS miomock_test;"
```

#### 2. 테스트 실행 시 격리

`package.json`:

```json theme={null}
{
  "scripts": {
    "test": "vitest run --pool=forks --poolOptions.forks.singleFork=true"
  }
}
```

#### 3. 테스트 전후 정리 확인

```typescript theme={null}
// vitest.config.ts
export default defineConfig({
  test: {
    globalSetup: "./test/setup.ts",
    globalTeardown: "./test/teardown.ts",
  },
});
```

```typescript theme={null}
// test/teardown.ts
export default async function teardown() {
  await DB.clearTestTransaction();
  await DB.closeConnection();
}
```

## 관련 문서

* [마이그레이션 오류](/ko/troubleshooting/common-errors/migration-errors)
* [Fixture 사용하기](/ko/testing/fixtures/test-database)
* [데이터베이스 설정](/ko/configuration/sonamu-config/database)
