📚 목차
[Next.js] Next.js에서 Sentry 도입: 에러 모니터링과 성능 추적
Sentry는 웹 애플리케이션의 에러 모니터링과 성능 추적을 위한 플랫폼이다.
최근 Next.js로 개발한 프로젝트를 리팩토링하고 있는데 에러 모니터링과 성능 추적을 위해 Sentry를 도입하게 되었다.
이번 포스팅에서는 Sentry를 도입하게 된 이유와 도입 과정, 그리고 트러블 슈팅 과정을 공유하고자 한다.
Sentry에 대한 자세한 내용은 Sentry 공식 문서와 여러 해외 글들을 참고하였다.
왜 Sentry를 도입하게 되었는가?
1. 프로덕션 환경의 에러 추적 필요성
개발 환경에서는 에러가 발생하면 즉시 콘솔에서 확인할 수 있지만, 프로덕션 환경에서는 사용자가 겪는 에러를 실시간으로 파악하기 어렵다.
특히 다음과 같은 상황에서 Sentry의 필요성이 절실하다.
- 사용자 경험 저하: 사용자가 겪는 에러를 모르고 방치하면 UX가 크게 저하된다
- 비즈니스 손실: 결제 실패, 기능 오류 등이 발생해도 즉시 알 수 없어 매출에 영향을 준다
- 디버깅의 어려움: 프로덕션 에러는 재현하기 어렵고, 스택 트레이스 없이는 원인 파악이 불가능하다
2. 성능 모니터링의 중요성
웹 애플리케이션의 성능은 사용자 만족도와 직접적으로 연결된다.
- 페이지 로딩 속도: 느린 로딩은 이탈률을 높인다
- API 응답 시간: 백엔드 호출의 지연은 전체 UX에 영향을 준다
- 사용자 인터랙션: 버튼 클릭, 폼 제출 등의 반응성
Sentry가 제공하는 핵심 기능
1. 실시간 에러 모니터링
// 자동 에러 캡처
Sentry.init({
dsn: process.env.SENTRY_DSN,
sendDefaultPii: true,
tracesSampleRate: 1,
debug: false,
});
// 수동 에러 캡처
try {
// 위험한 작업
} catch (error) {
Sentry.captureException(error);
}
- 장점:
- 실시간으로 에러 발생을 알림
- 에러의 컨텍스트 정보 제공 (브라우저, OS, 사용자 정보 등)
- 에러 발생 빈도와 영향도 분석
- 에러 그룹핑으로 중복 에러 정리
2. 성능 추적 (APM)
// 페이지 로딩 성능 추적
Sentry.init({
tracesSampleRate: 1, // 100% 샘플링
});
// 커스텀 성능 측정
const transaction = Sentry.startTransaction({
name: 'payment-process',
op: 'transaction',
});
// API 호출 성능 추적
const span = transaction.startChild({
op: 'http.request',
description: 'POST /api/payment',
});
- 추적 가능한 메트릭
- 페이지 로딩 시간 (FCP, LCP, FID)
- API 응답 시간
- 데이터베이스 쿼리 성능
- 사용자 인터랙션 반응 시간
3. 세션 리플레이 (Session Replay)
Sentry.init({
replaysOnErrorSampleRate: 1.0, // 에러 발생 시 100% 리플레이 수집
replaysSessionSampleRate: 0.1, // 일반 세션의 10% 수집
integrations: [
Sentry.replayIntegration({
maskAllText: true, // 텍스트 마스킹으로 개인정보 보호
blockAllMedia: true, // 미디어 차단
}),
],
});
- 세션 리플레이의 장점
- 사용자가 에러를 겪은 정확한 과정을 재현 가능
- UI/UX 문제점 파악
- 디버깅 시간 단축
- 사용자 행동 패턴 분석
4. 사용자 피드백 수집
// 사용자 피드백 위젯 추가
Sentry.init({
integrations: [
Sentry.feedbackIntegration({
colorScheme: 'light',
showBranding: false,
}),
],
});
프로젝트 실제 적용
사용자가 서비스를 이용하는 도중 에러가 발생하면 글로벌 에러 핸들러에서 에러를 캡처하고, 사용자에게 에러 메시지를 표시한다.
이후 Sentry.captureException(error)
함수를 통해 에러를 캡처하고 Sentry 콘솔에서 확인할 수 있다.
// 글로벌 에러 핸들링
export default function GlobalError({ error, reset }: { error: Error; reset: () => void }) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return (
<html>
<body>
<h2>에러가 발생했습니다.</h2>
<button onClick={reset}>다시 시도</button>
</body>
</html>
);
}
Sentry 장점
1. 실시간 모니터링
- 에러 발생 즉시 알림
- 성능 지표 실시간 추적
- 사용자 행동 패턴 분석
2. 상세한 컨텍스트
- 브라우저, OS, 디바이스 정보
- 사용자 행동 흐름
- 에러 발생 시점의 애플리케이션 상태
3. 효율적인 디버깅
스택 트레이스와 소스맵
세션 리플레이로 재현 가능
에러 그룹핑으로 중복 제거
4. 성능 최적화
- 느린 API 호출 식별
- 페이지 로딩 성능 분석
- 병목 구간 파악
Sentry 초기 설정
패키지 설치
npm install @sentry/nextjs
# 또는
pnpm add @sentry/nextjs
sentry.server.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
sendDefaultPii: true,
tracesSampleRate: 1,
debug: false,
});
instrumenation-client.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
sendDefaultPii: true,
tracesSampleRate: 1, // 0에서 1 사이의 숫자로 주어진 트랜잭션이 Sentry로 전송 될 확률을 제어
debug: false,
replaysOnErrorSampleRate: 1.0, //오류가 발생한 세션 중 어느 정도의 비율로 리플레이 데이터를 수집할지 결정
replaysSessionSampleRate: 0.1, //Sentry SDK에서 세션 리플레이 기능의 샘플링 비율을 제어
integrations: [
Sentry.replayIntegration({
// replay 를 이용할 수 있습니다. (사용자 추적)
maskAllText: true,
blockAllMedia: true,
}),
],
});
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
sentry.edge.config.ts
import * as Sentry from '@sentry/nextjs';
Sentry.init({
dsn: process.env.SENTRY_DSN,
sendDefaultPii: true,
tracesSampleRate: 1,
debug: false,
});
instrumentation.ts
import * as Sentry from '@sentry/nextjs';
export const onRequestError = (error: Error, request: Request) => {
Sentry.captureException(error);
// optional: 추가 로직
};
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
await import('./sentry.server.config');
}
if (process.env.NEXT_RUNTIME === 'edge') {
await import('./sentry.edge.config');
}
}
next.config.ts
import { withSentryConfig } from '@sentry/nextjs';
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
// ...
};
export default withSentryConfig(nextConfig, {
org: 'your-org-name',
project: 'your-project-name',
disableLogger: true,
authToken: process.env.SENTRY_AUTH_TOKEN,
silent: !process.env.CI,
});
app/global-error.tsx
'use client';
import * as Sentry from '@sentry/nextjs';
import { useEffect } from 'react';
export default function GlobalError({ error, reset }: { error: Error; reset: () => void }) {
useEffect(() => {
Sentry.captureException(error);
}, [error]);
return (
<html>
<body>
<h2>에러가 발생했습니다.</h2>
<button onClick={reset}>다시 시도</button>
</body>
</html>
);
}
.env 환경변수 설정
SENTRY_DSN = your - sentry - dsn - here;
SENTRY_AUTH_TOKEN = your - sentry - auth - token - here;
트러플슈팅
⚠ ./node_modules/.pnpm/@opentelemetry+instrumentat_d3ec4b47637246e6f49655125a61e52f/node_modules/@opentelemetry/instrumentation/build/esm/platform/node
Package require-in-the-middle can't be external
The request require-in-the-middle matches serverExternalPackages (or the default list).
The request could not be resolved by Node.js from the project directory.
Packages that should be external need to be installed in the project directory, so they can be resolved from the output files.
Try to install it into the project directory by running npm install require-in-the-middle from the project directory.
위와 같은 에러가 발생하여서 어떤 문제가 있는지 확인해보았다.
에러를 읽어보면 @opentelemetry/instrumentation
이라는 패키지가 내부적으로 require-in-the-middle이라는 모듈을 사용하려고 했으나, 이 모듈이 프로젝트에 설치되어 있지 않아 로딩에 실패했다는 의미다.
Next.js 프로젝트에 Sentry를 적용하고 성능 모니터링 옵션(tracesSampleRate, Session Replay 등)을 활성화를 했었는데 이때 발생한 에러로 추정된다.
Sentry의 성능 모니터링 기능을 활성화하면, 내부적으로 OpenTelemetry 기반의 트레이싱 기능을 사용하는데, 이때 @opentelemetry/instrumentation이 함께 동작한다. 이 패키지는 특정 Node.js 모듈의 동작을 가로채기 위해 require-in-the-middle이라는 핵심 유틸리티를 사용한다.
하지만 pnpm은 트리 기반 의존성 관리를 사용하므로, @opentelemetry/instrumentation
이 내부적으로 필요로 하는 require-in-the-middle
이 루트 경로에서 존재하지 않으면 해석이 불가능할 수 있다.
특히 Next.js가 빌드 시 특정 서버 전용 패키지를 external로 분리할 때, 해당 패키지가 프로젝트 루트에 없으면 빌드 오류 또는 경고를 발생시킨다.
그래서 에러 메세지대로 프로젝트 루트에서 pnpm add require-in-the-middle
를 설치하여 해당 문제를 해결했다.
마무리
Sentry를 통해 수집된 데이터를 바탕으로 더 정확한 의사결정을 할 수 있게 되었다. 어떤 기능에서 문제가 자주 발생하는지, 어떤 성능 이슈가 있는지 등을 객관적으로 파악할 수 있다.
이러한 설정으로 Next.js 애플리케이션에서 에러 모니터링, 성능 추적, 사용자 세션 리플레이 기능을 모두 활용할 수 있다. Sentry는 단순한 에러 추적 도구를 넘어서 애플리케이션의 전반적인 상태를 파악할 수 있는 강력한 모니터링 솔루션이다.
특히 프로덕션 환경에서 발생하는 문제들을 사전에 방지하고, 사용자 경험을 지속적으로 개선하는 데 큰 도움이 된다. Sentry 도입은 단순한 기술적 선택이 아닌, 비즈니스 성공을 위한 전략적 투자라고 할 수 있다.