로깅 설정 (LoggingConfig)
개요
LoggingConfig는 애플리케이션 로깅 시스템의 동작 방식을 설정합니다. 로그 레벨, 출력 형식, 저장 위치, 알림 설정 등 로깅 관련 설정을 정의합니다. 특히 GCP BigQuery를 활용한 로그 저장 및 분석을 지원합니다.
구성 요소
핵심 설정 값
| 설정 키 | 환경 변수 | 타입 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|---|
level | LOG_LEVEL | string | 선택 | 'info' | 로그 레벨 ('error', 'warn', 'info', 'debug', 'verbose') |
json | LOG_JSON | boolean | 선택 | false | JSON 형식으로 로그 출력 여부 |
console | LOG_CONSOLE_ENABLED | boolean | 선택 | true | 콘솔 로그 출력 여부 |
BigQuery 설정
| 설정 키 | 환경 변수 | 타입 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|---|
bigquery.enabled | LOG_BIGQUERY_ENABLED | boolean | 선택 | false | BigQuery 로깅 활성화 여부 |
bigquery.projectId | LOG_BIGQUERY_PROJECT_ID | string | 조건부 필수* | - | BigQuery 프로젝트 ID |
bigquery.datasetId | LOG_BIGQUERY_DATASET_ID | string | 조건부 필수* | - | BigQuery 데이터셋 ID |
bigquery.tableId | LOG_BIGQUERY_TABLE_ID | string | 조건부 필수* | - | BigQuery 테이블 ID |
bigquery.retentionDays | LOG_BIGQUERY_RETENTION_DAYS | number | 선택 | 365 | 로그 보존 기간(일) |
* BigQuery 로깅이 활성화된 경우 필수
알림 설정
| 설정 키 | 환경 변수 | 타입 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|---|
alerts.enabled | LOG_ALERTS_ENABLED | boolean | 선택 | false | 로그 알림 활성화 여부 |
alerts.email | LOG_ALERTS_EMAIL | string | 조건부 선택* | - | 이메일 알림 수신 주소 |
alerts.slack | LOG_ALERTS_SLACK_WEBHOOK | string | 조건부 선택* | - | Slack Webhook URL |
* 알림이 활성화된 경우 이메일 또는 Slack 중 하나 이상 필요
사용 예시
구성 정의
// libs/core/config/src/lib/namespaces/logging.config.ts
import { registerAs } from '@nestjs/config';
export const loggingConfig = registerAs('logging', () => ({
level: process.env.LOG_LEVEL || 'info',
json: process.env.LOG_JSON === 'true',
console: process.env.LOG_CONSOLE_ENABLED !== 'false',
bigquery: {
enabled: process.env.LOG_BIGQUERY_ENABLED === 'true',
projectId: process.env.LOG_BIGQUERY_PROJECT_ID,
datasetId: process.env.LOG_BIGQUERY_DATASET_ID,
tableId: process.env.LOG_BIGQUERY_TABLE_ID,
retentionDays: parseInt(process.env.LOG_BIGQUERY_RETENTION_DAYS || '365', 10),
},
alerts: {
enabled: process.env.LOG_ALERTS_ENABLED === 'true',
email: process.env.LOG_ALERTS_EMAIL,
slack: process.env.LOG_ALERTS_SLACK_WEBHOOK,
},
}));
유효성 검증 스키마
// libs/core/config/src/lib/schemas/logging.schema.ts
import * as Joi from 'joi';
export const loggingConfigSchema = {
LOG_LEVEL: Joi.string()
.valid('error', 'warn', 'info', 'debug', 'verbose')
.default('info'),
LOG_JSON: Joi.boolean().default(false),
LOG_CONSOLE_ENABLED: Joi.boolean().default(true),
LOG_BIGQUERY_ENABLED: Joi.boolean().default(false),
LOG_BIGQUERY_PROJECT_ID: Joi.string().when('LOG_BIGQUERY_ENABLED', {
is: true,
then: Joi.string().required(),
otherwise: Joi.string().optional(),
}),
LOG_BIGQUERY_DATASET_ID: Joi.string().when('LOG_BIGQUERY_ENABLED', {
is: true,
then: Joi.string().required(),
otherwise: Joi.string().optional(),
}),
LOG_BIGQUERY_TABLE_ID: Joi.string().when('LOG_BIGQUERY_ENABLED', {
is: true,
then: Joi.string().required(),
otherwise: Joi.string().optional(),
}),
LOG_BIGQUERY_RETENTION_DAYS: Joi.number().default(365),
LOG_ALERTS_ENABLED: Joi.boolean().default(false),
LOG_ALERTS_EMAIL: Joi.string().email().optional(),
LOG_ALERTS_SLACK_WEBHOOK: Joi.string().uri().optional(),
};
로거 서비스에서 사용
// 로깅 설정 사용 예시
import { Injectable, LoggerService } from '@nestjs/common';
import { ConfigService } from '@core/config';
import { createLogger, Logger, format, transports } from 'winston';
import { BigQuery } from '@google-cloud/bigquery';
@Injectable()
export class AppLogger implements LoggerService {
private logger: Logger;
private context: string = 'Application';
constructor(private readonly configService: ConfigService) {
// 로깅 설정 로드
const logConfig = this.configService.getNamespace<{
level: string;
json: boolean;
console: boolean;
bigquery: {
enabled: boolean;
projectId?: string;
datasetId?: string;
tableId?: string;
};
}>('logging');
// Winston 로거 구성
this.logger = createLogger({
level: logConfig.level,
format: logConfig.json
? format.combine(format.timestamp(), format.json())
: format.combine(
format.timestamp(),
format.colorize(),
format.printf(({ timestamp, level, message, context, ...metadata }) => {
return `${timestamp} [${context || this.context}] ${level}: ${message} ${
Object.keys(metadata).length ? JSON.stringify(metadata) : ''
}`;
})
),
transports: [],
});
// 콘솔 로그 설정
if (logConfig.console) {
this.logger.add(new transports.Console());
}
// BigQuery 로그 설정
if (logConfig.bigquery?.enabled &&
logConfig.bigquery.projectId &&
logConfig.bigquery.datasetId &&
logConfig.bigquery.tableId) {
// BigQuery 로깅 트랜스포트 추가 (여기서는 간략하게 표현)
this.setupBigQueryTransport(
logConfig.bigquery.projectId,
logConfig.bigquery.datasetId,
logConfig.bigquery.tableId
);
}
}
setContext(context: string) {
this.context = context;
return this;
}
log(message: string, context?: string, ...metadata: any[]) {
this.logger.info(message, { context: context || this.context, ...metadata });
}
error(message: string, trace?: string, context?: string, ...metadata: any[]) {
this.logger.error(message, { trace, context: context || this.context, ...metadata });
}
warn(message: string, context?: string, ...metadata: any[]) {
this.logger.warn(message, { context: context || this.context, ...metadata });
}
debug(message: string, context?: string, ...metadata: any[]) {
this.logger.debug(message, { context: context || this.context, ...metadata });
}
verbose(message: string, context?: string, ...metadata: any[]) {
this.logger.verbose(message, { context: context || this.context, ...metadata });
}
private setupBigQueryTransport(projectId: string, datasetId: string, tableId: string) {
// BigQuery 로깅 로직 구현
// 실제 구현은 winston-bigquery-transport와 같은 라이브러리 사용 가능
// 또는 커스텀 트랜스포트 구현
}
}
환경별 설정 가이드
로컬 개발 환경
로컬 개발 환경에서는 서비스별 JSON 설정 파일을 통해 로깅 설정을 구성합니다. 일반적으로 콘솔 로깅을 주로 사용하고 자세한 디버그 정보를 출력합니다.
// cloudrun-deploy/secret/local/dev/dta-wide-api.json
{
"LOG_LEVEL": "debug",
"LOG_JSON": "false",
"LOG_CONSOLE_ENABLED": "true",
"LOG_BIGQUERY_ENABLED": "false"
}
클라우드 런 개발 환경
개발 환경의 클라우드 런에서는 서비스별 JSON 설정 파일을 통해 구조화된 로깅과 BigQuery 로깅을 활성화합니다.
// cloudrun-deploy/secret/cloudrun/dev/dta-wide-api.json
{
"LOG_LEVEL": "debug",
"LOG_JSON": "true",
"LOG_CONSOLE_ENABLED": "true",
"LOG_BIGQUERY_ENABLED": "true",
"LOGGING_BIGQUERY_PROJECT_ID": "dta-cloud-de-dev",
"LOGGING_BIGQUERY_DATASET_ID": "logging",
"LOGGING_BIGQUERY_SYSTEM_LOGS_TABLE": "system_logs",
"LOGGING_BIGQUERY_ERROR_LOGS_TABLE": "error_logs",
"LOGGING_BIGQUERY_METRIC_LOGS_TABLE": "metric_logs",
"LOGGING_RETENTION_SYSTEM_DAYS": "30",
"LOG_ALERTS_ENABLED": "false"
}
클라우드 런 프로덕션 환경
프로덕션 환경에서는 서비스별 JSON 설정 파일을 통해 필요한 정보만 로깅하고 알림 기능을 활성화합니다.
// cloudrun-deploy/secret/cloudrun/prod/dta-wide-api.json
{
"LOG_LEVEL": "info",
"LOG_JSON": "true",
"LOG_CONSOLE_ENABLED": "true",
"LOG_BIGQUERY_ENABLED": "true",
"LOGGING_BIGQUERY_PROJECT_ID": "dta-cloud-de-prod",
"LOGGING_BIGQUERY_DATASET_ID": "logging",
"LOGGING_BIGQUERY_SYSTEM_LOGS_TABLE": "system_logs",
"LOGGING_BIGQUERY_ERROR_LOGS_TABLE": "error_logs",
"LOGGING_BIGQUERY_METRIC_LOGS_TABLE": "metric_logs",
"LOGGING_RETENTION_SYSTEM_DAYS": "30",
"LOGGING_RETENTION_ERROR_DAYS": "90",
"LOGGING_RETENTION_METRIC_DAYS": "365",
"LOG_ALERTS_ENABLED": "true",
"LOG_ALERTS_EMAIL": "alerts@weltcorp.com",
"LOG_ALERTS_SLACK_WEBHOOK": "https://hooks.slack.com/services/xxx/yyy/zzz"
}
로그 데이터 구조
BigQuery에 저장되는 로그 데이터의 스키마는 다음과 같습니다:
| 필드 | 타입 | 설명 |
|---|---|---|
timestamp | TIMESTAMP | 로그 발생 시간 |
service | STRING | 서비스 이름 |
level | STRING | 로그 레벨 |
message | STRING | 로그 메시지 |
context | STRING | 로그 컨텍스트 |
trace | STRING | 오류 추적 정보 |
environment | STRING | 환경 (dev, staging, prod) |
version | STRING | 애플리케이션 버전 |
metadata | JSON | 추가 로그 메타데이터 |
request_id | STRING | 요청 ID (추적용) |
user_id | STRING | 사용자 ID (추적용) |
주의 사항
- 민감한 정보: 로그에 개인 식별 정보(PII)나 민감한 데이터를 포함하지 않도록 주의하세요.
- 로그 볼륨: 과도한 로깅은 성능에 영향을 미치고 비용을 증가시킬 수 있습니다. 적절한 로그 레벨을 사용하세요.
- BigQuery 비용: BigQuery 로깅을 사용할 때는 데이터 볼륨과 쿼리 비용을 고려하세요.
- 로그 보존: 정책에 따라 적절한 로그 보존 기간을 설정하세요.
- 구조화된 로깅: 클라우드 환경에서는 구조화된 로깅(JSON)을 사용하여 로그 분석과 검색을 용이하게 하세요.