콘텐츠로 이동

로그 설정 | Next.js용 Sentry

원본 URL: https://docs.sentry.io/platforms/javascript/guides/nextjs/logs

Sentry Logs를 사용하면 Next.js 애플리케이션에서 구조화된 로그 데이터를 전송할 수 있습니다. 기존의 문자열 기반 로깅과 달리, 구조화된 로그에는 쿼리 가능한 속성이 포함되어 있어 특정 사용자, 주문 또는 포함한 비즈니스 컨텍스트로 필터링하여 문제를 더 빠르게 디버깅할 수 있습니다.

세 가지 런타임 파일 모두의 Sentry 설정에 enableLogs: true를 추가하세요.

로그는 모든 Next.js 런타임에서 동작합니다.

  • Client — 브라우저 측 로깅
  • Server — Node.js 서버 측 로깅
  • Edge — Edge 런타임 로깅

instrumentation-client.ts

import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: "___PUBLIC_DSN___",
enableLogs: true,
});

각 메시지에 맞는 적절한 레벨을 사용하세요.

레벨사용 시점
trace세밀한 디버깅
debug개발 진단
info일반 동작, 마일스톤
warn잠재적 문제, 성능 저하 상태
error대응이 필요한 실패
fatal치명적 실패, 시스템 다운
import * as Sentry from "@sentry/nextjs";
// Different log levels
Sentry.logger.trace("Entering function", { fn: "processOrder" });
Sentry.logger.debug("Cache lookup", { key: "user:123" });
Sentry.logger.info("Order created", { orderId: "order_456" });
Sentry.logger.warn("Rate limit approaching", { current: 95, max: 100 });
Sentry.logger.error("Payment failed", { reason: "card_declined" });
Sentry.logger.fatal("Database unavailable", { host: "primary" });

두 번째 인수로 구조화된 데이터를 전달하세요. 이 속성들은 Sentry에서 쿼리 가능한 컬럼이 됩니다.

파라미터화된 메시지에는 fmt 헬퍼를 사용하세요. 값이 검색 가능한 속성으로 추출됩니다.

// Pass attributes directly
Sentry.logger.info("User signed up", {
userId: user.id,
plan: "pro",
referrer: "google",
});
// Use fmt for parameterized messages
Sentry.logger.info(
Sentry.logger.fmt`User ${userId} purchased ${productName}`,
);

스코프에 속성을 설정하면 해당 컨텍스트 내 모든 로그에 자동으로 포함됩니다.

스코프는 Next.js 런타임 간에 전파되지 않습니다. 세 런타임 모두에서 생성되는 로그에 속성을 포함하려면 각 런타임(client, edge, server)에서 getIsolationScope().setAttribute()를 호출하세요. 동시 요청 간 데이터 누수를 방지하려면 전역 스코프가 아니라 격리 스코프를 사용해야 합니다. 서버 측 코드에서는 오류에도 컨텍스트가 포함되도록 모든 try/catch 블록 이전에 컨텍스트를 설정하세요.

자세한 내용은 다양한 스코프 종류를 참고하세요.

// setAttribute() or setAttributes()
// Global scope - shared across entire app
Sentry.getGlobalScope().setAttributes({
service: "checkout",
version: "2.1.0",
});
// Isolation scope - unique per request
Sentry.getIsolationScope().setAttributes({
org_id: user.orgId,
user_tier: user.tier,
});
// Current scope - single operation
Sentry.withScope((scope) => {
scope.setAttribute("request_id", req.id);
Sentry.logger.info("Processing order");
});

상호 연관시키기 어려운 얇은 로그를 많이 남기는 대신, 관련 컨텍스트를 모두 담은 포괄적인 로그를 작업 단위로 하나씩 내보내세요.

이렇게 하면 디버깅 속도가 크게 빨라집니다. 쿼리 한 번으로 특정 주문, 사용자 또는 요청에 대한 모든 정보를 확인할 수 있습니다.

// ❌ Scattered thin logs
Sentry.logger.info("Starting checkout");
Sentry.logger.info("Validating cart");
Sentry.logger.info("Processing payment");
Sentry.logger.info("Checkout complete");
// ✅ One wide event with full context
Sentry.logger.info("Checkout completed", {
orderId: order.id,
userId: user.id,
userTier: user.subscription,
cartValue: cart.total,
itemCount: cart.items.length,
paymentMethod: "stripe",
duration: Date.now() - startTime,
});

우선순위 지정과 디버깅에 도움이 되는 속성을 추가하세요.

  • 사용자 컨텍스트 — 티어, 계정 사용 기간, 생애 가치
  • 트랜잭션 데이터 — 주문 금액, 품목 수
  • 기능 상태 — 활성화된 feature flag
  • 요청 메타데이터 — endpoint, method, duration

이렇게 하면 고가치 고객이나 특정 기능 기준으로 로그를 필터링할 수 있습니다.

Sentry.logger.info("API request completed", {
// User context
userId: user.id,
userTier: user.plan, // "free" | "pro" | "enterprise"
accountAgeDays: user.ageDays,
// Request data
endpoint: "/api/orders",
method: "POST",
duration: 234,
// Business context
orderValue: 149.99,
featureFlags: ["new-checkout", "discount-v2"],
});

코드베이스 전반에서 일관된 네이밍 규칙을 정하고 유지하세요. 이름이 일관되지 않으면 쿼리가 사실상 불가능해집니다.

권장: 일반적인 관례에 맞게 커스텀 속성에는 snake_case를 사용하세요.

// ❌ Inconsistent naming
{ user: "123" }
{ userId: "123" }
{ user_id: "123" }
{ UserID: "123" }
// ✅ Consistent snake_case
{
user_id: "123",
order_id: "456",
cart_value: 99.99,
item_count: 3,
}

console.log, console.warn, console.error 호출을 구조화된 로그로 수집합니다.

이 통합은 여러 인수를 검색 가능한 속성으로 파싱합니다.

Sentry.init({
dsn: "___PUBLIC_DSN___",
enableLogs: true,
integrations: [
Sentry.consoleLoggingIntegration({
levels: ["log", "warn", "error"],
}),
],
});
// Arguments become searchable attributes
console.log("User action:", userId, success);
// -> message.parameter.0: userId
// -> message.parameter.1: success

Pino 로깅 라이브러리의 로그를 Sentry로 전송합니다.

SDK 버전 10.18.0 이상이 필요합니다.

Sentry.init({
dsn: "___PUBLIC_DSN___",
enableLogs: true,
integrations: [Sentry.pinoIntegration()],
});

구성 옵션은 Pino integration docs를 참고하세요.

Consola 로깅 라이브러리의 로그를 Sentry로 전송합니다.

SDK 버전 10.12.0 이상과 Sentry.init 호출의 enableLogs: true 설정이 필요합니다.

import { consola } from "consola";
const sentryReporter = Sentry.createConsolaReporter({
levels: ["error", "warn"], // optional filter
});
consola.addReporter(sentryReporter);

Winston 로깅 라이브러리의 로그를 Sentry로 전송합니다.

SDK 버전 9.13.0 이상과 Sentry.init 호출의 enableLogs: true 설정이 필요합니다.

import winston from "winston";
import Transport from "winston-transport";
const SentryTransport = Sentry.createSentryWinstonTransport(Transport, {
levels: ["error", "warn"], // optional filter
});
const logger = winston.createLogger({
transports: [new SentryTransport()],
});

통합 요청하기

전송 전에 로그를 필터링하거나 수정합니다. 로그를 버리려면 null을 반환하세요.

다음과 같은 용도로 사용하세요.

  • 민감한 데이터 제거
  • 노이즈성 로그 필터링
  • 계산된 속성 추가

instrumentation-client.ts

Sentry.init({
dsn: "___PUBLIC_DSN___",
enableLogs: true,
beforeSendLog(log) {
// Drop debug logs in production
if (log.level === "debug") {
return null;
}
// Remove sensitive attributes
if (log.attributes?.password) {
delete log.attributes.password;
}
return log;
},
});

Sentry는 모든 로그에 다음 속성을 자동으로 추가합니다.

{
"message": "Order completed",
"level": "info",
"attributes": {
// Your custom attributes
"order_id": "order_123",
"user_tier": "pro",
// Core (always present)
"sentry.environment": "production",
"sentry.release": "my-app@1.2.3",
"sentry.sdk.name": "sentry.javascript.nextjs",
"sentry.sdk.version": "9.0.0",
// User (if set via Sentry.setUser)
"user.id": "user_456",
"user.email": "jane@example.com",
"user.name": "Jane",
// Browser (client-side only)
"browser.name": "Chrome",
"browser.version": "120.0.0",
// Server (server-side only)
"server.address": "api-server-1",
// Trace (if tracing enabled)
"sentry.trace.parent_span_id": "abc123",
"sentry.replay_id": "def456",
// Message (when using fmt)
"sentry.message.template": "Order {} completed",
"sentry.message.parameter.0": "order_123",
// Payload
"payload_size": 342
}
}

모든 Sentry 설정 파일에 enableLogs: true가 설정되어 있는지 확인하세요.

  • instrumentation-client.ts (client)
  • sentry.server.config.ts (server)
  • sentry.edge.config.ts (edge)

1 MB보다 큰 로그는 드롭됩니다. 로그가 rate limit에 걸리거나 드롭되는지 확인하려면 org stats를 확인하세요.

속성이 [Filtered]로 표시된다면 server-side data scrubbing에 의해 제거되고 있는 것입니다. 무엇을 필터링할지 조정하려면 프로젝트의 data scrubbing 설정을 확인하세요.