Next.js에 Sentry 연동하기 2026: App Router 실전 설정 가이드

Next.js

Next.js

vs
Sentry

Sentry

프론트엔드 모니터링 도구 비교는 Sentry vs LogRocket vs Datadog 비교 글에서 이미 다뤘습니다. 결론은 Sentry였고, 이 글에서는 Next.js App Router 프로젝트에 Sentry를 실제로 연동하는 전 과정을 정리합니다. "설치하면 끝 아니야?"라고 생각하실 수 있는데, App Router 환경에서는 설정 파일이 여러 개이고 소스맵 업로드까지 고려하면 삽질 포인트가 꽤 많습니다. 직접 겪은 이슈 위주로 정리했으니 그대로 따라하시면 시간을 절약하실 수 있습니다.

1. 패키지 설치 및 초기 세팅

Sentry는 Next.js 전용 SDK를 제공합니다. 일반 @sentry/react가 아니라 반드시 @sentry/nextjs를 사용하셔야 합니다. 서버 컴포넌트, 엣지 런타임, 클라이언트 각각에 맞는 설정을 자동으로 처리해 주기 때문입니다.

# Sentry Wizard로 자동 설정 (권장)
npx @sentry/wizard@latest -i nextjs

위저드를 실행하면 대화형으로 진행되면서 필요한 설정 파일들을 자동 생성합니다. 수동으로 만들 수도 있지만 위저드를 사용하는 것이 실수를 줄여줍니다.

생성 파일 역할
sentry.client.config.ts 클라이언트 사이드 Sentry 초기화
sentry.server.config.ts Node.js 서버 런타임 초기화
sentry.edge.config.ts Edge 런타임 초기화
next.config.js withSentryConfig 래핑 추가
.sentryclirc 소스맵 업로드용 인증 토큰

2. sentry.client.config.ts — 클라이언트 설정

클라이언트 설정에서 가장 중요한 것은 DSN과 샘플링 비율입니다. 개발 중에는 전부 캡처하고, 프로덕션에서는 비율을 조저해야 비용이 폭발하지 않습니다.

import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
  // 프로덕션에서는 10%만 트레이싱
  tracesSampleRate: process.env.NODE_ENV === "production" ? 0.1 : 1.0,
  replaysSessionSampleRate: 0.1,
  replaysOnErrorSampleRate: 1.0,
  integrations: [
    Sentry.replayIntegration(),
    Sentry.browserTracingIntegration(),
  ],
});
⚠️ 삽질 포인트 #1: NEXT_PUBLIC_ 접두사를 빠뜨말면 클라이언트에서 DSN이 undefined가 됩니다. Vercel 대시보드에서 설정할 때도 동일하게 확인하슱니다.

3. sentry.server.config.ts — 서버 설정

서버 쪽은 주른 더 간결합니다. App Router의 서버 컴포넌트에서 발생하는 에러를 잡으려면 이 파일이 반드시 있어야 합니다.

import * as Sentry from "@sentry/nextjs";

Sentry.init({
  dsn: process.env.SENTRY_DSN,
  tracesSampleRate: process.env.NODE_ENV === "production" ? 0.2 : 1.0,
});
⚠️ 삽질 포인트 #2: 서버용 DSN은 NEXT_PUBLIC_ 접두사가 필요 없습니다. 오히려 붙이면 클라이언트 번들에 노출되므로 SENTRY_DSN으로 분리하는 것이 보안상 올바릅니다.

4. next.config.js — withSentryConfig 래핑

기존 Next.js 설정을 withSentryConfig으로 감싸는 형태로 적용합니다. 가장 헷갈리는 부분이므로 아래 코드를 그대로 참고하싱 바랍니다.

const { withSentryConfig } = require("@sentry/nextjs");

const nextConfig = { /* 기존 설정 */ };

module.exports = withSentryConfig(nextConfig, {
  silent: true,
  org: "your-org",
  project: "your-project",
}, {
  // 소스맵을 클라이언트 번들에서 제거 (보안 필수)
  hideSourceMaps: true,
  widenClientFileUpload: true,
  // 광고 차단기 우회 — 실서비스에서 거의 필수
  tunnelRoute: "/monitoring",
});
⚠️ 삽질 포인트 #3: hideSourceMaps: true를 빠트리면 프로덕션 빌드에 소스맵이 포함되어 배포됩니다. 코드가 그대로 노출되는 보안 이슈이므로 반드시 설정하싱 바랍니다.

⚠️ 삽질 포인트 #4: tunnelRoute를 설정하면 Sentry로의 요청이 같은 도메인을 경유합니다. 광고 차단기가 Sentry 요청을 막는 문제를 우회할 수 있어 실서비스에서는 사실상 필수입니다.

5. 소스맵 업로드 — .sentryclirc 설정

에러 발생 시 원본 코드 위치를 보려면 소스맵 업로드가 필수입니다. 프로젝트 루트에 .sentryclirc 파일을 만들거나 환경변수로 토큰을 전달합니다.

# .sentryclirc
[auth]
token=sntrys_eyJ...

[defaults]
org=your-org
project=your-project

중요: > .sentryclirc에 토큰이 들어가므로 반드시 .gitignore에 추가하시기 바랍니다. CI/CD에서는 환경변수 SENTRY_AUTH_TOKEN으로 전달하는 것이 안전합니다.

Vercel 환경변수 설정 설명
SENTRY_AUTH_TOKEN Sentry 인증 토큰
SENTRY_ORG 조직 slug
SENTRY_PROJECT 프로젝트 slug
NEXT_PUBLIC_SENTRY_DSN 클라이언트용 DSN
SENTRY_DSN 서버용 DSN

6. 커스터 에러 페이지 — global-error.tsx

App Router에서는 app/global-error.tsx가 최상위 Error Boundary 역할을 합니다. Sentry와 연동하면 에러 발생 시 자동으로 리포트되면서 사용자에게는 깔끔한 에러 페이지를 보여줄 수 있습니다.

"use client";
import * as Sentry from "@sentry/nextjs";
import { useEffect } from "react";

export default function GlobalError({
  error, reset
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
  useEffect(() => {
    Sentry.captureException(error);
  }, [error]);

  return (
    <html><body>
      <h2>문제가 발생했습니다</h2>
      <button onClick={() => reset()}>다시 시도</button>
    </body></html>
  );
}
⚠️ 삽질 포인트 #5: global-error.tsx는 반드시 "use client"여야 합니다. 서버 컴포넌트로 만들면 Error Boundary가 동작하지 않습니다.

7. 환경별 설정 분리

실무에서는 development, staging, production 환경마다 다르게 동작해야 합니다. 아래 표를 참고해 설정을 분리하시기 바랍니다.

설정 Development Staging Production
DSN 비활성화 스테이징 DSN 프로덕션 DSN
tracesSampleRate 1.0 (100%) 0.5 (50%) 0.1 (10%)
소스맵 업로드
Session Replay 10% 1%

8. 실전 팁 — 직접 겪은 이슈 정리

  • 빌드 시간 증가: withSentryConfig을 적용하면 소스맵 업로드로 인해 빌드가 30초~1분 정도 늘어납니다. CI/CD에서 캐시를 잘 활용하면 완화할 수 있습니다.
  • 번들 사이즈: Sentry SDK가 약 30~40KB(gzipped) 추가됩니다. @sentry/nextjs 8.x부터는 모듈러 임포트가 개선되어 필요한 것만 가져올 수 있습니다.
  • 개발 모드에서 에러 중복: React Strict Mode에서 컴포넌트가 두 번 렌더링되면서 에러도 두 번 잡히는 경우가 있습니다. 개발 중에는 DSN을 비워두면 깔끔합니다.

✅ 마무리 체크리스트

📌 배포 전 Sentry 설정 체크리스트

  • NEXT_PUBLIC_SENTRY_DSN 환경변수 설정 확인
  • hideSourceMaps: true 설정 확인
  • tunnelRoute 설정 (광고 차단기 우회)
  • .sentryclirc.gitignore에 추가
  • global-error.tsx"use client" 선언 확인
  • ☑ 프로덕션 tracesSampleRate 0.1 이하로 조정
  • ☑ Vercel 환경변수 5개 전부 설정 완료

❓ 자주 묻는 질문 (FAQ)

Q. @sentry/nextjs와 @sentry/react의 차이는 무엇입니까?

@sentry/nextjs는 Next.js의 서버 컴포넌트, 엣지 런타임, App Router에 맞는 설정을 자동으로 처리합니다. @sentry/react는 클라이언트 사이드만 지원하므로 Next.js 프로젝트에서는 반드시 @sentry/nextjs를 사용하셔야 합니다.

Q. 소스맵 업로드 없이도 에러 추적이 됩니까?

에러 추적 자체는 됩니다. 다만 소스맵이 없으면 Sentry 대시보드에서 난독화된 번들 코드만 보이므로 에러 위치를 파악하기가 매우 어렵습니다. 실서비스에서는 소스맵 업로드를 반드시 설정하시기 바랍니다.

Q. Sentry 무료 플랜으로 운영이 가능합니까?

소규모 프로젝트라면 무료 플랜(월 5,000 에러)으로 충분합니다. tracesSampleRatereplaysSessionSampleRate를 적절히 낮추면 쿼터를 아낄 수 있습니다. Session Replay는 유료 플랜에서만 정상 동작합니다.

Q. tunnelRoute 설정이 필수입니까?

필수는 아니지만 실서비스에서는 강력히 권장합니다. uBlock Origin 등 광고 차단기가 Sentry 도메인(sentry.io)으로의 요청을 차단하는 경우가 많아, tunnelRoute 없이는 에러 데이터 상당수가 누락될 수 있습니다.

Q. Cloudflare Pages에 배포할 때도 동일한 설정이 적용됩니까?

대부분 동일하게 적용됩니다. 다만 Cloudflare의 엣지 환경에서는 sentry.edge.config.ts 설정이 추가로 필요할 수 있습니다. 환경변수는 Cloudflare 대시보드에서 동일하게 추가하시면 됩니다.

🔗 관련 글

항목
에러 추적Sentry 필수-
성능 모니터링완전 지원-
환경프로덕션/스테이징 분리-
대시보드상세함-
알림 통합Slack/Discord/PagerDuty-
가격이벤트 기반 종량제-

댓글