Data · Frontend

Datadog RUM 도입기: 비용을 90% 줄이기까지

Datadog RUM을 도입하고 비용을 최대로 줄인 이야기

CCheolgyun Lim (철균)
·
# Datadog# 비용절감# RUM
Datadog RUM 도입기: 비용을 90% 줄이기까지
date
slug
author
status
tags(최대 3개)
summary
type
thumbnail
category
updatedAt
사용자가 결제 페이지에서 갑자기 이탈했다고 해봅시다. 그 직전에 어떤 화면을 봤고, 어떤 버튼을 눌렀고, 어떤 에러를 만났을까요? 단순한 에러 로그만으로는 답이 안 나오는 질문입니다. 이런 질문에 답하려면 사용자의 여정 전체를 한 타임라인으로 따라갈 수 있어야 합니다.
Datadog RUM(Real User Monitoring)실제 사용자의 브라우저에서 성능·에러·행동 데이터를 수집하는 모니터링 서비스입니다.
아임웹은 이미 Datadog 모니터링과 APM을 안정적으로 운영하고 있습니다. 프론트엔드 챕터는 사용자가 실제로 느끼는 UX(성능·오류·행동 흐름)를 세션 단위로 관측하고, 문제 재현과 원인 추적 시간을 줄이기 위해 Datadog RUM을 도입하기로 했습니다. 그 전에는 주문·결제 같은 주요 서비스에 Sentry를 일부 도입해 운용하고 있었습니다.
notion image
항목
Sentry
Datadog RUM
관점
에러 중심
세션 중심
핵심 질문
무엇이 터졌나
누가 어떤 여정에서 터졌나
수집 데이터
에러, 스팬(트랜잭션), 세션 리플레이
세션, 뷰, 액션, 리소스, 에러, Long Task
가격 구조
월 정액 기반, 초과분은 이벤트당 과금
월 정액 없음, 세션 수 기반 사용량 과금
Datadog RUM의 주요 특징은 다음과 같습니다.
  • 세션 단위의 풀스택 관측성: 에러만 추적하는 게 아니라 사용자 여정 전체(뷰·액션·리소스·Long Task·Web Vitals)를 타임라인으로 기록합니다.
  • Datadog 생태계와의 네이티브 연결: RUM 세션이 백엔드 APM trace·로그·인프라 metric과 자동 연결돼, 클라이언트 에러부터 DB 쿼리까지 한 대시보드에서 추적할 수 있습니다.
  • 자동 수집되는 웹 성능 지표: LCP·FCP·CLS 같은 Core Web Vitals를 별도 설정 없이 자동 수집합니다.

일생일대의 기회

Datadog RUM 소개 세션을 통해 한 달간 POC를 진행할 기회가 생겼습니다. POC 기간의 비용을 무효화해 주는 일생일대의 기회를 제대로 활용하려고, 일단 모든 유저의 세션을 100% 수집해 보기로 했습니다.

시작부터 순조롭지 않다

Datadog 앱 콘솔 좌측에서 Digital Experience → Real User Monitoring으로 들어가야 합니다. APM처럼 사이드바에 바로 보이지 않아 몇 번 헤맸습니다. 페이지에 진입했다면 JS 타입 애플리케이션을 생성하고, 나오는 SDK 코드블록을 복사해 적용하면 됩니다.
현 시점 Datadog RUM의 모든 설정은 SDK로만 제어할 수 있습니다. 콘솔에서 샘플 레이트나 프라이버시 처리 방식을 조정할 수는 있지만, 변경 결과가 코드 스니펫으로만 제공되어 이 값을 서비스 코드에 직접 반영해야 적용됩니다.
대부분은 문제가 없지만, 최신 설정값이 웨이백 머신으로 아카이브된 사이트까지는 도달하지 않는 치명적 문제를 발견했습니다. 그래서 POC가 끝나고 정식 도입할 때는 애플리케이션을 새로 생성해 시작하길 권합니다.

이걸 언제 다 하지

프론트엔드 챕터는 마이크로 프론트엔드 아키텍처로 60여 개의 웹 애플리케이션을 운용합니다.
각 앱마다 init 코드를 주입하면 식별은 쉽지만 관리가 치명적입니다. 설정 하나 바꾸는 작업을 개별 앱에 모두 적용해야 한다면 벌써부터 피로감이 몰려옵니다. 반대로 마이크로 애플리케이션의 호스트에서 init 코드를 주입하면 유지보수성은 크게 좋아지지만, 어디서 발생한 이벤트인지 알아차리기 어렵습니다.
결국 host에서 단 한 번만 init하고, 커스텀 속성으로 각 앱을 식별하는 하이브리드 전략을 택했습니다.

결과는 예상 밖으로

미리 파악했던 마이크로 애플리케이션 문제뿐 아니라, 예상치 못한 부분도 발견했습니다.

봇이 상상 이상으로 많았다

아임웹으로 운영되는 브랜드의 공개 웹사이트에는 관심 있는 소비자도 많이 방문하지만, 특정하기 힘든 봇도 상당히 많이 방문하고 있었습니다. 특히 AI 에이전트의 영향으로 봇 종류가 천차만별이라는 사실도 알게 됐습니다.
봇은 여정 추적에 아무 도움이 되지 않습니다. 실제로 분석해 보니 단순 페이지 방문과 의미 없는 이벤트뿐이었습니다.

그냥 구경하러 온 방문자

아임웹의 브랜드는 쇼핑몰만 있는 게 아닙니다. 상상하는 모든 유형의 사이트를 쉽게 구축할 수 있어, 각양각색의 사이트가 아임웹으로 제작됐습니다. 그러다 보니 들어와서 눈팅만 하거나, 다른 페이지로 넘어가지 않는 등 여정이 아주 짧은 유저도 많았습니다.
이들이 완전히 무의미한 세션은 아니지만, 단순한 여정은 예기치 못한 에러를 마주할 확률도 상대적으로 낮아 유의미한 세션으로 보기 어렵습니다.

의미 있는 세션 획득

Datadog RUM은 세션당 과금 구조입니다. 즉 유의미한 세션만 필터링해도 비용이 상당히 줄어듭니다. 앞서 발견한 문제는 전부 세션 수와 직접 연결됩니다. 그래서 전략을 의미 있는 세션 획득에 집중하기로 했습니다. 목표는 누구인지, 어떤 여정인지를 잘 선별하는 것입니다.

로봇이 아닙니다

처음 접근한 방식은 User Agent를 식별해 차단하는 것이었습니다. Datadog RUM 공식 문서가 봇 감지용 정규표현식을 제공하고 있어, 여기에 AI 관련 에이전트를 조사해 추가해 150개 이상의 봇 시그니처로 User Agent를 검사한 뒤 세션 활성화 여부를 결정하는 로직을 넣었습니다.
notion image
이것만으로도 공개 사이트에서 일간 세션이 50% 넘게 감소하는 놀라운 효과를 확인했습니다. 다만 로그인이 필요한 백오피스는 2%만 감소했습니다. 로그인에 성공해야 SDK를 초기화할 수 있어, 대부분 로그인 진입 페이지에서 막혔을 것으로 추정됩니다.

아직도 남아 있다

일부 세션에서 여전히 봇으로 의심되는 행동 패턴이 확인됐습니다. User Agent는 얼마든지 조작할 수 있어 더 엄격한 정책이 필요했습니다.
그래서 환경 시그널 점수 방식을 도입했습니다. 플러그인 없음, 언어 설정 없음, Chrome 객체 누락 등 10가지 이상의 시그널을 검사해 세션 활성화 여부를 추가로 판단합니다. 여기에 웹드라이버가 감지되면 바로 봇으로 판정해 세션을 활성화하지 않는 간단한 스크립트도 더했습니다.
봇으로 판정되면 다음이 적용됩니다.
  • sessionSampleRate를 0으로 설정해, SDK가 초기화돼도 세션을 수집하지 않습니다.
  • sessionReplaySampleRate를 0으로 설정해 리플레이 녹화도 함께 막습니다.
  • 세션이 buffering 상태에서 영구 대기하며, 이후 어떤 이벤트도 Datadog으로 전송되지 않습니다.

구경만 하는 방문자 거르기

POC에서 발견한 패턴 중 흥미로웠던 건, 페이지에 들어와 스크롤만 내려보고 이탈하는 유형이 꽤 많았다는 점입니다. 여정이 단순할수록 수집되는 데이터의 가치도, 양도 적습니다. 이런 세션을 막기 위해 몇 가지를 시도했습니다.
세션 초기화 지연 — 페이지 진입 후 아무 액션도 하지 않거나 몇 초 만에 이탈하는 세션이 여럿이었습니다. 행동을 파악하기 힘든 유형이라, 페이지 진입 후 10초가 지나거나 첫 액션을 수행하면 세션을 초기화하는 방식을 도입했고, 봇 필터링과 함께 적용한 결과 세션 비용이 약 80% 줄었습니다.
세션 중단 막기 (적용 안 함) — RUM 세션의 만료 시간은 최대 4시간이지만, 15분 이상 비활성이면 만료됩니다. 세션이 끊기지 않게 allowUntrustedEvents 옵션으로 일정 시간마다 무작위 클릭·스크롤 이벤트를 발생시켜 연장해 봤습니다. 모니터링 결과 세션 감소 효과가 미미해 적용하지 않기로 했습니다.
여정이 기록되는 세션만 — 10초 경과 시 세션을 활성화하는 정책으로 세션 수는 많이 줄었지만, 유의미한 세션이 확보됐냐는 질문에는 그렇다고 답할 수 없었습니다. 대부분의 세션에 여정이 기록되지 않았기 때문입니다. RUM은 여정을 통해 예상되는 에러를 미리 식별하고 확산 전에 조치하기 위한 도구입니다.
이 관점에서 기록되지 않은 여정은 유의미한 세션이 될 수 없다는 결론에 이르렀습니다. 그래서 사이트 접속 후 어떤 액션이든 10회 이상 발생하면 세션을 활성화하기로 했습니다.
notion image

세션을 켤지 말지 직접 정하기

Datadog RUM SDK의 init()에는 trackingConsent 옵션이 있습니다. 이름 그대로 사용자 데이터 수집 동의 상태를 관리하는 용도로, GDPR·CCPA 같은 개인정보 보호 규정 준수를 위해 도입된 기능입니다.
기본값은 granted지만 not-granted로 설정하면 인스턴스만 생성하고 데이터를 일절 수집하지 않습니다. 당연히 세션도 생성되지 않습니다. 이렇게 쓰라고 만든 기능은 아니겠지만, 세션 활성화 여부를 SDK 로드 이후에 결정할 수 있는 유일한 수단이긴 합니다.

이벤트 카운팅

이벤트 카운팅은 이렇게 합니다.
  • 사용자 인터랙션: 페이지에서 발생하는 클릭과 스크롤은 페이지 최상위(window)에 이벤트 리스너를 두어 수집합니다. 단, interactive 요소(button, a, input 등)나 data-dd-action-name 속성이 있는 요소의 클릭만 의미 있는 액션으로 분류합니다. 빈 div 클릭처럼 의미를 추출하기 어려운 건 무시합니다.
  • 마이크로 애플리케이션에서 보낸 액션: 같은 페이지의 다른 마이크로 애플리케이션이 발생시킨 액션은 브라우저 이벤트(CustomEvent, postMessage)로 호스트에 전달돼 카운팅됩니다.
각 마이크로 애플리케이션이 보내는 이벤트는 페이지가 이동되면 유실되는데, 이를 해결하려고 이벤트가 발생할 때마다 버퍼에 추가하고 버퍼 전체를 sessionStorage에 백업하도록 구현했습니다. 또한 버퍼를 RUM 세션 비활성 타임아웃(마지막 이벤트로부터 15분)에 맞춰 폐기하면, 이전 카운트가 다음 세션에 영향을 주지 않습니다.

트래픽 규모에 따른 차등 샘플링

트래픽이 높은 사이트일수록 사용자 여정이 길고, 다양한 브라우저·디바이스 분포까지 풍부하게 잡혀 에러와 성능 지표를 분석하기에 훨씬 유의미하다는 것을 알게 됐습니다.
그래서 모든 사이트를 같은 비율로 보지 않고, 트래픽 규모에 따라 샘플링 비율을 차등 적용하기로 했습니다. 트래픽이 큰 사이트는 적극적으로, 작은 사이트는 보수적으로 수집하는 방식입니다.
앞서 봇 필터링과 세션 지연 활성화로 무의미한 세션을 줄였기 때문에 샘플링 비율을 점진적으로 올릴 수 있었고, 이는 곧 유저보다 먼저 사이트 문제를 발견할 가능성이 커졌다는 뜻이기도 합니다.
정책 차원의 비용 최적화는 정리됐지만, 이걸 60여 개 마이크로 애플리케이션에 어떻게 일관되게 적용할지가 다음 과제였습니다.

SDK를 래퍼로 포장하기

가장 먼저 손본 건 SDK 로드 방식이었습니다. 아임웹은 멀티 도메인 SaaS라 호스트 특성상 CDN 방식으로 RUM 스크립트를 로드해야 합니다. 이 방식은 DD_RUM이라는 전역 변수를 생성·노출하기 때문에 데이터 조작에 취약합니다.
이를 해결하려고 내부에서 운용할 Datadog RUM SDK 래퍼 패키지를 제작했습니다. 앞서 구현한 모든 정책을 여기에 담았습니다.
래퍼는 core와 bridge 두 엔트리포인트로 구성됩니다.
  • core — 호스트에서 사용합니다. RUM 초기화, 세션 관리, 이벤트 수집·전송(Datadog)을 담당합니다.
  • bridge — 마이크로 애플리케이션 단위에서 사용합니다. 발생한 이벤트를 호스트로 전달합니다.
ESM only이라 CDN으로 쓰더라도 전역 변수 노출 우려가 없습니다.

이벤트 추적하기

프론트엔드 챕터가 운용하는 마이크로 애플리케이션은 크게 웹 컴포넌트, Same-origin iframe, Cross-origin iframe 세 유형입니다.
웹 컴포넌트와 Same-origin iframe은 호스트와 같은 window 전역을 공유할 수 있어, CustomEvent 방식으로 이벤트를 수집·전송하면 됩니다. DOM 이벤트를 호스트 window에 디스패치하면 호스트가 그대로 받아 처리합니다.
반면 Cross-origin iframe처럼 호스트와 origin이 다르면 window.postMessage를 활용해야 합니다. 다음 액션은 bridge가 직접 자동 캡처해 전달합니다.
  • 에러: window.errorunhandledrejection을 잡아 처리되지 않은 예외를 호스트로 전달합니다.
  • 뷰 전환: history.pushState/replaceState 호출을 가로채고 popstate/hashchange도 함께 감지해, SPA 라우팅 변화를 호스트로 전달합니다.
  • 클릭: iframe의 window에서 click 이벤트를 잡되 의미 있는 요소만 캡처합니다.
  • (옵션) 리소스: trackResources를 켜면 fetchXMLHttpRequest 호출을 가로채 네트워크 요청의 시작·완료 시점, URL, 메서드, 응답 상태 코드를 호스트로 전달합니다. 동적으로 로드되는 <script> 리소스는 PerformanceObserver로 함께 감지합니다.
bridge는 마이크로 애플리케이션 유형과 무관하게 동일한 인터페이스를 제공합니다. 엔지니어 입장에서는 앱 유형과 상관없이 일관된 방식으로 API를 쓸 수 있습니다.

가심비 대신 가성비: Session Replay 대체하기

Session Replay는 유저가 세션 동안 무엇을 했는지 시각적으로 보여주는 Datadog의 화려한 기능입니다. 화면 녹화 없이도 유저 행동을 시각적으로 추적할 수 있어 원인 파악에 큰 도움이 되지만, 너무 비쌉니다. (1,000 세션당 $2.50, 일반 세션보다 약 16.7배)
게다가 이 기능은 호스트에서만 SDK를 초기화하면 iframe의 행동까지는 수집할 수 없는 치명적 한계가 있습니다. 수집하려면 iframe 마이크로 애플리케이션에서 SDK를 별도로 초기화해야 하는데, 그러면 한 페이지에서 두 세션이 활성화되는 문제가 생깁니다.
그래서 앞서 구현한 bridge로 interactive 요소의 액션을 Datadog에 자동 전송하는 방법을 적용했습니다. 핵심은 식별 가능한 이름을 추출해 전송하는 것입니다. 다음 3단계로 이름을 얻습니다.
  1. data-dd-action-name 속성 — 가장 높은 우선순위. 클릭된 요소 또는 부모 요소에 이 속성이 있으면 그 값을 사용합니다.
  1. 접근성 속성·텍스트 — 위 속성이 없으면 정해진 순서로 이름을 탐색합니다.
  1. 이름을 못 찾으면 빈 문자열을 전송합니다.
 
순서
속성
예시
추출 이름
1
aria-labelledby
<button aria-labelledby=”lal”> <span id=”lbl”>저장하기</span>
저장하기
2
aria-label
<button aria-label=”닫기”>x</button>
닫기
3
alt
<img alt=”프로필 사진” />
프로필 사진
4
textContent
<button>구매하기</button
구매하기
5
title
<button title=”설정”>설정</button>
설정
6
placeholder
<input placeholder=”검색어 입력”/>
검색어 입력
속성 값과 textContent는 전송 전 PII 패턴을 [REDACTED]로 치환합니다. 이렇게 하면 Session Replay처럼 동작을 직관적으로 볼 순 없지만, 세션에 기록된 액션 흐름으로 문제 원인 파악 시간을 줄여 Session Replay를 대체할 수 있게 됐습니다.

이만큼 줄였습니다

봇 필터링, 단순 방문 필터링, 트래픽 기반 차등 샘플링을 단계적으로 적용한 결과, 세션 수가 약 90% 감소했습니다. Session Replay까지 비활성화하면서 전체 비용은 세션 수보다 더 많이 줄었습니다.
봇 필터링이 세션 수를 줄이는 데 가장 효과적이었지만, 유의미한 세션 필터링을 더하면서 수집되는 세션의 품질 자체가 놀랍도록 향상됐습니다.

마무리

비용을 줄여볼까에서 시작한 여러 실험은, 비용 절감을 넘어 어떻게 효과적으로 여정을 수집할까라는 질문까지 확장됐습니다. 그 결과 유의미한 세션만 획득하면서도 편리한 RUM SDK 사용 환경을 함께 제공할 수 있게 됐습니다.
세션당 과금 방식이 나쁜 건 전혀 아닙니다. 오히려 세션 안에서 수집되는 요소에는 추가 비용이 거의 들지 않아 유리할 때가 많습니다.
짧은 POC 기간과 타이트한 일정에도 이만큼 최적화할 수 있었던 건, 각자의 스쿼드에서 다양한 시각으로 바라보는 프론트엔드 엔지니어들이 있었기에 가능했습니다.
의미 있는 세션만 필터링하면 모니터링 항목의 품질을 잃지 않으면서 비용까지 확실히 줄일 수 있습니다. Datadog RUM을 도입하는 데 이 글이 도움이 되길 바랍니다.

댓글