Henry
← 모든 글

프론트 에러 관측

프론트엔드 에러 알림 구축

서비스와 환경별로 Datadog RUM 모니터를 만들고 새 에러를 Slack에서 받아보기 시작했다.

4분 읽기수정 2026-09-06

프론트 에러는 보통 채널톡 문의가 들어오고 나서야 알았다.

"수업 생성이 안 된다"거나 "결제가 되지 않는다"는 문의가 들어오면 CS 담당자나 기획자가 개발 채널에 확인을 요청했다. 브라우저에서 생긴 문제는 Datadog Session Replay로 사용자의 세션을 찾았다. 서버 요청까지 확인해야 할 때는 ECS 컨테이너의 CloudWatch 로그를 검색했다.

가끔 Datadog에서 최근 에러를 열어보긴 했지만 정해진 주기는 없었다. 사용자가 먼저 불편을 겪고 문의를 남긴 다음에야 에러를 보는 날이 많았다.

알림이 아예 없었던 건 아니다. 한 서비스의 운영 스크립트 에러를 Slack으로 보내는 모니터가 이미 있었다. 문제는 별도의 제외 조건 없이 하루 동안 한 번이라도 발생한 이슈를 모두 보내고 있었다는 점이다.

예전 기록을 보면 서로 다른 알림이 몇 초 간격으로 열 건 넘게 이어졌다. Failed to fetch, ResizeObserver, MetaMask 연결 실패, 사용자 취소 메시지와 외부 SDK 에러가 한곳에 섞여 있었다.

Failed to fetch 한 줄만으로는 원인을 알기 어려웠다. 알림을 눌러봐도 서비스 동작에는 문제가 없는 경우가 많았고 누가 확인했는지도 남지 않았다. 나도 어느 순간 채널 알림을 꺼두고 필요할 때만 Datadog을 찾고 있었다.

매일 올라오던 백엔드 에러 리포트

어느 날 다른 개발자가 만든 백엔드 에러 자동 분석 시스템이 개발 채널에 공유됐다. Datadog에 500 에러가 찍히면 Claude가 로그와 코드를 확인해 원인을 정리하고, 매일 오전에는 아직 처리하지 않은 항목을 다시 올려주는 방식이었다.

스레드에 공유된 저장소도 열어봤다. 로컬 스케줄러로 계속 실행하는 구조라 실제로 주말에도 노트북을 켜둔 채 돌리고 있었다.

그걸 보니 프론트도 문의를 기다리지 않고 하루치 RUM 에러를 먼저 볼 수 있겠다 싶었다. Claude 커넥터에 Datadog이 있었고 루틴으로 매일 데이터를 조회할 수도 있었다.

새로 생긴 에러는 바로 Slack으로 받고, 하루 동안 쌓인 에러는 다음 날 한 번에 정리해보기로 했다.

모니터 6개부터 다시 만들었다

선생님용 웹은 dev와 prod 2개, 수강생용 서비스는 web과 app을 다시 dev와 prod로 나눠 4개를 만들었다. 총 6개 모니터에서 새로운 에러 패턴이 잡히면 프론트 에러 전용 Slack 채널로 알림이 오게 했다.

기존 알림과 달리 어느 서비스와 환경에서 발생했는지 먼저 보이게 했다. RUM 이슈로 바로 들어가는 링크도 넣었다. dev 모니터는 배포 전에 테스트하면서 처음 생긴 에러를 찾을 때 사용했다.

처음부터 필터를 많이 걸지는 않았다. 테스트 중인 설정과 쿼리를 프론트엔드 채널에 공유했고 다른 개발자도 들어오는 알림을 같이 봤다.

프론트엔드 채널에 공유한 Datadog 신규 에러 로깅 테스트
프론트엔드 채널에 올린 모니터 테스트 공지

실제 버그를 찾은 날에는 알림 스레드에 수정 PR을 달았다. 배포 뒤 같은 에러가 다시 생기는지도 그곳에서 확인했다.

리포트를 만들고 나서야 보인 에러도 있었다

첫 테스트에서는 한 서비스의 웹 구간만 수천 건이 잡혔다. 상위에는 Amplitude와 푸시 SDK 로그가 반복됐고, API 500과 처음 보는 프론트 에러도 섞여 있었다.

상위 에러를 하나씩 열다 보니 화면만 봐서는 모르던 문제도 나왔다.

하나는 공지의 New 배지를 확인하는 요청이었다. 훅이 함수가 아니라 이미 시작된 Promise를 반환하고 있어서 컴포넌트가 렌더될 때마다 요청이 나갔다. 요청이 끝나기 전에 페이지를 옮기면 React Query 바깥에서 시작된 Promise가 Failed to fetch로 남았다. 최근 30일 동안 602건, 193세션에 쌓여 있었지만 New 배지는 정상적으로 보여 화면만 봐서는 알아채기 어려웠다.

다른 서비스에서는 2024년부터 쌓인 구조분해 에러를 찾았다. 상세 페이지를 떠난 직후에 주로 발생했다. useEffect에서 호출한 Server Action이 이탈 과정에서 undefined로 끝날 수 있는데 항상 튜플이 온다고 보고 바로 구조분해하고 있었다. 발생한 세션은 모두 WebKit이었다. RUM에서 확인된 네 곳에 가드를 추가한 뒤 dev 환경의 Safari에서 같은 조건으로 확인했다.

하루치 발생량을 계속 확인한 과정은 프론트 에러 일간 리포트 만들기에 따로 적었다.

알림을 켜도 필터는 끝나지 않았다

처음부터 들어오는 에러를 전부 정확하게 나누지는 못했다. 브라우저 확장 프로그램이나 외부 SDK 로그도 계속 들어왔고, 당장 원인을 정하기 어려운 에러도 있었다.

반복해서 보이던 SDK 로그는 RUM 데이터를 확인한 뒤 수집 단계에서 줄였다. 하루치 발생량과 새 에러를 같이 보는 프론트 에러 일간 리포트도 만들었다.

우리 Next.js 번들에서 난 것처럼 보였던 Failed to fetch는 브라우저 확장 프로그램에서 발생한 에러였다. 이 경우 원본 데이터는 남기고 Slack 모니터에서만 제외했다.