서버 운영
개발 서버와 운영 서버의 로그 레벨을 다르게 설정하는 이유
개발 환경에서 DEBUG 레벨로 찍은 로그를 운영에도 그대로 두면 노이즈가 쌓이고 정작 중요한 에러를 찾기 어려워진다.
로컬에서 개발할 때는 로그가 많을수록 좋다. SQL 쿼리, HTTP 요청 헤더, 미들웨어 통과 경로까지 다 보여야 원인을 빨리 잡는다. 그런데 운영 서버에 이 설정을 그대로 올리면 두 가지 문제가 생긴다. 로그 볼륨이 너무 커서 디스크를 빠르게 먹고, 에러 로그가 디버그 출력에 묻혀 알림이 제때 오지 않는다.
로그 레벨이 무엇을 결정하나
일반적으로 로그 레벨은 낮은 것부터 DEBUG → INFO → WARN → ERROR 순서다. 레벨을 올릴수록 그 레벨 미만의 로그는 출력되지 않는다. 운영 환경에서 WARN 이상만 남기면, 정상 트래픽에서는 조용하다가 실제 문제가 생겼을 때만 로그가 쌓인다.
Next.js에서 직접 로거를 세팅하지 않았다면 console.log가 뒤섞인 코드베이스가 될 가능성이 높다. 작은 프로젝트라면 pino나 winston 같은 구조화 로거를 붙이는 게 낫다.
// lib/logger.ts (pino 사용 예)
import pino from 'pino';
const logger = pino({
level: process.env.LOG_LEVEL ?? (process.env.NODE_ENV === 'production' ? 'warn' : 'debug'),
});
export default logger;
LOG_LEVEL 환경변수로 레벨을 주입하면 코드를 건드리지 않고 운영/스테이징을 다르게 설정할 수 있다.
운영에서 DEBUG를 켜두면 생기는 실제 문제
가장 흔하게 겪은 상황은 Prisma의 query 로그다. prisma.$on('query', ...) 를 켜두면 매 요청마다 실행된 SQL이 전부 출력된다. 트래픽이 적을 땐 괜찮아 보이지만, 동시 요청이 조금만 늘어도 로그 파일이 빠르게 커진다. 로그 로테이션을 설정해두지 않으면 디스크가 찬다.
알림 연동 측면에서도 문제다. Sentry나 DataDog 같은 도구에 console.error를 연결해두었다면, DEBUG 수준의 출력까지 에러로 잡혀 알림 피로가 생긴다.
환경별로 구분하는 간단한 방법
별도 로거 라이브러리를 쓰기 어려운 상황이라면, 최소한 아래처럼 분기를 두는 것만으로도 차이가 난다.
const isDev = process.env.NODE_ENV !== 'production';
export const log = {
debug: (...args: unknown[]) => { if (isDev) console.debug(...args); },
info: (...args: unknown[]) => { console.info(...args); },
warn: (...args: unknown[]) => { console.warn(...args); },
error: (...args: unknown[]) => { console.error(...args); },
};
운영에서는 debug만 무음 처리하고 나머지는 그대로 두는 방식이다. 코드 전체에서 console.log 대신 log.debug를 쓰는 습관을 들이면 나중에 레벨 조정이 한 곳에서 끝난다.
결국 로그는 사건이 발생했을 때 읽는 것이다. 평상시에 조용한 로그가 사건 때 눈에 띈다.