RUM(Real User Monitoring)

[!tldr] 한줄 요약 RUM은 브라우저/모바일에 SDK를 삽입하여 실제 사용자의 페이지 로딩, 에러, 상호작용을 수집하고, allowedTracingUrls 설정으로 백엔드 APM 트레이스와 연결하여 프론트엔드→백엔드 end-to-end 옵저버빌리티를 제공한다.

핵심 내용

RUM이란

Real User Monitoring — 실제 사용자의 브라우저/모바일에서 발생하는 경험을 수집·분석하는 프론트엔드 모니터링이다. 신서틱 모니터링(Synthetic Monitoring)이 "가상 사용자로 능동적 테스트"라면, RUM은 "실제 사용자의 수동적 관측"이다.

RUM SDK를 앱에 삽입하면 자동으로 수집이 시작된다:

이벤트 계층 구조

RUM이 수집하는 데이터는 계층 구조로 구성된다:

graph TD
    S[Session<br/>사용자 방문 단위] --> V1[View<br/>페이지 A]
    S --> V2[View<br/>페이지 B]
    V1 --> A1[Action<br/>버튼 클릭]
    V1 --> E1[Error<br/>JS 에러]
    V1 --> R1[Resource<br/>API 호출]
    V1 --> L1[Long Task<br/>50ms+ 블로킹]
    V2 --> A2[Action<br/>폼 제출]
    V2 --> R2[Resource<br/>이미지 로딩]
이벤트설명예시
Session사용자 방문 단위. 비활성 15분 만료, 최대 4시간한 사용자의 사이트 방문
View페이지(SPA의 경우 라우트 변경) 단위/checkout, /products/123
Action사용자 상호작용클릭, 탭, 스크롤
ErrorJS 에러, 네트워크 에러TypeError: Cannot read property
Resource네트워크 요청XHR, fetch, 이미지, CSS, JS 파일
Long Task50ms 이상 메인 스레드 블로킹무거운 JS 연산

Core Web Vitals 자동 수집

RUM은 Google의 Core Web Vitals를 자동으로 수집하여 p75 기준으로 대시보드에 표시한다:

지표설명좋음나쁨
LCP (Largest Contentful Paint)가장 큰 콘텐츠 렌더링 시간≤ 2.5s> 4.0s
INP (Interaction to Next Paint)사용자 상호작용 후 화면 반응 시간≤ 200ms> 500ms
CLS (Cumulative Layout Shift)레이아웃 이동 누적 점수≤ 0.1> 0.25

각 지표마다 해당하는 DOM 엘리먼트의 CSS Selector를 함께 리포트하여, "어떤 요소가 문제인지"까지 알 수 있다.

Session Replay

사용자 세션을 영상처럼 재생하는 기능이다. DOM 스냅샷을 찍고, 이후 발생하는 DOM 변경/마우스 이동/클릭/입력 이벤트를 타임스탬프와 함께 기록한다.

SDK 초기화

import { datadogRum } from '@datadog/browser-rum';

datadogRum.init({
  applicationId: '<APPLICATION_ID>',
  clientToken: '<CLIENT_TOKEN>',
  site: 'datadoghq.com',
  service: 'my-web-app',
  env: 'production',
  version: '1.0.0',
  // 세션 수집 비율 (비용 제어)
  sessionSampleRate: 100,
  // Session Replay 비율 (sessionSampleRate의 %)
  sessionReplaySampleRate: 20,
  // 이벤트 수집 옵션
  trackUserInteractions: true,
  trackResources: true,
  trackLongTasks: true,
  // APM 연결 (아래 섹션 참조)
  allowedTracingUrls: ["https://api.example.com"],
});

[!tip] 샘플링 비율 계산 sessionSampleRate: 60, sessionReplaySampleRate: 50이면:

  • 40% 세션 버림
  • 30% Browser RUM만 수집
  • 30% Browser RUM + Session Replay 수집

RUM ↔ APM 상관관계 (End-to-End 연결)

RUM의 가장 강력한 기능은 프론트엔드 요청을 백엔드 트레이스와 연결하는 것이다. 이전에 배운 로그-트레이스 상관관계가 "로그 ↔ 트레이스"를 연결했다면, 이것은 "브라우저 ↔ 백엔드 트레이스"를 연결한다.

동작 원리

sequenceDiagram
    participant Browser as 브라우저 (RUM SDK)
    participant Backend as 백엔드 (dd-trace)
    participant DD as Datadog 백엔드

    Browser->>Browser: fetch("/api/checkout") 호출
    Browser->>Backend: HTTP 요청 + traceparent 헤더 자동 주입
    Note right of Browser: traceparent: 00-{traceId}-{spanId}-01
    Backend->>Backend: 헤더에서 traceId 추출, 같은 traceId로 Span 생성
    Browser->>DD: RUM Resource 이벤트 (traceId 포함)
    Backend->>DD: APM Trace (같은 traceId)
    DD->>DD: traceId로 RUM Resource ↔ APM Trace 매칭

RUM SDK가 allowedTracingUrls에 지정된 URL로 요청할 때, HTTP 헤더에 trace context를 자동 주입한다. 백엔드의 dd-trace가 이 헤더를 읽어 같은 traceId로 Span을 생성하므로, Datadog 백엔드에서 자동으로 매칭된다.

allowedTracingUrls 설정

datadogRum.init({
  // ...
  allowedTracingUrls: [
    "https://api.example.com",           // 문자열 매치
    /https:\/\/.*\.example\.com/,         // 정규식
    (url) => url.startsWith("https://")  // 함수
  ],
});

[!warning] 자사 백엔드만 지정할 것 외부 서비스(Google Analytics, CDN 등)에 trace 헤더를 보내면 CORS 에러가 나거나 불필요한 트레이스가 생긴다. 자사 백엔드 URL만 지정해야 한다.

전파 헤더 종류 (propagatorTypes)

타입헤더용도
Datadogx-datadog-trace-id, x-datadog-parent-iddd-trace 기본
W3C Trace Contexttraceparent (00-{traceId}-{parentId}-{flags})OTel / 표준
B3X-B3-TraceId, X-B3-SpanIdZipkin 호환

기본값은 Datadog + W3C 둘 다 전송한다. 백엔드가 OpenTelemetry를 쓴다면 W3C만으로도 충분하다.

연결된 후 Datadog UI에서

프론트엔드 → 백엔드:

  1. RUM Explorer에서 느린 페이지/에러 세션 선택
  2. View 상세 → "Resources" 탭 → API 호출 클릭
  3. "View Trace" → APM Flame Graph로 이동
  4. 백엔드의 어떤 서비스/DB 쿼리가 느렸는지 확인

백엔드 → 프론트엔드:

  1. APM에서 에러 트레이스 발견
  2. 트레이스에 태깅된 session_id, view_id로 RUM 세션 확인
  3. Session Replay로 사용자가 뭘 했는지 재생

로그-트레이스-RUM 전체 연결 그림

graph TB
    subgraph Frontend
        RUM[RUM SDK<br/>session_id, view_id]
    end
    subgraph Backend
        APM[dd-trace<br/>trace_id, span_id]
    end
    subgraph Logs
        LOG[Log Management<br/>dd.trace_id]
    end

    RUM -->|traceparent 헤더| APM
    APM -->|dd.trace_id 주입| LOG
    RUM -.->|같은 trace_id| LOG

    style RUM fill:#7B68EE
    style APM fill:#FF6347
    style LOG fill:#3CB371

세 영역이 모두 같은 trace_id로 연결되어, Datadog UI에서 RUM ↔ APM ↔ 로그를 자유롭게 오갈 수 있다. 이것이 Datadog이 말하는 "end-to-end 옵저버빌리티"의 핵심이다.

과금

1,000 세션 단위로 과금된다. sessionSampleRatesessionReplaySampleRate로 비용을 제어한다. Session Replay가 포함되면 단가가 더 높다.

플랜포함 내용
Browser RUMRUM 이벤트 수집, Error Tracking
Browser RUM & Session Replay위 + Session Replay 녹화

예시

import { datadogRum } from '@datadog/browser-rum';

datadogRum.init({
  applicationId: '<APPLICATION_ID>',
  clientToken: '<CLIENT_TOKEN>',
  site: 'datadoghq.com',
  service: 'checkout-web',
  env: 'production',
  version: '2.1.0',
  sessionSampleRate: 100,
  sessionReplaySampleRate: 20,
  trackUserInteractions: true,
  trackResources: true,
  trackLongTasks: true,
  allowedTracingUrls: ["https://api.myshop.com"],
});

// 사용자 정보 추가 (세션에 태깅)
datadogRum.setUser({
  id: 'user-123',
  name: 'John Doe',
  email: 'john@example.com',
  plan: 'premium',
});

// 커스텀 액션 추적
datadogRum.addAction('checkout_completed', {
  cart_total: 150000,
  item_count: 3,
});

// 커스텀 에러 추적
try {
  processPayment();
} catch (error) {
  datadogRum.addError(error, {
    source: 'payment',
    order_id: 'ORD-456',
  });
}

[!example] 장애 대응 시 RUM 활용 흐름

  1. 모니터 알림: "checkout 페이지 에러율 급증"
  2. RUM Explorer에서 service:checkout-web status:error 필터링
  3. Error Tracking에서 에러 그룹 확인 → 스택 트레이스 분석
  4. 해당 세션의 Session Replay로 사용자 행동 재현
  5. Resource 탭에서 실패한 API 클릭 → "View Trace"로 APM 이동
  6. Flame Graph에서 백엔드 원인 확인 (예: DB 타임아웃)
  7. 로그-트레이스 상관관계로 해당 시점 로그 확인

사용자 행동 → 프론트 에러 → 백엔드 원인 → 로그 전체 흐름 파악

참고 자료

관련 노트