본문으로 건너뛰기

데이터베이스 설정 (DatabaseConfig)

개요

DatabaseConfig는 애플리케이션에서 사용하는 데이터베이스 연결 설정을 관리합니다. PostgreSQL, Redis 등 데이터 저장소에 대한 접속 정보와 관련 설정을 정의합니다.

구성 요소

PostgreSQL 설정

설정 키환경 변수타입필수 여부기본값설명
postgres.hostDATABASE_HOSTstring필수-PostgreSQL 서버 호스트
postgres.portDATABASE_PORTnumber선택5432PostgreSQL 서버 포트
postgres.usernameDATABASE_USERNAMEstring필수-데이터베이스 사용자 이름
postgres.passwordDATABASE_PASSWORDstring필수-데이터베이스 비밀번호
postgres.databaseDATABASE_NAMEstring필수-데이터베이스 이름
postgres.schemaDATABASE_SCHEMAstring선택'public'데이터베이스 스키마
postgres.sslDATABASE_SSL_ENABLEDboolean선택falseSSL 연결 사용 여부
postgres.maxPoolSizeDATABASE_MAX_POOL_SIZEnumber선택10연결 풀 최대 크기
postgres.idleTimeoutMsDATABASE_IDLE_TIMEOUT_MSnumber선택30000유휴 연결 타임아웃(ms)

Redis 설정

설정 키환경 변수타입필수 여부기본값설명
redis.hostREDIS_HOSTstring선택(cloudrun에서 필수)-Redis 서버 호스트
redis.portREDIS_PORTnumber선택6379Redis 서버 포트
redis.passwordREDIS_PASSWORDstring선택-Redis 서버 비밀번호
redis.dbREDIS_DBnumber선택0Redis 데이터베이스 인덱스
redis.tlsREDIS_TLS_ENABLEDboolean선택falseTLS 연결 사용 여부
redis.ttlREDIS_TTLnumber선택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 마이그레이션을 사용하여 관리하는 것을 권장합니다.