데이터베이스 설정 (DatabaseConfig)
개요
DatabaseConfig는 애플리케이션에서 사용하는 데이터베이스 연결 설정을 관리합니다. PostgreSQL, Redis 등 데이터 저장소에 대한 접속 정보와 관련 설정을 정의합니다.
구성 요소
PostgreSQL 설정
| 설정 키 | 환경 변수 | 타입 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|---|
postgres.host | DATABASE_HOST | string | 필수 | - | PostgreSQL 서버 호스트 |
postgres.port | DATABASE_PORT | number | 선택 | 5432 | PostgreSQL 서버 포트 |
postgres.username | DATABASE_USERNAME | string | 필수 | - | 데이터베이스 사용자 이름 |
postgres.password | DATABASE_PASSWORD | string | 필수 | - | 데이터베이스 비밀번호 |
postgres.database | DATABASE_NAME | string | 필수 | - | 데이터베이스 이름 |
postgres.schema | DATABASE_SCHEMA | string | 선택 | 'public' | 데이터베이스 스키마 |
postgres.ssl | DATABASE_SSL_ENABLED | boolean | 선택 | false | SSL 연결 사용 여부 |
postgres.maxPoolSize | DATABASE_MAX_POOL_SIZE | number | 선택 | 10 | 연결 풀 최대 크기 |
postgres.idleTimeoutMs | DATABASE_IDLE_TIMEOUT_MS | number | 선택 | 30000 | 유휴 연결 타임아웃(ms) |
Redis 설정
| 설정 키 | 환경 변수 | 타입 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|---|
redis.host | REDIS_HOST | string | 선택(cloudrun에서 필수) | - | Redis 서버 호스트 |
redis.port | REDIS_PORT | number | 선택 | 6379 | Redis 서버 포트 |
redis.password | REDIS_PASSWORD | string | 선택 | - | Redis 서버 비밀번호 |
redis.db | REDIS_DB | number | 선택 | 0 | Redis 데이터베이스 인덱스 |
redis.tls | REDIS_TLS_ENABLED | boolean | 선택 | false | TLS 연결 사용 여부 |
redis.ttl | REDIS_TTL | number | 선택 | 86400 | 기본 캐시 만료 시간(초) |
사용 예시
구성 정의
// libs/core/config/src/lib/namespaces/database.config.ts
import { registerAs } from '@nestjs/config';
export const databaseConfig = registerAs('database', () => ({
postgres: {
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT || '5432', 10),
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
schema: process.env.DATABASE_SCHEMA || 'public',
ssl: process.env.DATABASE_SSL_ENABLED === 'true',
maxPoolSize: parseInt(process.env.DATABASE_MAX_POOL_SIZE || '10', 10),
idleTimeoutMs: parseInt(process.env.DATABASE_IDLE_TIMEOUT_MS || '30000', 10),
},
redis: {
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || '6379', 10),
password: process.env.REDIS_PASSWORD,
db: parseInt(process.env.REDIS_DB || '0', 10),
tls: process.env.REDIS_TLS_ENABLED === 'true',
ttl: parseInt(process.env.REDIS_TTL || '86400', 10),
},
}));
유효성 검증 스키마
// libs/core/config/src/lib/schemas/database.schema.ts
import * as Joi from 'joi';
export const databaseConfigSchema = {
DATABASE_HOST: Joi.string().required(),
DATABASE_PORT: Joi.number().default(5432),
DATABASE_USERNAME: Joi.string().required(),
DATABASE_PASSWORD: Joi.string().required(),
DATABASE_NAME: Joi.string().required(),
DATABASE_SCHEMA: Joi.string().default('public'),
DATABASE_SSL_ENABLED: Joi.boolean().default(false),
DATABASE_MAX_POOL_SIZE: Joi.number().default(10),
DATABASE_IDLE_TIMEOUT_MS: Joi.number().default(30000),
REDIS_HOST: Joi.string().when('RUNTIME_ENV', {
is: 'cloudrun',
then: Joi.string().required(),
otherwise: Joi.string().optional(),
}),
REDIS_PORT: Joi.number().default(6379),
REDIS_PASSWORD: Joi.string().optional(),
REDIS_DB: Joi.number().default(0),
REDIS_TLS_ENABLED: Joi.boolean().default(false),
REDIS_TTL: Joi.number().default(86400),
};
PostgreSQL 서비스에서 사용
// PostgreSQL 설정 사용 예시
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@core/config';
import { Pool } from 'pg';
@Injectable()
export class PostgresService {
private pool: Pool;
constructor(private readonly configService: ConfigService) {
// PostgreSQL 설정 로드
const postgresConfig = this.configService.getConfig<{
host: string;
port: number;
username: string;
password: string;
database: string;
ssl: boolean;
maxPoolSize: number;
idleTimeoutMs: number;
}>('database', 'postgres');
// 연결 풀 초기화
this.pool = new Pool({
host: postgresConfig.host,
port: postgresConfig.port,
user: postgresConfig.username,
password: postgresConfig.password,
database: postgresConfig.database,
ssl: postgresConfig.ssl ? { rejectUnauthorized: false } : false,
max: postgresConfig.maxPoolSize,
idleTimeoutMillis: postgresConfig.idleTimeoutMs,
});
}
async query(text: string, params: any[] = []): Promise<any> {
const client = await this.pool.connect();
try {
return await client.query(text, params);
} finally {
client.release();
}
}
}
Redis 서비스에서 사용
// Redis 설정 사용 예시
import { Injectable, OnModuleDestroy } from '@nestjs/common';
import { ConfigService } from '@core/config';
import Redis from 'ioredis';
@Injectable()
export class RedisService implements OnModuleDestroy {
private readonly redis: Redis;
constructor(private readonly configService: ConfigService) {
// Redis 설정 로드
const redisConfig = this.configService.getConfig<{
host: string;
port: number;
password?: string;
db: number;
tls: boolean;
ttl: number;
}>('database', 'redis');
// Redis 클라이언트 초기화 (host가 있는 경우에만)
if (redisConfig.host) {
this.redis = new Redis({
host: redisConfig.host,
port: redisConfig.port,
password: redisConfig.password,
db: redisConfig.db,
tls: redisConfig.tls ? {} : undefined,
});
}
}
async get(key: string): Promise<string | null> {
if (!this.redis) return null;
return this.redis.get(key);
}
async set(key: string, value: string, ttl?: number): Promise<void> {
if (!this.redis) return;
const expiration = ttl || this.configService.getConfig<number>('database', 'redis.ttl', 86400);
await this.redis.set(key, value, 'EX', expiration);
}
onModuleDestroy() {
if (this.redis) {
this.redis.disconnect();
}
}
}
환경별 설정 가이드
로컬 개발 환경
로컬 개발 환경에서는 서비스별 JSON 설정 파일을 통해 데이터베이스 설정을 구성합니다. 일반적으로 로컬 호스트나 Docker 컨테이너로 실행된 데이터베이스에 연결합니다.
// cloudrun-deploy/secret/local/dev/dta-wide-api.json
{
"DATABASE_HOST": "localhost",
"DATABASE_PORT": "5432",
"DATABASE_USERNAME": "postgres",
"DATABASE_PASSWORD": "welt10004",
"DATABASE_NAME": "wir_v_0_3_0",
"DATABASE_SCHEMA": "public",
"DATABASE_SSL_ENABLED": "false",
"DATABASE_MAX_POOL_SIZE": "10",
"REDIS_HOST": "localhost",
"REDIS_PORT": "6379",
"REDIS_PASSWORD": "",
"REDIS_DB": "0",
"REDIS_TLS_ENABLED": "false"
}
클라우드 런 환경
클라우드 런 환경에서는 서비스별 JSON 설정 파일의 내용이 Cloud Run 서비스의 환경 변수로 설정되며, Cloud SQL 및 Memorystore에 연결합니다.
// cloudrun-deploy/secret/cloudrun/dev/dta-wide-api.json
{
"DATABASE_HOST": "127.0.0.1",
"DATABASE_PORT": "5432",
"DATABASE_USERNAME": "postgres",
"DATABASE_PASSWORD": "welt10004",
"DATABASE_NAME": "wir_v_0_3_0",
"DATABASE_SCHEMA": "public",
"DATABASE_SSL_ENABLED": "true",
"DATABASE_MAX_POOL_SIZE": "20",
"INSTANCE_UNIX_SOCKET": "/cloudsql/dta-cloud-de-dev:europe-west3:db-dta-mono-dev",
"REDIS_HOST": "10.1.0.3",
"REDIS_PORT": "6379",
"REDIS_CACHE_DB": "0",
"REDIS_TEMP_DB": "1",
"REDIS_TLS_ENABLED": "true"
}
주의 사항
- 보안: 데이터베이스 자격 증명은 민감한 정보이므로 프로덕션 환경에서는 반드시 Secret Manager를 통해 관리해야 합니다.
- 연결 풀링: 프로덕션 환경에서는 적절한 연결 풀 크기를 설정하여 데이터베이스 리소스를 효율적으로 사용해야 합니다.
- 고가용성: 프로덕션 환경에서는 데이터베이스 장애 시 대응 방안(읽기 전용 복제본, 장애 조치 등)을 고려해야 합니다.
- 로컬 개발: 로컬 개발 시에는 Docker를 통해 데이터베이스를 실행하는 것이 권장됩니다.
- 데이터베이스 마이그레이션: 스키마 변경 시 Prisma 마이그레이션을 사용하여 관리하는 것을 권장합니다.