✍️ 필사 모드: Frontend Monitoring & Error Tracking 2025 — Sentry, Datadog RUM, PostHog, LogRocket, Session Replay, Source Maps, AI Anomaly Detection (S6 E8)
EnglishPrologue — "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.
현재 단락 (1/176)
Sunday 10pm after a deploy. Slack pings: "checkout is broken." Local is fine, staging is fine, only ...