Split View: 프런트엔드 모니터링·에러 트래킹 2025 — Sentry·Datadog RUM·PostHog·LogRocket·Session Replay·Source Map·AI 이상탐지 완전 가이드
프런트엔드 모니터링·에러 트래킹 2025 — Sentry·Datadog RUM·PostHog·LogRocket·Session Replay·Source Map·AI 이상탐지 완전 가이드
프롤로그 — "내 PC에선 잘 되는데?"
배포를 마치고 모두가 퇴근한 일요일 밤 10시. Slack에 "장바구니 결제가 안 돼요"라는 문의가 들어오기 시작한다. 로컬에서는 잘 되고, 스테이징에서도 멀쩡한데, 프로덕션에서만 에러가 터진다. 어떤 브라우저? 어떤 OS? 어떤 네트워크? 어떤 A/B 변형? 로그가 없다. 아무것도 모른다.
2025년의 프런트엔드 엔지니어에게 모니터링 없는 배포는 눈 감고 운전하는 것과 같다. 백엔드는 20년 전부터 APM·로그·메트릭 삼박자가 기본이었지만, 프런트엔드는 최근 5년 사이에야 실사용자 세계의 가시성이 확보되기 시작했다.
2025년의 주요 변화:
- RUM(Real User Monitoring)의 대중화 — Sentry·Datadog·Vercel Speed Insights·PostHog가 무료 또는 저렴한 요금제로 RUM을 제공하면서, 스타트업도 Google CrUX 데이터를 넘어선 세밀한 사용자 행태를 본다.
- Session Replay의 윤리 논쟁 — LogRocket·Microsoft Clarity·PostHog로 유저의 화면을 "녹화"하는 기능이 대중화되었지만, 개인정보 유출 사고가 연이어 터지며 "언제·무엇을·얼마나 녹화하느냐"의 가이드라인이 업계 표준화되었다.
- AI 기반 이상 탐지 — 단순 threshold 알림을 넘어, 에러 그룹핑·근본 원인 분석·알림 노이즈 감소에 LLM이 투입된다.
- 개인정보 보호법 강화 — GDPR(EU)·CCPA(캘리포니아)·한국 개인정보보호법이 프런트엔드 로깅의 범위와 보관 기간을 직접 규제한다.
이번 글에서는 프런트엔드 모니터링의 모든 레이어를 13개 챕터로 풀어본다.
1장 · 무엇을 모니터링할까 — 프런트엔드 관측 가능성의 4축
백엔드 관측 가능성은 보통 Logs · Metrics · Traces 삼각구도로 설명된다. 프런트엔드에는 사용자 자체가 더해져 4축이 된다.
| 축 | 질문 | 도구 |
|---|---|---|
| Errors | 무엇이 깨졌는가? | Sentry, Bugsnag, Rollbar |
| Performance (RUM) | 얼마나 느린가? | Datadog RUM, Vercel Speed Insights, SpeedCurve |
| User Behavior | 사용자가 무엇을 하는가? | PostHog, Mixpanel, Amplitude, Heap |
| Session Replay | 사용자가 어떻게 겪었는가? | LogRocket, Clarity, PostHog, FullStory |
중요한 건 "하나의 도구로 통일해야 한다"는 강박이 틀렸다는 것. Sentry(에러) + PostHog(행태+replay) + Vercel Speed Insights(RUM) 조합이 2025년 스타트업의 사실상 표준.
서로 다른 "이벤트"를 합치면 맥락이 살아난다
- 이 에러는 어떤 기능에서 나왔나? (PostHog event + Sentry breadcrumb)
- 느려진 LCP의 원인은 이 빌드인가? (RUM + Release tracking)
- 이 사용자는 무엇을 시도하다 포기했나? (Session Replay + 클릭 이벤트)
연결되지 않은 도구는 데이터의 노이즈만 늘린다. distinctId·user_id·release를 세 도구에 일관되게 주입하는 것이 가장 중요한 기초 작업.
2장 · Sentry — 에러 트래킹의 표준
2008년 창업한 Sentry는 2025년 시점 오픈소스 에러 트래킹의 de facto 표준. 스택 트레이스, 소스맵, 릴리스 추적, Performance Monitoring, Session Replay, Tracing까지 전방위로 확장되었다.
설치 (Next.js 예시)
npx @sentry/wizard@latest -i nextjs
위 위저드가 다음을 자동 생성한다:
sentry.client.config.ts,sentry.server.config.ts,sentry.edge.config.tsnext.config.js에withSentryConfig래핑- 샘플 에러 페이지
.sentryclirc
최소 설정
// sentry.client.config.ts
import * as Sentry from "@sentry/nextjs";
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NEXT_PUBLIC_ENV,
release: process.env.NEXT_PUBLIC_BUILD_ID,
tracesSampleRate: 0.1,
replaysSessionSampleRate: 0.05,
replaysOnErrorSampleRate: 1.0,
integrations: [
Sentry.replayIntegration({
maskAllText: true,
blockAllMedia: true,
}),
],
});
사용자 컨텍스트 주입
Sentry.setUser({
id: user.id,
email: user.email, // 개인정보 주의
segment: user.plan,
});
Sentry.setTag("feature_flag_checkout_v2", "enabled");
Sentry.setContext("cart", {
itemCount: cart.items.length,
total: cart.total,
});
Breadcrumb — 에러 전 사용자 행동 추적
Sentry는 클릭·라우팅·네트워크 요청을 자동으로 breadcrumb으로 기록. 에러 발생 시 "직전에 뭘 눌렀는가"가 드러난다.
Sentry.addBreadcrumb({
category: "purchase",
message: "쿠폰 적용 시도",
level: "info",
data: { couponCode: "SUMMER" },
});
배포와 연결 — Release Tracking
sentry-cli releases new $VERSION
sentry-cli releases set-commits $VERSION --auto
sentry-cli releases finalize $VERSION
커밋과 릴리스를 연결하면 "이 에러를 유발한 커밋은 이것"이라고 Sentry가 자동 추정해준다.
3장 · Source Map — 압축된 JS의 해독 키
프로덕션 번들은 minify·tree shake·transpile을 거쳐 t.default.map같은 글자만 남는다. Source Map은 이를 원본 코드로 되돌려주는 지도.
원리
빌드 도구(esbuild·Webpack·Turbopack·Vite)가 번들과 함께 .map 파일을 생성한다. 파일 끝에:
//# sourceMappingURL=main.a3f2.js.map
브라우저 DevTools는 이 힌트를 보고 .map을 내려받아 원본 위치로 변환한다.
프로덕션에 .map 업로드 vs 번들 포함
문제: .map을 그대로 CDN에 배포하면 원본 소스가 외부에 공개된다. 민감한 비즈니스 로직·API 비밀이 노출될 수 있다.
해결:
.map파일을 빌드에는 생성하지만, CDN에 올리지 않고 Sentry에만 업로드- 번들에
sourceMappingURL을 제거하거나 내부 경로로만 지정 - Sentry가 에러 접수 시 자신이 보관한
.map으로 스택 트레이스 복원
# Sentry에 source map 업로드
sentry-cli sourcemaps upload \
--release $VERSION \
--url-prefix '~/_next' \
.next/static
Next.js 15의 경우 sentry.config.js의 widenClientFileUpload: true와 hideSourceMaps: true를 조합.
디버깅 효과
- Before:
TypeError: n is undefined at t.default (main.a3f2.js:1:4829) - After:
TypeError: user is undefined at CheckoutForm.tsx:42:16
소스맵이 없으면 프로덕션 에러는 고대 상형문자다.
4장 · Datadog RUM — 엔터프라이즈 풀스택 옵저버빌리티
Datadog은 백엔드 APM에서 시작해 Frontend RUM·Logs·Synthetics·CI Visibility까지 확장된 통합 플랫폼. 대형 조직에서 백엔드 트레이스와 프런트엔드 세션을 하나의 타임라인으로 보는 능력이 강점.
초기화
import { datadogRum } from "@datadog/browser-rum";
datadogRum.init({
applicationId: process.env.NEXT_PUBLIC_DD_APP_ID,
clientToken: process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN,
site: "datadoghq.com",
service: "web-app",
env: "prod",
version: process.env.NEXT_PUBLIC_BUILD_ID,
sessionSampleRate: 100,
sessionReplaySampleRate: 20,
trackUserInteractions: true,
trackResources: true,
trackLongTasks: true,
defaultPrivacyLevel: "mask-user-input",
});
datadogRum.startSessionReplayRecording();
강점
- Trace → Session 연결: 백엔드 trace ID를 프런트엔드 요청 헤더에 자동 주입, Datadog UI에서 "이 API 호출은 이 세션에서 발생"을 즉시 탐색
- Long Task 감지:
requestIdleCallback이 blocked된 원인을 자동 수집 (INP 근본 원인 추적) - Custom Actions + Vital: 비즈니스 지표(예: "장바구니 담기 버튼 누른 후 1초 내 응답") 정의 가능
비용 주의
Datadog의 RUM 세션 가격은 업계에서 비싼 편. 대규모 트래픽 서비스는 sessionSampleRate를 10%~30%로 조절해야 한다.
5장 · PostHog — 이벤트·RUM·Replay·FlagsOps 통합
PostHog는 오픈소스 Product Analytics + Session Replay + Feature Flag + A/B Test + Experiment를 통합한 "Amplitude + LogRocket + LaunchDarkly 올인원". 2024~2025년에 스타트업 사이에서 급성장한 플랫폼.
초기화
import posthog from "posthog-js";
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: "https://app.posthog.com",
session_recording: {
maskAllInputs: true,
maskTextSelector: "[data-private]",
},
autocapture: true,
});
이벤트 추적
posthog.capture("checkout_started", {
cart_total: cart.total,
items: cart.items.length,
coupon_applied: !!coupon,
});
posthog.identify(user.id, {
email: user.email,
plan: user.plan,
});
posthog.group("company", company.id, {
name: company.name,
industry: company.industry,
});
Feature Flag 연동
if (posthog.isFeatureEnabled("checkout-v2")) {
return <CheckoutV2 />;
}
2025 업데이트
- SQL Insights: SQL로 이벤트·세션을 쿼리 (ClickHouse 기반)
- LLM Observability: OpenAI·Anthropic 호출을 자동 계측
- Data Warehouse: Snowflake·BigQuery와 양방향 동기
장점: 하나의 도구로 4-5개 카테고리 커버. 단점: Session Replay 품질은 LogRocket·FullStory보다 다소 떨어진다는 평가.
6장 · LogRocket·Clarity·FullStory — Session Replay 전문
LogRocket
- JS 에러·네트워크·Redux·콘솔·비디오를 통합 녹화
- 1분 30초 이상 세션 분석이 강점
- 월 10,000 세션 무료 → 그 이상은 급등
Microsoft Clarity
- 무료·무제한. 히트맵·Scrollmap·Rage Click·Dead Click 감지
- Microsoft가 AI·서비스 개선용 데이터로 사용한다는 데이터 제공 조건 동의
- 개인 블로그·중소 서비스에 압도적 가성비
FullStory
- 엔터프라이즈 급. 프라이버시 컨트롤과 GDPR 대응이 업계 최고 수준
- 가격도 엔터프라이즈 급
Session Replay의 가치
- 재현 불가 버그 해결: "왜 이 모달이 안 열려요?" → 실제 화면으로 확인
- UX 인사이트: 사용자가 어디에서 Rage Click하고, 어디서 이탈하는지
- Funnel 분석 보완: 숫자가 말하지 않는 "왜 포기했는지"
7장 · Session Replay의 윤리 — Privacy by Design
2024년의 교훈
2024년 여러 대형 서비스가 Session Replay에 비밀번호·신용카드 번호·주민번호가 녹화된 상태로 저장된 것이 발견되어 GDPR 위반으로 과징금을 맞았다.
방어선 3층
1층: Mask 설정 기본값을 "안전한 쪽"으로
// LogRocket
LogRocket.init("your-app-id", {
dom: {
textSanitizer: true, // 텍스트 기본 마스킹
inputSanitizer: true, // 입력 기본 마스킹
},
});
// Sentry Replay
Sentry.replayIntegration({
maskAllText: true, // 모든 텍스트 마스킹
maskAllInputs: true, // 모든 입력 마스킹
blockAllMedia: true, // 이미지·비디오 차단
});
2층: 개인정보 필드에 data-private 또는 data-sensitive 마크업
<input type="password" data-private />
<div data-private>{creditCard}</div>
<span class="ph-no-capture">주민등록번호</span>
3층: 전송 전 클라이언트 측 sanitize
posthog.capture("form_submit", {
email: user.email.replace(/(.{2}).+(@.+)/, "$1***$2"), // 이메일 부분 마스킹
// 전화번호·주소는 아예 전송 안 함
});
법적 요구 (GDPR Art. 6, 7)
- 명시적 동의: 쿠키 배너에서 "세션 녹화"를 별도 항목으로
- 목적 제한: UX 개선 목적 이외로 활용 금지
- 보관 기간: 30-90일 권장
- DSAR (Data Subject Access Request): 사용자가 자신의 녹화 삭제 요청 가능해야 함
8장 · 프런트엔드에서 발생하는 에러의 유형
1. JavaScript Runtime Errors
TypeError: Cannot read property 'x' of undefinedReferenceError: foo is not defined- 대응: TypeScript + strict null check + 가드 클로저
2. Unhandled Promise Rejections
- 비동기 함수에서
.catch누락 - 대응: 글로벌 핸들러
window.addEventListener("unhandledrejection", (event) => {
Sentry.captureException(event.reason);
});
3. Chunk Load Error — 배포 시 대표 버그
ChunkLoadError: Loading chunk 42 failed.
원인: 사용자가 페이지를 열어둔 사이 새 배포가 나가 이전 해시의 청크가 CDN에서 사라짐.
해결:
// Next.js — 자동 재시도
// next.config.js
module.exports = {
experimental: { optimizePackageImports: [...] },
};
// 커스텀 재시도 + 강제 새로고침
window.addEventListener("error", (e) => {
if (e.message.includes("ChunkLoadError") || e.message.includes("Loading chunk")) {
window.location.reload();
}
});
또는 Long-term caching + hash invalidation을 잘 관리한 CDN 전략.
4. Hydration Mismatch
Text content does not match server-rendered HTML.
원인: SSR과 Client에서 다른 값 렌더 (Date, Math.random, localStorage 등).
해결:
// Bad
<div>{new Date().toLocaleString()}</div>
// Good — Client에서만
const [now, setNow] = useState<string>("");
useEffect(() => {
setNow(new Date().toLocaleString());
}, []);
return <div suppressHydrationWarning>{now}</div>;
5. CORS·CSP 에러
- Mixed content, strict CSP로 인라인 스크립트 차단
- 대응: CSP nonce, Report-Only 모드로 점진 도입
6. 3rd-party Script Errors
- "Script error." (스택 없음)
- 원인: Cross-origin 스크립트의 보안 제약
- 대응:
<script crossorigin="anonymous">+ CORS 헤더 +Sentry.ignoreErrors
9장 · Core Web Vitals와 연결 — RUM 집계
web-vitals 라이브러리
import { onCLS, onINP, onLCP, onFCP, onTTFB } from "web-vitals";
function sendToAnalytics(metric) {
navigator.sendBeacon(
"/api/vitals",
JSON.stringify({
name: metric.name,
value: metric.value,
id: metric.id,
rating: metric.rating,
delta: metric.delta,
navigationType: metric.navigationType,
})
);
}
onCLS(sendToAnalytics);
onINP(sendToAnalytics);
onLCP(sendToAnalytics);
Vercel Speed Insights
Next.js + Vercel 조합이면 <SpeedInsights /> 한 줄 추가로 자동 수집. CrUX 기반 RUM을 무료 한도 내에서 즉시 활용.
Custom Dashboard로 집계
- Percentile 집계: 평균보다는 P75·P90·P95가 의미 있다
- Segmentation: 기기별(모바일·데스크탑)·라우트별·버전별·지역별로 나눠 본다
- Regression Detection: 배포 전후 비교로 성능 회귀 자동 감지
10장 · 알림·Alert Fatigue — 노이즈 줄이는 설계
Alert Fatigue의 함정
- 하루 50건의 Slack 알림이 들어오면 → 아무도 안 본다
- 중요한 알림이 사소한 알림에 묻힌다
- 팀의 번아웃과 이직으로 이어짐
SLO 기반 알림 (Google SRE 방식)
"에러가 1개 발생했다"는 노이즈. "에러 예산을 이 속도로 소진하면 월말 SLO를 깬다"가 의미 있는 알림.
slo:
name: "checkout-success-rate"
target: 99.9% # 월 SLO
window: 30d
alert:
- burn_rate: 14.4 # 2% 에러 예산을 1시간 내 소진
duration: 5m
severity: critical
- burn_rate: 6 # 5% 예산을 6시간 내 소진
duration: 30m
severity: warning
알림 그룹핑
- Sentry의 자동 Issue Grouping: 동일 스택 트레이스 패턴을 하나의 Issue로
- 변화 감지 알림: "새로운 에러 유형이 등장했을 때만 알림"
- 용량 알림: "에러 발생량이 P95 대비 3배 이상 증가"
Alert 우선순위
- Critical — 즉시 대응 필요 (페이지 다운, 결제 실패 급증)
- Warning — 업무 시간 내 대응 (일부 기능 이슈, 성능 저하)
- Info — 알림 없이 대시보드에만 (트렌드 관찰)
11장 · AI 기반 이상 탐지와 근본 원인 분석
전통적 이상 탐지의 한계
- Threshold: "에러가 100건 넘으면 알림" → 계절성·트렌드 못 봄
- Static baseline: 매주 월요일 트래픽 스파이크를 이상으로 감지
2025년의 AI 기반 이상 탐지
Datadog Watchdog, Sentry Insights, PostHog AI, Dynatrace Davis AI 모두 2024~2025년에 LLM·시계열 모델 기반 기능을 출시.
주요 기능:
- 자동 이상치 감지: 시계열의 변곡점을 찾아 "지난주 같은 시간대 대비 3.5σ 초과" 식으로 알림
- 근본 원인 추정(RCA): 에러 스파이크와 동시에 발생한 변경사항(배포·피처 플래그·외부 의존성)을 자동 연결
- 에러 요약: LLM이 스택 트레이스와 로그를 읽어 "어떤 기능의 어떤 유저 흐름에서 실패했다"를 자연어로 요약
- 우선순위 랭킹: 비즈니스 영향도(트래픽 × 결제 페이지) 기반으로 자동 랭킹
주의 — AI가 틀릴 수 있다
- Correlation ≠ Causation: "이 배포 시점에 에러가 증가했다"가 반드시 "이 배포가 원인"은 아니다
- 최종 판단은 사람이 내려야 한다. AI는 탐색 범위를 좁히는 조수.
12장 · 사용자 피드백 루프 — 숫자와 목소리를 잇기
정량(quantitative)과 정성(qualitative)의 결합
숫자(Sentry, RUM, Analytics)만 보면 **"왜"**가 빠진다. 피드백(NPS, 설문, 지원 티켓)만 보면 **"얼마나"**가 빠진다.
피드백 도구
- NPS·CSAT: Delighted, Wootric, Typeform
- 인앱 피드백: Canny, UserVoice, Feedback Fish
- 세션 녹화 + 코멘트: LogRocket·PostHog에서 사용자가 "이 화면 녹화 공유" 가능
- Copy linking: 에러 발생 시 "이 문제를 신고하기" 버튼 — Sentry에 User Feedback으로 자동 전송
User Feedback in Sentry
Sentry.showReportDialog({
user: {
email: user.email,
name: user.name,
},
title: "문제가 발생했습니다",
subtitle: "아래 양식을 작성해 주시면 빠르게 해결하겠습니다",
});
사용자 설명이 스택 트레이스와 묶여 이슈에 첨부된다.
13장 · 체크리스트·안티패턴·다음 글 예고
프런트엔드 모니터링 체크리스트 (14개)
- Sentry(또는 Bugsnag/Rollbar)로 에러 수집
- Source Map을 Sentry에 업로드, 프로덕션에는 공개하지 않음
- Release tracking — 커밋·빌드·에러 연결
- User context 주입 (id·plan·기능 플래그)
- RUM(Vercel Speed Insights·Datadog·PostHog) 배포
- Core Web Vitals 수집 + 배포 전후 비교
- Session Replay — 기본 mask +
data-private전략 - Chunk Load Error 자동 재시도 로직
- Hydration Mismatch 모니터링 및 재현 테스트
- unhandledrejection 글로벌 핸들러
- SLO 기반 알림 — Burn rate alerting
- Alert 우선순위 3단계 분리
- GDPR·개인정보보호법 대응 (동의·보관 기간·DSAR)
- Dashboard — 기기·라우트·버전별 세그먼트 분석
모니터링 안티패턴 TOP 10
console.error만으로 "로그 완료" — 서버로 안 가면 없는 것- Sentry에 PII 평문 전송 — 이메일·전화번호 마스킹 없이 로깅
- Source Map을 CDN에 공개 — 원본 노출 + 영업 비밀 유출
- 모든 에러를 Critical 알림 — Alert fatigue
- Dev·Staging·Prod 이벤트 섞임 — environment 태그 누락
- Sample rate 100% — 비용 폭발
data-private없이 Session Replay — 법적 리스크- Release 추적 없음 — "이 에러 언제부터?" 대답 불가
- Hydration Mismatch 방치 — 경고만 수천 건
- 사용자 피드백과 에러를 분리 보관 — 정량·정성 단절
다음 글 예고 — Season 6 Ep 9: "프런트엔드 보안"
모니터링·성능·a11y·i18n을 다 갖췄다면 다음은 보안. Ep 9는 프런트엔드 보안.
- XSS·CSRF·Clickjacking 2025 최신 공격 양상
- CSP(Content Security Policy)와 nonce·hash·strict-dynamic
- Trusted Types와 DOM-based XSS 방지
- 쿠키·JWT·세션 관리 (SameSite, HttpOnly, Secure)
- OAuth·OIDC·PKCE·Passkey 실전
- Supply Chain Attack (npm 패키지 위험)
- SRI(Subresource Integrity)·CSP Report-Only
- Web Bot Auth·CAPTCHA 대안
- 한국 전자정부법·ISMS-P·PCI DSS·SOC 2
- CVE 대응 파이프라인
"보안은 나중에 붙이는 게 아니다. 처음부터 스며들어 있어야 한다."
다음 글에서 만나자.
"모니터링은 배포 이후의 또 다른 제품이다. 에러·성능·행태·감정을 모두 계측하되, 사용자의 프라이버시를 침범하지 않는 설계가 2025년의 품질이다."
Frontend Monitoring & Error Tracking 2025 — Sentry, Datadog RUM, PostHog, LogRocket, Session Replay, Source Maps, AI Anomaly Detection (S6 E8)
Prologue — "works on my machine"
Sunday 10pm after a deploy. Slack pings: "checkout is broken." Local is fine, staging is fine, only production fails. Which browser? Which OS? Which A/B variant? No logs. No idea.
In 2025, deploying without monitoring is driving blindfolded. Backends have had APM + logs + metrics for 20 years; frontends only got true RUM in the last five.
Four 2025 shifts:
- RUM went mass-market — Sentry, Datadog, Vercel Speed Insights, PostHog offer affordable RUM. Even startups see more detail than CrUX gives.
- Session Replay ethics crystallized — 2024 password/credit-card-in-replay scandals forced industry guidelines for when, what, how much to record.
- AI-powered anomaly detection — beyond threshold alerts: LLMs do grouping, root-cause, alert-noise reduction.
- Privacy regulation bite — GDPR, CCPA, Korean PIPA directly regulate frontend logging scope and retention.
This post maps every layer.
1. What to monitor — four axes
Backend observability is Logs + Metrics + Traces. Frontend adds users → four axes.
| Axis | Question | Tool |
|---|---|---|
| Errors | What broke? | Sentry, Bugsnag, Rollbar |
| Performance (RUM) | How slow? | Datadog RUM, Vercel Speed Insights, SpeedCurve |
| User Behavior | What are users doing? | PostHog, Mixpanel, Amplitude, Heap |
| Session Replay | How did they experience it? | LogRocket, Clarity, PostHog, FullStory |
No single tool wins. 2025 startup default: Sentry (errors) + PostHog (behavior + replay) + Vercel Speed Insights (RUM).
Connect them via consistent distinctId, user_id, release across all three — otherwise the noise wins.
2. Sentry — the de facto error tracker
Install for Next.js:
npx @sentry/wizard@latest -i nextjs
Minimal init:
import * as Sentry from '@sentry/nextjs'
Sentry.init({
dsn: process.env.NEXT_PUBLIC_SENTRY_DSN,
environment: process.env.NEXT_PUBLIC_ENV,
release: process.env.NEXT_PUBLIC_BUILD_ID,
tracesSampleRate: 0.1,
replaysSessionSampleRate: 0.05,
replaysOnErrorSampleRate: 1.0,
integrations: [Sentry.replayIntegration({ maskAllText: true, blockAllMedia: true })],
})
User + context + breadcrumbs:
Sentry.setUser({ id: user.id, segment: user.plan })
Sentry.setTag('feature_flag_checkout_v2', 'enabled')
Sentry.addBreadcrumb({ category: 'purchase', message: 'coupon applied', level: 'info' })
Release tracking — link commits to errors:
sentry-cli releases new $VERSION
sentry-cli releases set-commits $VERSION --auto
sentry-cli releases finalize $VERSION
3. Source Maps — the decoder
Production bundles are mangled. Source maps (.map files) translate minified frames back to original lines.
Don't publish .map to CDN
Your source code becomes public. Instead:
- Upload
.mapto Sentry only. - Remove or obscure
sourceMappingURLin bundles. - Sentry resolves stacks server-side.
sentry-cli sourcemaps upload \
--release $VERSION \
--url-prefix '~/_next' \
.next/static
Next.js: withSentryConfig({ widenClientFileUpload: true, hideSourceMaps: true }).
Before: TypeError: n is undefined at t.default (main.a3f2.js:1:4829)
After: TypeError: user is undefined at CheckoutForm.tsx:42:16
4. Datadog RUM — enterprise full-stack observability
import { datadogRum } from '@datadog/browser-rum'
datadogRum.init({
applicationId: process.env.NEXT_PUBLIC_DD_APP_ID,
clientToken: process.env.NEXT_PUBLIC_DD_CLIENT_TOKEN,
site: 'datadoghq.com',
service: 'web-app',
env: 'prod',
version: process.env.NEXT_PUBLIC_BUILD_ID,
sessionSampleRate: 100,
sessionReplaySampleRate: 20,
trackUserInteractions: true,
trackResources: true,
trackLongTasks: true,
defaultPrivacyLevel: 'mask-user-input',
})
datadogRum.startSessionReplayRecording()
Strength: trace → session link. Backend trace IDs auto-injected as request headers, so one timeline shows "API X served this session."
Caveat: Datadog RUM pricing is enterprise. Drop sessionSampleRate to 10–30% at scale.
5. PostHog — analytics + replay + flags + experiments
Open-source Amplitude + LogRocket + LaunchDarkly.
import posthog from 'posthog-js'
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
api_host: 'https://app.posthog.com',
session_recording: { maskAllInputs: true, maskTextSelector: '[data-private]' },
autocapture: true,
})
posthog.capture('checkout_started', { cart_total: cart.total, items: cart.items.length })
posthog.identify(user.id, { email: user.email, plan: user.plan })
if (posthog.isFeatureEnabled('checkout-v2')) return <CheckoutV2 />
2025 additions: SQL Insights (ClickHouse), LLM Observability (auto OpenAI/Anthropic instrumentation), Data Warehouse sync.
6. Session replay tools
- LogRocket — JS + network + Redux + console, premium. 10k sessions free, steep after.
- Microsoft Clarity — free unlimited, heatmaps, rage/dead clicks. You share data with Microsoft.
- FullStory — enterprise, best privacy controls.
Session replay value: reproduce impossible bugs, UX insight (rage clicks, abandons), funnel completion with the "why."
7. Session replay ethics — privacy by design
2024 scandals: passwords and credit-card numbers captured, GDPR fines.
Three defensive layers
1. Safe defaults
Sentry.replayIntegration({ maskAllText: true, maskAllInputs: true, blockAllMedia: true })
2. Markup-level controls
<input type="password" data-private />
<div data-private>{creditCard}</div>
<span class="ph-no-capture">SSN</span>
3. Client-side sanitize before send
posthog.capture('form_submit', {
email: user.email.replace(/(.{2}).+(@.+)/, '$1***$2'),
})
GDPR Art. 6/7
- Explicit consent — "session recording" as separate item in cookie banner.
- Purpose limitation — UX only.
- Retention — 30–90 days.
- DSAR — users can delete their recordings.
8. Frontend error types
JS runtime
TypeError: Cannot read property 'x' of undefined. Fix: TS strict + null guards.
Unhandled promise rejection
window.addEventListener('unhandledrejection', (e) => Sentry.captureException(e.reason))
ChunkLoadError — the deploy classic
User had tab open during deploy; old chunk gone from CDN.
window.addEventListener('error', (e) => {
if (e.message.includes('ChunkLoadError') || e.message.includes('Loading chunk')) {
window.location.reload()
}
})
Or long-term cache with hash invalidation.
Hydration mismatch
SSR ≠ client render (Date, Math.random, localStorage).
const [now, setNow] = useState('')
useEffect(() => { setNow(new Date().toLocaleString()) }, [])
return <div suppressHydrationWarning>{now}</div>
CORS / CSP errors
Start with CSP Report-Only → tighten gradually. Use nonces.
3rd-party script errors
"Script error." with no stack = cross-origin block. Fix: <script crossorigin="anonymous"> + CORS headers + Sentry.ignoreErrors.
9. Core Web Vitals — the RUM loop
web-vitals library
import { onCLS, onINP, onLCP, onFCP, onTTFB } from 'web-vitals'
function send(metric) {
navigator.sendBeacon('/api/vitals', JSON.stringify({
name: metric.name, value: metric.value, id: metric.id,
rating: metric.rating, delta: metric.delta, navigationType: metric.navigationType,
}))
}
onCLS(send); onINP(send); onLCP(send)
Vercel Speed Insights
On Vercel: one line, <SpeedInsights />. CrUX-style RUM, free tier.
Dashboard discipline
- Percentiles — p75/p90/p95, not average.
- Segments — device, route, version, region.
- Regression detection — pre/post-deploy diff.
10. Alert fatigue — the real enemy
50 Slack alerts/day → everyone mutes → the important ones die in the noise.
SLO-based alerting (Google SRE)
Alert on "burn rate," not "an error happened":
slo:
name: checkout-success-rate
target: 99.9%
window: 30d
alert:
- burn_rate: 14.4 # 2% budget in 1 hour
duration: 5m
severity: critical
- burn_rate: 6 # 5% budget in 6 hours
duration: 30m
severity: warning
Grouping
Sentry auto-groups by stack pattern. Alert on new issue types or 3× traffic spikes.
Priority tiers
- Critical — page down, checkout broken. Paging.
- Warning — partial issue, perf regression. Business hours.
- Info — trend watching, dashboard only.
11. AI anomaly detection + root cause
Static thresholds miss seasonality. 2024–2025 Datadog Watchdog, Sentry Insights, PostHog AI, Dynatrace Davis ship LLM/time-series anomaly features.
What they do:
- Detect change-points (3σ vs same time last week).
- Correlate error spikes with deploys, flags, external deps (RCA suggestions).
- LLM summarizes stacks + logs in plain language: "this function of this flow failed."
- Business-impact ranking (traffic × checkout page).
Caveat: correlation ≠ causation. AI narrows the search; humans decide.
12. User feedback loops
Numbers answer "how many," feedback answers "why."
- NPS/CSAT — Delighted, Wootric, Typeform.
- In-app feedback — Canny, UserVoice, Feedback Fish.
- Session + comment — LogRocket/PostHog "share recording."
- Sentry User Feedback — prompt users on error:
Sentry.showReportDialog({ user: { email: user.email, name: user.name } })
13. Checklist + anti-patterns
14-item checklist
- Sentry (or equivalent) collecting errors.
- Source maps uploaded only to Sentry, not public.
- Release tracking — commit → build → error chain.
- User context injected.
- RUM deployed (Vercel Speed Insights / Datadog / PostHog).
- CWV collected + pre/post-deploy diff.
- Session replay with mask defaults +
data-private. - ChunkLoadError auto-retry.
- Hydration mismatch monitored.
unhandledrejectionglobal handler.- SLO-based burn-rate alerting.
- 3-tier alert priority.
- GDPR/PIPA compliance (consent, retention, DSAR).
- Dashboard segmented by device/route/version.
Top 10 monitoring anti-patterns
console.errorwithout server-side collection.- Sending PII to Sentry un-masked.
- Publishing
.mapfiles to CDN. - Every error as critical.
- Dev/staging/prod mixed (no environment tag).
- 100% sample rate (cost explosion).
- Session replay without
data-private. - No release tracking ("when did this start?" → silence).
- Ignoring hydration mismatches.
- Quant data and feedback stored separately.
Next episode
Season 6 Episode 9: Frontend Security 2025 — XSS, CSRF, CSP v3, Trusted Types, JWT, OAuth + PKCE, Passkey, supply chain, SRI.
"Monitoring is a second product shipping after deploy. Measure errors, performance, behavior, emotion — but never at the cost of users' privacy."
— End of Frontend Monitoring & Error Tracking.