Sentry 도입 일지

2026년 05월 18일

개발프론트엔드

현재 회사에 Sentry를 도입하고 개선한 경험을 나눠보고자 합니다.

이전 회사에서도 Sentry나 Datadog 같은 모니터링 체계를 구축해보고 싶은 마음이 있었는데 지금 회사에서 다뤄볼 기회가 있었고 이를 기록해두려고 합니다.

Sentry란

Sentry는 요약하자면 서비스에서 발생하는 에러를 자동으로 모아서 보여주는 도구입니다. 단순하게 말하면 실시간 로그 취합 및 분석 도구이면서 모니터링 플랫폼입니다. 로그에 대한 자세한 정보를 제공하며 이벤트, 이슈별로 에러 모니터링을 용이하게 할 수 있으며 알림 기능도 지원해 바로 파악이 가능하게 해주는 툴입니다.

운영 중 에러를 알려면 서버에 직접 접속해서 로그 파일을 들여다보거나, 사용자의 CS 문의가 들어왔을 때만 파악이 가능했습니다. 이를 해결하고자 필요한 것이 바로 Sentry 입니다.

도입 이유

점점 서비스의 유저가 늘어나게 되면서 다양한 에러들이 나왔고 이를 쉽게 파악하기가 어려웠습니다. EC2 로그를 보고 고객 CS 문의를 보며 원인을 찾아야 했습니다. 당연히 이렇게 모든 에러를 해결하는 것은 불가능에 가까웠고 모니터링 체계 구축에 대한 필요성이 점점 커졌습니다.

가장 필요로 했던 기능은 두 가지였습니다.

  • 에러가 발생 했을 때 바로 알 수 있어야 함
  • 에러에 대한 상세한 정보를 알 수 있어야 함

이외 유저 경로, 성능 측정, 재현 가능 등도 필요로 했고 Sentry를 통해 모든 것을 해결할 수 있었기에 Sentry를 도입했습니다.

Sentry 핵심 개념

이제 Sentry를 이해하기 위한 핵심 용어과 개념에 대해 살펴보겠습니다.

  1. 이벤트 (Event)

    • Sentry에 들어가는 개별 기록입니다.
    • 각각의 이벤트가 하나의 에러가 될 수 있습니다.
  2. 이슈 (Issue)

    • 비슷한 이벤트들을 Sentry가 묶어서 보여주는 그룹입니다.
  3. 에러 캡쳐 (Capture)

    • 에러 정보를 Sentry로 전송하는 행위입니다. 아래와 같은 종류가 있습니다.

      • captureException : 에러 객체나 문자열 전송 가능

        import * as Sentry from '@Sentry/react'
        
        try {
          aFunctionThatMightFail()
        } catch (err) {
          Sentry.captureException(err)
        }
        
      • captureMessage : 문자열 전송 기능

        Sentry.captureMessage('에러가 발생했습니다!')
        
    1. 태그 (Tag)
      • 에러에 붙이는 라벨입니다. Sentry 대시보드에서 검색,필터, 알림 조건으로 쓰입니다.
    2. 브레드크럼 (Breadcrumb)
      • 에러 직전까지의 사용자 행동 기록을 의미합니다. “빵 부스러기”라는 뜻처럼 직전 유저의 기록을 확인할 수 있습니다.
    3. 세션 리플레이 (Session Replay)
      • 사용자 화면을 비디오처럼 재생해주는 기능입니다.
      • 개인정보 보호를 위해 마스킹 정책 등을 고려해야 합니다.
    4. 분산 트레이싱
      • 하나의 사용자 행동을 처음부터 끝까지 한 흐름으로 묶어서 보는 것입니다.
    5. 소스맵 (Source Map)
      • 빌드된 코드를 원본 코드로 되돌려주는 매핑 파일입니다.
      • 에러가 났을 때 실제 어느 코드 라인에서 발생했는지 알아볼 수 있게 해줍니다.
    6. 에러 종류
      • Unhandled Error
        • try/catch 밖으로 터진 에러
        • 자동 수집되기 쉬움
      • Handled Error
        • try/catch로 잡았지만 captureException 명시적으로 보낸 에러

    이외 여러가지가 있지만 설명한 내용만 봐도 충분히 설정이 가능하므로 어떻게 개선했는지를 살펴보겠습니다.

    개선 사항

    1. 단순 에러 수집이 아닌 실질적인 모니터링 기능으로 확대

    기존 에러 수집 단계까지는 구축이 되어 있었다면 이를 실질적인 모니터링 기능으로 확대하고자 했습니다.

    1.1 프로젝트 설정

    현재 회사는 같은 서비스를 웹과 앱 동시에 서비스하고 있습니다. 따라서 앱과 웹을 별도의 프로젝트를 설정하여 각각의 이슈를 트래킹할 수 있도록 했습니다.

    각각 별도의 프로젝트와 DSN을 설정하였고 알림 체계를 통합하여 앱,웹 각각의 이슈를 효과적으로 파악할 수 있도록 개선했습니다.

    1.2 태그 확대

    에러를 구분할 때 사용되는 태그 범위를 확대했습니다. 아래와 같이 구분하여 에러 발생 위치, 서비스, 심각성 등을 나누어 개발자가 이슈를 볼 때 중요도를 쉽게 파악할 수 있도록 개선했습니다.

    태그 예시

    태그형식부착 방법예시
    featurekebab-case수동 (필수)toss-payment-confirm
    error.actionsnake_case수동 (필수)payment_confirm
    error.servicekebab-case수동 (필수)toss, points
    error.severityenum수동 (필수)critical / high / medium
    error.sourceenum자동 (beforeSend)internal / external

    또한 수동으로 부착하지 않아도 beforeSend 가 자동으로 붙이는 태그도 확대했습니다.

    간단하게 몇 가지 보자면 아래와 같습니다.

    • api.method - GET , POST
    • api.path - api/test/sentry
    • api.status - 500 , 400

    1.3 에러 캡쳐 공통 헬퍼 함수 구축

    captureException , captureMessage 등 라우트마다 산재되어있던 것을 공통 헬퍼 서비스 함수로 구축하여 에러 출력 양식을 통일시키고자 했습니다.

    아래처럼 유저 정보, 응답 컨텍스트, 필수 태그 등이 통일성 있게 삽입될 수 있도록 구현했습니다.

    export function captureApiError(error, request, options) {
      Sentry.withScope((scope) => {
        // 유저 정보 부착
        if (options?.user) scope.setUser({ id: options.user.userId, ... });
    
        // 요청 컨텍스트 (헤더는 sanitize)
        scope.setContext('API Request Detail', {
          method: request.method,
          url: request.url,
          headers: sanitizeData({ ... }),
        });
    
        // 응답 컨텍스트 (바디 트렁케이트)
        scope.setContext('API Response Detail', {
          status: options.responseStatus,
          data: truncateData(sanitizeData(options.responseBody)),
        });
    
        // 5축 태그
        scope.setTag('feature', options.feature);
        scope.setTag('api.method', request.method);
        scope.setTag('api.path', new URL(request.url).pathname);
        scope.setTag('api.status', options.responseStatus.toString());
    
        // fingerprint / severity / level 자동 결정
        if (options.fingerprint?.length) scope.setFingerprint(options.fingerprint);
        if (options.responseStatus >= 500) scope.setLevel('error');
    
        Sentry.captureException(normalizeError(error));
      });
    }
    

2. 알림 연동

사내 메신저 툴로 Slack을 사용하고 있었기에 Slack 채널을 연동하여 알림 기능을 통해 빠르게 에러를 파악할 수 있도록 했습니다.

또한 단순 알림이 아닌 커스텀 알림을 설정하여 개발자가 한 눈에 어떤 알림인지 볼 수 있도록 구현했습니다.

예를 들어 결제, 환급, 사용자 리뷰 제출 등 핵심 기능인 것들은 error.severity 태그가 critical 로 설정하여 해당 알림의 빈도와 메시지 등을 우선순위에 맞게 수정하였습니다.

또한 한 가지 더 예시를 들자면 외부 에러 또한 error.sevirce 태그가 external 인 것들을 따로 모아 외부 API 에러임을 알 수 있도록 수정하였습니다.

스크린샷 2026-05-14 오후 5.37.27

위처럼 커스텀 알림을 통해 알림을 세세하게 나누니 이슈 파악에 드는 공수가 훨씬 절약 되었고 빠르게 기능 수정 혹은 CS 응대가 가능해졌습니다.

도입 및 개선 후

Sentry를 도입 후 또 실제 모니터링 기능으로 개선해가는 과정을 거치면서 다음과 같은 장점을 얻을 수 있었습니다.

  1. 에러 트래킹의 용이함
  2. 알림 등 빠른 에러 파악으로 조기 대응 가능

아래처럼 다양한 이슈를 한 번에 파악할 수 있으며 보안상 테스트 알림이지만 Slack 을 통해 빠른 에러 파악으로 조기 대응이 가능하여 서비스 운영의 효율성을 향상 시킬 수 있었습니다.

스크린샷 2026-05-14 오후 5.37.47 스크린샷 2026-05-14 오후 5.36.58

마무리

아직 더 서비스를 운영하면서 개선해야할 점들이 보이지만 Sentry 도입 후 CS 응대까지 걸리는 시간이 대폭 절약되었고 기능 수정도 빠르게 이어질 수 있어 사용자 이탈률이 줄어드는 모습을 확인할 수 있었습니다.

이를 통해 서비스 개발을 넘어 모니터링의 중요성을 깨달았으며 인프라 등 다양한 요소를 쉽게 파악할 수 있는 체계적인 시스템의 필요성을 절실히 느꼈습니다.

좀 더 시간이 주어진다면 Sentry MCP와 같은 시스템을 도입하여 더 쉽고 빠른 모니터링 체계를 구축하고 싶고 세션 리플레이 기능이나 LLM 모니터링 등 Sentry를 더 자세히 사용해보고 싶습니다.