NestJS와 Prisma로 로그 제어하기: 효과적인 백엔드 로깅 방법
2025-02-12 02:13:46NestJS와 Prisma: 로그 관리를 위한 새로운 접근
NestJS와 Prisma는 각각 현대적인 웹 애플리케이션 개발에 널리 쓰이는 프레임워크와 ORM으로, 두 기술을 결합하면 강력한 백엔드 솔루션을 구축할 수 있습니다. 백엔드 시스템에서 로그 관리는 애플리케이션의 디버깅과 모니터링에 중요합니다. 이 글에서는 Prisma 클라이언트의 로그 시스템 문제를 해결하고, NestJS에서 효과적으로 로그를 관리하는 방법을 설명하겠습니다.
Prisma의 기본 로그 설정과 문제점
Prisma는 TypeScript로 작성된 ORM으로, 데이터베이스와의 상호작용을 단순화합니다. 그러나 기본적으로 제공되는 로그 시스템은 모든 로그 메시지를 표준 출력(콘솔)에 직접 보내는 방식입니다. 이는 제한적이며, 특히 로그를 더욱 체계적으로 관리하거나 별도의 로그 파일로 보관하고자 할 때 문제가 됩니다.
기본 PrismaService 코드
NestJS 애플리케이션에서 Prisma를 사용하기 위해서는 다음과 같은 PrismaService를 정의합니다.
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
async onModuleDestroy() {
await this.$disconnect();
}
async onModuleInit() {
await this.$connect();
}
}
이 설정에서는 기본적으로 로그 관련 설정을 하지 않으므로, 로그 메시지가 발생하면 모두 콘솔에 출력됩니다.
로그 제어하기: Constructor와 이벤트 사용
로그를 보다 세부적으로 제어하기 위해 Prisma 클라이언트의 로그 옵션을 설정할 수 있습니다. 이는 주로 constructor에서 이루어지며, emit: 'event' 속성을 통해 영향력 있는 이벤트 기반 로그 시스템을 구축합니다.
PrismaService의 로그 설정
로그를 보다 정밀하게 관리하려면, Prisma 클라이언트의 인스턴스를 생성할 때 log 옵션을 지정해야 합니다. 다음은 constructor에서 log 옵션을 설정하는 예시입니다.
constructor() {
super({
log: [
{ emit: 'event', level: 'query' },
{ emit: 'stdout', level: 'info' },
{ emit: 'stdout', level: 'warn' },
{ emit: 'stdout', level: 'error' },
],
errorFormat: 'pretty',
});
}
위 코드는 Prisma에서 제공하는 여러 로그 레벨에 대해 로그 방식을 설정합니다. query 레벨의 로그는 이벤트로 emit되며, 나머지 레벨은 콘솔에 출력됩니다.
이벤트 기반 로그 처리
이벤트 기반으로 로그를 처리하면, 로그 메시지를 원하는 대로 제어할 수 있습니다. 이를 통해 특정 이벤트에 대한 특별한 로그 처리를 구현할 수 있습니다.
이벤트 로그 수신기 설정
emit: 'event'로 설정된 로그는 특정 이벤트로 캐치할 수 있습니다. 예를 들어, 다음과 같이 로그 이벤트를 수신하여 커스터마이즈된 로그 메시지를 생성할 수 있습니다.
this.$on('query', (event) => {
this.logger.log(`[Duration]: ${event.duration} ms`);
this.logger.log(`[Timestamp]: ${event.timestamp}`);
this.logger.log(`[Query]: ${event.query}`);
});
이러한 방식으로 쿼리 로그의 상세 정보를 추출하여 필요한 부분만을 로깅하거나, 추가적인 프로세싱을 수행할 수 있습니다.
TypeScript와의 통합
NestJS와 Prisma를 함께 사용할 때, TypeScript의 타입 시스템이 때때로 문제를 발생시킬 수 있습니다. 특히, Prisma의 이벤트 이름으로 사용되는 문자열에 대해 TypeScript가 오류를 발생시킬 수 있습니다.
Type 오류 해결하기
TypeScript 오류 예시는 다음과 같습니다.
The argument of type '"query"' is not assignable to parameter of type 'never'.ts(2345)
이는 PrismaClient의 인스턴스 생성 시 로그 시스템의 제네릭을 명확히 지정하지 않았기 때문입니다. 이를 해결하려면 다음과 같이 제네릭을 추가합니다.
import { Prisma, PrismaClient } from '@prisma/client';
export class PrismaService extends PrismaClient<Prisma.PrismaClientOptions, Prisma.LogLevel> {
// 기존의 PrismaService 코드
}
위 코드는 Prisma 클라이언트를 생성할 때 로그 레벨에 대한 제네릭 타입을 명시적으로 지정하여 TypeScript 오류를 해결할 수 있습니다.
마무리
NestJS와 Prisma를 활용하여 로그를 보다 효과적으로 관리함으로써, 애플리케이션의 유지보수성과 모니터링 효율성을 높일 수 있습니다. 이 글에서는 Prisma의 기본 로그 설정의 문제점을 극복하고, 더욱 강력한 로깅 시스템을 구축하는 방법을 살펴보았습니다. TypeScript의 타입 안전성을 유지하면서도 실용적인 로그 관리 기능을 구현할 수 있습니다.