기본 구조
복사
import { defineConfig } from "sonamu";
export default defineConfig({
database: {
database: "pg",
name: "mydb",
defaultOptions: {
connection: {
host: "localhost",
port: 5432,
user: "postgres",
password: "password",
},
},
environments: {
development: { /* ... */ },
production: { /* ... */ },
},
},
// ...
});
database
사용할 PostgreSQL 드라이버를 지정합니다. 타입:"pg" | "pgnative" (선택적)
기본값: "pg"
복사
export default defineConfig({
database: {
database: "pg", // 기본 pg 모듈 사용
// ...
},
});
pg vs pgnative
-
"pg": 순수 JavaScript로 구현된 PostgreSQL 드라이버 (권장)- 설치:
pnpm add pg - 크로스 플랫폼 지원
- 대부분의 경우 충분한 성능
- 설치:
-
"pgnative": C 바인딩을 사용하는 네이티브 드라이버- 설치:
pnpm add pg-native - 더 빠른 성능 (특히 대량 데이터 처리)
- 컴파일 필요, 플랫폼 의존성
- 설치:
특별한 성능 요구사항이 없다면
"pg"를 사용하세요. 설치와 배포가 간단합니다.name
데이터베이스 이름을 지정합니다. 타입:string (필수)
복사
export default defineConfig({
database: {
database: "pg",
name: "ecommerce", // 연결할 데이터베이스 이름
// ...
},
});
복사
export default defineConfig({
database: {
database: "pg",
name: process.env.DATABASE_NAME ?? "mydb",
// ...
},
});
defaultOptions
모든 환경에 공통으로 적용될 데이터베이스 설정입니다. Knex 설정 옵션을 사용합니다. 타입:DatabaseConfig (필수)
복사
type DatabaseConfig = Omit<Knex.Config, "connection"> & {
connection?: Knex.PgConnectionConfig;
};
connection 설정
데이터베이스 연결 정보를 설정합니다.복사
export default defineConfig({
database: {
database: "pg",
name: "mydb",
defaultOptions: {
connection: {
host: "localhost", // 데이터베이스 호스트
port: 5432, // PostgreSQL 포트
user: "postgres", // 사용자 이름
password: "password", // 비밀번호
},
},
},
});
복사
export default defineConfig({
database: {
database: "pg",
name: process.env.DATABASE_NAME ?? "mydb",
defaultOptions: {
connection: {
host: process.env.DB_HOST ?? "localhost",
port: Number(process.env.DB_PORT ?? 5432),
user: process.env.DB_USER ?? "postgres",
password: process.env.DB_PASSWORD,
},
},
},
});
데이터베이스 비밀번호는 반드시 환경 변수로 관리하세요. 코드에 직접 작성하지 마세요!
추가 Knex 옵션
connection 외에도 다양한 Knex 옵션을 설정할 수 있습니다:복사
export default defineConfig({
database: {
database: "pg",
name: "mydb",
defaultOptions: {
connection: { /* ... */ },
// 커넥션 풀 설정
pool: {
min: 2,
max: 10,
acquireTimeoutMillis: 30000,
idleTimeoutMillis: 30000,
},
// 쿼리 타임아웃
acquireConnectionTimeout: 10000,
// 디버그 모드
debug: process.env.NODE_ENV === "development",
},
},
});
environments
환경별로 다른 데이터베이스 설정을 지정합니다.defaultOptions를 오버라이드합니다.
타입: (선택적)
복사
environments?: {
development?: DatabaseConfig;
development_slave?: DatabaseConfig;
production?: DatabaseConfig;
production_slave?: DatabaseConfig;
fixture?: DatabaseConfig;
test?: DatabaseConfig;
}
환경별 설정 예시
복사
export default defineConfig({
database: {
database: "pg",
name: "mydb",
defaultOptions: {
connection: {
host: "localhost",
port: 5432,
user: "postgres",
password: "dev-password",
},
},
environments: {
// 개발 환경 (기본값 사용)
development: {
connection: {
host: "localhost",
port: 5432,
user: "dev_user",
password: "dev_password",
},
},
// 프로덕션 환경
production: {
connection: {
host: process.env.PROD_DB_HOST,
port: Number(process.env.PROD_DB_PORT),
user: process.env.PROD_DB_USER,
password: process.env.PROD_DB_PASSWORD,
},
pool: {
min: 5,
max: 30, // 프로덕션에서는 더 큰 풀
},
},
// 테스트 환경
test: {
connection: {
host: "localhost",
port: 5432,
user: "test_user",
password: "test_password",
database: "mydb_test", // 별도의 테스트 DB
},
},
},
},
});
현재 환경 결정
Sonamu는 다음 순서로 현재 환경을 결정합니다:NODE_ENV환경 변수- 기본값:
development
복사
# 개발 환경
NODE_ENV=development pnpm dev
# 프로덕션 환경
NODE_ENV=production pnpm start
# 테스트 환경
NODE_ENV=test pnpm test
Slave DB 설정
읽기 전용 복제본(slave)을 사용하는 경우:복사
export default defineConfig({
database: {
database: "pg",
name: "mydb",
defaultOptions: { /* ... */ },
environments: {
production: {
connection: {
host: "master.db.example.com",
port: 5432,
user: "master_user",
password: process.env.MASTER_DB_PASSWORD,
},
},
production_slave: {
connection: {
host: "slave.db.example.com",
port: 5432,
user: "slave_user",
password: process.env.SLAVE_DB_PASSWORD,
},
},
},
},
});
Slave DB는 읽기 전용 쿼리에 사용되어 마스터 DB의 부하를 분산시킵니다.
실전 예시
기본 로컬 개발 설정
복사
import { defineConfig } from "sonamu";
export default defineConfig({
database: {
database: "pg",
name: "myapp",
defaultOptions: {
connection: {
host: "localhost",
port: 5432,
user: "postgres",
password: "postgres",
},
},
},
// ...
});
환경 변수 활용 (권장)
복사
import { defineConfig } from "sonamu";
export default defineConfig({
database: {
database: "pg",
name: process.env.DATABASE_NAME ?? "myapp",
defaultOptions: {
connection: {
host: process.env.DB_HOST ?? "localhost",
port: Number(process.env.DB_PORT ?? 5432),
user: process.env.DB_USER ?? "postgres",
password: process.env.DB_PASSWORD,
},
pool: {
min: 2,
max: 10,
},
},
},
// ...
});
복사
DATABASE_NAME=myapp
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=your-password-here
다중 환경 설정
복사
import { defineConfig } from "sonamu";
const isDev = process.env.NODE_ENV === "development";
const isProd = process.env.NODE_ENV === "production";
export default defineConfig({
database: {
database: "pg",
name: "ecommerce",
defaultOptions: {
connection: {
host: process.env.DB_HOST ?? "localhost",
port: Number(process.env.DB_PORT ?? 5432),
user: process.env.DB_USER ?? "postgres",
password: process.env.DB_PASSWORD,
},
debug: isDev,
},
environments: {
development: {
connection: {
host: "localhost",
port: 5432,
user: "dev_user",
password: "dev_password",
database: "ecommerce_dev",
},
pool: {
min: 2,
max: 10,
},
},
production: {
connection: {
host: process.env.PROD_DB_HOST,
port: Number(process.env.PROD_DB_PORT),
user: process.env.PROD_DB_USER,
password: process.env.PROD_DB_PASSWORD,
database: "ecommerce_prod",
},
pool: {
min: 5,
max: 30,
},
acquireConnectionTimeout: 60000,
},
production_slave: {
connection: {
host: process.env.PROD_SLAVE_DB_HOST,
port: Number(process.env.PROD_SLAVE_DB_PORT),
user: process.env.PROD_SLAVE_DB_USER,
password: process.env.PROD_SLAVE_DB_PASSWORD,
database: "ecommerce_prod",
},
pool: {
min: 3,
max: 20,
},
},
test: {
connection: {
host: "localhost",
port: 5432,
user: "test_user",
password: "test_password",
database: "ecommerce_test",
},
pool: {
min: 1,
max: 5,
},
},
fixture: {
connection: {
host: "localhost",
port: 5432,
user: "fixture_user",
password: "fixture_password",
database: "ecommerce_fixture",
},
},
},
},
// ...
});
Docker Compose 환경
복사
import { defineConfig } from "sonamu";
export default defineConfig({
database: {
database: "pg",
name: "myapp",
defaultOptions: {
connection: {
// Docker Compose의 서비스 이름 사용
host: process.env.DB_HOST ?? "postgres",
port: Number(process.env.DB_PORT ?? 5432),
user: process.env.DB_USER ?? "postgres",
password: process.env.DB_PASSWORD ?? "postgres",
},
},
},
// ...
});
복사
services:
postgres:
image: postgres:16
environment:
POSTGRES_DB: myapp
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- "5432:5432"
api:
build: .
environment:
DB_HOST: postgres # 서비스 이름
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: postgres
DATABASE_NAME: myapp
연결 테스트
데이터베이스 설정이 올바른지 확인하려면:복사
# 개발 서버 시작
pnpm dev
# 연결 성공 시 콘솔에 표시됨
# ✅ Database connected: myapp
복사
# 1. 비밀번호 오류
❌ password authentication failed for user "postgres"
# 2. 호스트 연결 실패
❌ connect ECONNREFUSED 127.0.0.1:5432
# 3. 데이터베이스가 존재하지 않음
❌ database "myapp" does not exist
연결 문제가 발생하면 PostgreSQL이 실행 중인지 확인하세요:
복사
# macOS
brew services list
# Linux
systemctl status postgresql
# Docker
docker ps
주의사항
1. 비밀번호 보안
복사
// ❌ 나쁜 예: 코드에 비밀번호 직접 작성
export default defineConfig({
database: {
defaultOptions: {
connection: {
password: "super-secret-password", // 절대 금지!
},
},
},
});
// ✅ 좋은 예: 환경 변수 사용
export default defineConfig({
database: {
defaultOptions: {
connection: {
password: process.env.DB_PASSWORD,
},
},
},
});
2. 포트 번호 타입
복사
// ❌ 나쁜 예: 문자열로 포트 지정
port: process.env.DB_PORT, // "5432" (string)
// ✅ 좋은 예: 숫자로 변환
port: Number(process.env.DB_PORT ?? 5432), // 5432 (number)
3. 커넥션 풀 크기
복사
// 개발 환경: 작은 풀
pool: { min: 2, max: 10 }
// 프로덕션: 트래픽에 맞게 조정
pool: { min: 5, max: 30 }
// 테스트: 최소한으로
pool: { min: 1, max: 5 }
다음 단계
데이터베이스 설정을 완료했다면:- server - 서버 옵션 및 플러그인 설정
- database/migrations - 마이그레이션으로 스키마 관리
- troubleshooting - 연결 문제 해결