Skip to main content
입문

관측성 신호: 숫자에서 원인까지 어떤 증거를 따라갈 것인가

로그·오류·메트릭·트레이스·프로파일이 답하는 질문을 구분하고, 공통 문맥으로 연결해 사용자 문제를 릴리스와 코드 위치까지 좁힌다.

마지막 검증 재검증 정책: 제품 버전 의존: 새 주요 버전마다 재검증
목차
표준·구현·측정·해석 표시는 무엇인가요?
  • 표준웹 표준이나 언어 명세가 정한 동작
  • 구현특정 기술이나 브라우저가 실제로 구현한 동작
  • 측정명시한 환경에서 직접 실행해 관찰한 결과
  • 해석앞선 근거에서 도출한 설계 판단
  • 미확인아직 공식 근거나 재현 결과를 확인하지 못한 내용

30초 요약

관측성 신호는 같은 사실을 다른 모양으로 저장한 복사본이 아니다. 각 신호는 서로 다른 질문에 답한다.

신호먼저 답하는 질문혼자서는 부족한 것
메트릭얼마나 많고, 느리고, 언제 변했는가?한 사용자의 정확한 사건 순서
트레이스한 요청이 어디를 거쳤고 어느 단계가 느리거나 실패했는가?코드 전체의 자원 소비 위치
로그그 시각에 무슨 사건과 실패가 있었는가?전체 영향 규모와 요청 경로
프로파일어느 코드 호출 스택이 중앙 처리 장치(CPU)·메모리 같은 자원을 썼는가?사용자 영향과 실패 이유 전체

오류는 별도 신호 형식이 아니라 로그·트레이스 안 한 작업 단위인 스팬·메트릭 등에 표현되는 실패 사건이다.

반복해서 기억할 문장은 이것이다.

숫자로 이상을 찾고, 흐름으로 좁히고, 사건으로 읽고, 프로파일로 코드까지 내려간다.

이 순서는 고정된 도구 사용법이 아니라 진단 흐름이다. 오류 한 건에서 시작해 반대로 영향 규모를 확인할 수도 있다. 중요한 것은 모든 단계가 같은 시각·환경·릴리스·실행 문맥을 가리키게 하는 것이다.

메트릭으로 감지·범위 좁히기 → 트레이스로 흐름 따라가기 → 로그로 사건 읽기
→ 프로파일로 코드 위치 파고들기 → 릴리스 연결

아래 절은 각 신호의 정의를 설명하기 위해 메트릭·로그·트레이스·프로파일 순서로 놓았다. 실제 진단에서는 위 회상축을 따르거나, 이미 발견한 오류에서 시작해 신호 사이를 반대로 왕복한다. 이 글에서는 새 Web 릴리스 뒤 결제 완료가 느려진 상황을 대표 사례로 삼는다. 각 신호의 정의를 읽을 때 “지금 아는 사실에서 다음에는 어떤 증거를 봐야 하는가?”만 이어서 묻는다.

관측성은 도구가 아니라 질문할 수 있는 능력이다

원격 측정 데이터가 많다는 사실과 관측성이 좋다는 말은 같지 않다.

데이터는 많음
  ├─ 릴리스 식별자 없음
  ├─ Web과 서버 요청을 연결할 문맥 없음
  ├─ 실패한 사용자 흐름을 구분할 필드 없음
  └─ 질문마다 어떤 신호를 볼지 정하지 않음
      → 원인을 좁히기 어려움

대시보드는 저장된 데이터를 보여 주는 화면이다. 관측성은 새 문제를 만났을 때 필요한 질문을 하고 증거를 따라 답을 얻는 성질이다. 따라서 먼저 “무엇을 수집할까?”가 아니라 다음을 묻는다.

  1. 어떤 사용자 결과가 나빠졌다는 사실을 알아야 하는가?
  2. 어느 환경·릴리스·화면·장치 범위에서 생겼는가?
  3. 한 실패 흐름을 어느 시스템 경계까지 이어 봐야 하는가?
  4. 마지막에 어떤 코드나 자원 소비 위치까지 좁혀야 하는가?

신호마다 질문이 다르다

예를 들어 “상품 상세 화면이 느리다”는 보고 하나에도 질문이 여러 개다.

얼마나 많은 사용자가 느린가?             → 메트릭
한 느린 화면에서 어떤 사건이 있었는가?    → 로그
화면 요청이 어느 서버 단계를 거쳤는가?    → 트레이스
느린 순간 어느 코드가 CPU를 사용했는가?  → 프로파일

하나의 신호로 모든 질문에 답하려 하면 두 문제가 생긴다. 메트릭에 사건의 모든 세부 값을 넣으면 집계 비용과 분류 수가 커지고, 로그만 쌓으면 전체 추세와 영향 범위를 빠르게 보기 어렵다. 신호별 책임을 나누고 공통 문맥으로 연결한다.

메트릭은 “얼마나, 언제, 어느 범위에서”를 답한다

메트릭은 이상을 찾는 출발점으로 유용하다.

  • 결제 시도 중 실패한 비율이 배포 전후에 달라졌는가?
  • 화면 응답 시간의 중앙값뿐 아니라 느린 쪽 분포가 악화됐는가?
  • 특정 앱 버전이나 운영체제에서 화면 멈춤 비율이 높은가?
  • 사용자에게 성공으로 보인 요청의 비율은 목표를 지키는가?

평균 하나만 보면 일부 사용자의 심한 지연이 숨을 수 있다. 그래서 지연 시간은 여러 측정값의 분포를 보고, 사용자 경험 기준은 백분위수처럼 “측정값을 작은 순서로 놓았을 때 어느 위치인가”를 이용하기도 한다. 어떤 집계와 분류를 얼마나 남길지는 다음 13편에서 다룬다.

메트릭이 checkout_failure_rate = 4.2%라고 알려 줘도 어느 사용자의 어떤 요청이 왜 실패했는지는 알 수 없다. 이때 같은 시각·릴리스의 트레이스나 로그로 이동한다.

로그는 “무슨 사건이 있었는가”를 답한다

사람이 읽는 문장만 남기기보다 조사에 필요한 필드를 분리한다.

{
  "time": "2026-08-04T10:15:31Z",
  "event": "checkout.failed",
  "reason": "inventory_conflict",
  "release": "web@sha256:abc...",
  "environment": "production",
  "traceId": "4bf92f..."
}

이 예시는 특정 제품 형식이 아니다. event는 일어난 사건의 안정된 이름이고 reason은 프로그램이 구분한 실패 이유다. 릴리스와 트레이스 식별자는 11편의 산출물과 이번 요청 흐름을 이어 준다.

좋은 로그는 “무슨 일이 일어났는가?”를 읽게 하지만, 기록하지 않은 상태를 나중에 만들어 내지는 못한다. 반대로 모든 객체와 응답 내용을 그대로 기록하면 개인정보·비밀 정보와 비용 문제가 생긴다. 질문에 필요한 최소 문맥과 보존 정책을 먼저 정한다.

오류는 하나의 독립 신호가 아니다

“오류를 수집한다”는 말만으로는 어떤 질문에 답하는지 알 수 없다.

오류 한 건의 메시지·스택·문맥      → 오류 로그 또는 오류 사건
릴리스별 오류 발생률                → 메트릭
오류가 난 요청의 브라우저→서버 경로 → 트레이스
오류 순간의 코드 호출 위치           → 스택 트레이스

스택 트레이스는 오류 지점까지 이어진 함수 호출과 코드 위치 목록이다. 5편에서 설명한 소스 맵은 변환된 위치를 원본 위치로 바꾸는 데 도움을 주지만, 발생 규모나 사용자 흐름까지 자동으로 알려 주지는 않는다. 오류 그룹화·원본 위치 복원은 5편의 경계를 따르고 여기서는 다른 신호와 연결하는 역할만 다룬다.

트레이스는 “어느 경로를 거쳤는가”를 답한다

trace: checkout-42
 
[브라우저 상호작용  0~820ms]
  └─ [서버 요청      40~790ms]
       ├─ [재고 확인  70~260ms]
       └─ [결제 처리 270~760ms]  ← 느린 단계

트레이스는 “전체가 820ms였다”에서 멈추지 않고 어느 단계가 시간을 사용했는지 좁힌다. 각 스팬의 속성에는 작업 이름, 상태와 릴리스 같은 문맥을 붙일 수 있다. 다만 스팬을 세밀하게 나누는 것과 모든 트레이스를 저장하는 것은 비용이 있으므로 수집 범위는 별도 정책이 필요하다.

문맥이 끊기면 신호도 끊긴다

브라우저에서 서버로 요청했는데 추적 문맥이 전달되지 않으면 두 기록은 시간으로 추측해서 맞춰야 한다. 같은 시각에 요청이 많으면 이 연결은 쉽게 틀린다.

브라우저 span ── traceparent 전달 ──> 서버 span ──> 데이터 저장 span
      │                                  │
      └─ traceId가 같은 오류 로그 ───────┘

추적 헤더가 있다고 전체 경로가 자동으로 저장되는 것은 아니다. 각 경계가 문맥을 전달하고 필요한 스팬을 기록해야 한다. 외부 서비스가 헤더를 받거나 돌려주는 정책, 브라우저의 다른 출처 요청 허용 범위도 실제 환경에서 검증한다.

프로파일은 “어느 코드가 자원을 썼는가”를 답한다

메트릭이 CPU 사용량 상승을 알리고 트레이스가 느린 요청 단계를 찾았다면, 프로파일은 그 구간에 어느 코드 호출 스택이 반복해서 나타났는지 보여 줄 수 있다.

메트릭: checkout 화면의 CPU 시간 증가
트레이스: 브라우저 렌더 단계가 느림
프로파일:
  48% normalizeItems → sort → compare
  21% renderRows → formatPrice

프로파일만 보고 normalizeItems가 사용자 문제의 원인이라고 단정하지 않는다. 같은 시간과 릴리스, 가능하다면 같은 트레이스 문맥에 연결하고 재현이나 변경 전후 비교로 확인한다.

프로파일링은 관측 자체가 실행에 비용을 더할 수 있다. 표본 빈도, 대상 사용자와 기록 시간은 목표와 허용 비용을 기준으로 정해야 한다. 구체적인 샘플링 정책은 다음 글에서 다룬다.

신호를 공통 문맥으로 연결한다

이 글에서는 같은 원리를 프론트엔드에 적용해 환경·앱 버전·릴리스·장치 계층을 공통 문맥으로 사용한다. 실제 필드 이름과 허용 값은 사용하는 도구의 의미 규칙과 개인정보 정책에 맞춘다.

최소 연결축은 질문에 따라 달라지지만 다음 네 종류를 구분하면 기억하기 쉽다.

연결축답하는 질문
시간시작·끝 시각같은 이상 구간인가?
배포 문맥환경, 릴리스 다이제스트, 앱 버전어느 변경과 함께 나타났는가?
실행 문맥trace ID, span ID, 세션 범위 식별자같은 요청·사용자 흐름인가?
대상 문맥화면 경로, Web·JS·UI·native 계층, 장치 종류어느 실행 표면에서 생겼는가?

사용자 ID나 전체 주소를 무조건 연결축으로 쓰지 않는다. 필요한 구분 수준과 개인정보 정책을 먼저 정하고, 안정된 범주와 짧은 보존 기간으로도 질문에 답할 수 있는지 검토한다. 서로 다른 값이 얼마나 많이 생기는지는 카디널리티라고 하며, 수집 비용과 함께 13편에서 다룬다.

Web에서는 사용자 결과와 내부 단서를 분리한다

LCP(Largest Contentful Paint)는 큰 주요 콘텐츠가 보인 시점, INP(Interaction to Next Paint)는 사용자 상호작용 뒤 다음 화면 표시까지의 반응성, CLS(Cumulative Layout Shift)는 예상하지 않은 화면 배치 이동의 누적 정도를 나타낸다.

이 세 값은 사용자가 느낀 결과를 알려 주지만 원인을 직접 말하지 않는다.

INP 악화 감지
  → 어느 화면·릴리스·브라우저 범위인가?
  → 느린 상호작용의 트레이스가 있는가?
  → 긴 JavaScript 작업이나 React 렌더 로그가 있는가?
  → 해당 구간의 프로파일에서 어느 호출 스택이 많은가?

실험실에서 한 번 빠르게 나온 값과 실제 사용자 분포도 구분한다. 네트워크·장치·캐시·사용자 행동이 다른 현장 데이터는 영향 범위를 보여 주고, 통제한 실험실 측정은 원인 가설을 반복 검증하는 데 유리하다.

React Profiler는 React 렌더링 경계만 측정한다

사용자 클릭
  → 데이터 요청
  → 상태 변경
  → React 렌더 ← Profiler가 렌더 시간을 측정
  → 커밋(계산한 변경을 브라우저 문서 구조에 적용) ← Profiler가 커밋 문맥을 전달
  → 브라우저 레이아웃·화면 그리기
  → 사용자가 다음 화면을 봄

React 렌더가 느린지 묻는다면 Profiler가 맞다. “클릭 뒤 화면이 늦게 보였다”를 묻는다면 요청 트레이스, 브라우저 성능 항목과 React 렌더 기록을 같은 상호작용 문맥으로 함께 본다.

React Native는 JavaScript와 UI 계층을 나눠 본다

같은 “스크롤이 끊긴다”는 증상도 신호 경로가 다르다.

JavaScript 프레임 저하
  → 상태 계산, React 렌더, JavaScript 작업 프로파일
 
UI 프레임 저하
  → 네이티브 화면 배치·그리기, 그래픽 처리 장치(GPU)와 시스템 트레이스
 
둘 다 정상처럼 보임
  → 장치·운영체제 범위, 네트워크·이미지·메모리 신호 재확인

개발 모드는 경고와 검사 때문에 JavaScript 실행 비용이 커진다. React Native 공식 문서도 성능을 릴리스 빌드에서 확인하라고 안내한다. 개발 환경의 숫자를 운영 사용자 메트릭과 직접 비교하지 않는다.

JavaScript 번들과 네이티브 앱이 서로 독립적으로 바뀌는 배포 구조라면, 조사할 때 두 버전을 함께 구분할 수 있도록 기록하는 것을 권장한다. 같은 JavaScript 코드라도 운영체제·장치와 네이티브 연동 코드의 경계가 다르면 사용자 결과가 달라질 수 있기 때문이다.

현재 OpenTelemetry 브라우저 구현은 근본 모델과 분리한다

이 글의 로그·메트릭·트레이스 구분은 특정 도구에 종속되지 않는 질문 모델이다. 실제 Web 앱에 OpenTelemetry 브라우저 패키지를 도입할지는 다음을 확인해 판단한다.

  • 필요한 브라우저와 프레임워크 경계를 실제로 계측하는가?
  • 번들 크기와 실행 비용이 허용 범위인가?
  • 페이지 종료·오프라인·네트워크 실패에서 데이터 손실을 어떻게 다루는가?
  • 사용하는 신호 기능 계약과 의미 규칙의 현재 안정 상태는 무엇인가?
  • 기존 오류·성능 도구와 같은 실행 문맥으로 연결할 수 있는가?

도구를 채택하지 않아도 질문 모델은 유지된다. 다른 개발 도구 묶음(SDK)을 쓰더라도 규모· 사건·경로·코드 위치를 어떤 데이터가 답하는지와 공통 문맥이 이어지는지를 검토한다.

문맥 식별자에 개인정보를 넣지 않는다

추적 식별자는 비밀값이 아니다. 브라우저와 여러 서비스 경계를 통과할 수 있고 저장될 수 있다. 사용자 이메일, 인증 값, 검색어 전체나 응답 본문을 식별자와 속성에 그대로 넣지 않는다.

조건부 권장은 수집 전에 허용 필드 목록, 삭제·가림 규칙, 보존 기간과 접근 권한을 정하는 것이다. 오류 조사에 원문이 꼭 필요하다면 왜 필요한지, 더 좁은 값으로 대체할 수 없는지와 누가 볼 수 있는지를 함께 결정한다.

실제 진단에서는 신호를 왕복한다

예를 들어 새 Web 릴리스 뒤 결제 완료가 느려졌다고 하자.

  1. 감지 — 완료 시간 메트릭이 실제로 악화됐는가?
  2. 범위 — 어느 릴리스·화면·브라우저·지역 구간에서 변했는가?
  3. 흐름 — 느린 사례의 트레이스에서 브라우저·서버 중 어느 스팬이 긴가?
  4. 사건 — 같은 trace ID의 로그에 재시도·오류·상태 변화가 있는가?
  5. 코드 — 병목 구간의 프로파일이나 React 렌더 기록에서 어느 작업이 두드러지는가?
  6. 릴리스 — 11편의 식별자로 검증·배포한 어느 산출물부터 변화가 시작됐는가?

오류 한 건에서 시작했다면 반대로 간다. 로그의 trace ID로 경로를 보고, 같은 릴리스의 오류율 메트릭으로 전체 영향을 확인한다. 신호 사이를 왕복하면서 가설을 줄인다.

신호가 없을 때도 결론을 과장하지 않는다

“오류 로그가 없다”는 사실은 오류가 없었다는 증거가 아닐 수 있다. 해당 경로를 계측하지 않았거나, 브라우저가 데이터를 보내기 전에 종료됐거나, 수집 과정에서 손실됐을 수 있다. 먼저 다음을 묻는다.

  • 이 실행 표면을 실제로 계측했는가?
  • 데이터가 만들어지고 전송·저장되는 각 단계가 정상인가?
  • 어떤 사용자·요청을 수집 대상에서 제외했는가?
  • 시간대와 릴리스 식별자가 맞는가?

관측 파이프라인도 실패할 수 있는 시스템이다. 신호의 부재와 정상 상태를 같은 뜻으로 쓰지 않는다.

어떤 신호부터 볼지 고르는 기준

문장을 질문으로 바꾸면 시작점을 고르기 쉽다.

지금 가진 질문먼저 볼 신호다음 연결
실패가 배포 뒤 늘었는가?릴리스별 오류율 메트릭오류 로그 → 트레이스
이 사용자 요청이 어디서 실패했는가?오류 사건 또는 트레이스같은 trace ID의 로그
어느 서버·클라이언트 단계가 느린가?트레이스느린 스팬의 로그·프로파일
React 업데이트에서 어느 트리가 비싼가?React Profiler 기록사용자 상호작용·Web Vitals
React Native 화면 끊김이 어느 계층인가?JS·UI 프레임 신호와 시스템 트레이스해당 계층 프로파일
어느 코드가 CPU를 많이 쓰는가?프로파일같은 시간의 메트릭·트레이스

마지막으로 다시 기억한다.

숫자로 이상을 찾고, 흐름으로 좁히고, 사건으로 읽고, 프로파일로 코드까지 내려간다.

그리고 어느 신호에서 시작하든 시간·환경·릴리스·실행 문맥을 연결한다.

다음 글과의 경계

이번 글은 신호별 질문과 연결 방법에 집중했다. 다음 내용은 분리한다.

  • 어떤 데이터를 얼마나 남길지 정하는 법: 13편 샘플링과 카디널리티
  • JavaScript 업데이트와 네이티브 앱의 실행 가능 범위: 14편 앱 버전과 호환성 계약
  • 어떤 신호로 소수 사용자 배포를 넓히거나 멈출지 정하는 법: 17편 점진 배포와 카나리 배포
  • 관측 데이터 저장·전송 비용을 계산하는 법: 20편 프론트엔드 비용 모델
  • 오류 위치를 원본 코드로 복원하는 법: 5편 소스 맵

대시보드 제품 이름보다 먼저 질문을 고른다. 신호 하나에 모든 답을 요구하지 않고, 각 신호가 잘 답하는 질문에서 다음 증거로 이동한다.

Active recall

기억에서 꺼내 보기

답을 쓰지 않아도 됩니다. 먼저 머릿속으로 답한 뒤 펼쳐서 정답·이유·흔한 오해를 비교하세요.

  1. 01결제 실패율이 지난 배포 뒤 얼마나 늘었는지 먼저 보려면 로그와 메트릭 중 무엇이 맞을까?

    정답

    시간 구간과 릴리스별 발생 규모·추세를 비교하는 메트릭이 먼저 맞다. 한 실패의 자세한 사건 문맥은 연결된 로그로 읽는다.

    왜 그런가

    집계 질문과 개별 사건 질문은 필요한 데이터 모양이 다르다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

  2. 02오류는 로그·메트릭·트레이스와 나란히 놓이는 하나의 고정된 관측 데이터 형식일까?

    정답

    아니다. 오류는 실패 사건이며 로그 항목, 오류 횟수 메트릭, 트레이스 안 한 작업 단위인 스팬의 사건이나 상태처럼 여러 신호에 표현될 수 있다.

    왜 그런가

    표현을 나누면 발생 규모, 한 사건의 문맥과 실패 경로를 각각 볼 수 있다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

  3. 03한 요청의 어느 단계가 느렸는지와 그때 어느 코드가 CPU를 많이 썼는지는 같은 신호가 답할까?

    정답

    요청 경로와 느린 단계는 트레이스가, 코드 수준 자원 소비 위치는 프로파일이 더 직접적으로 답한다.

    왜 그런가

    두 기록을 같은 시간·트레이스 문맥으로 연결하면 느린 단계와 코드 위치를 이어 볼 수 있다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

  4. 04React Profiler에서 렌더링 시간이 짧으면 사용자가 느끼는 전체 화면 반응도 반드시 빠를까?

    정답

    아니다. React Profiler는 선택한 React 트리의 렌더 시간과 React가 계산한 변경을 브라우저의 문서 구조(DOM) 같은 실제 실행 대상에 적용하는 커밋 단계의 문맥을 전달하며, 네트워크·브라우저 화면 그리기·장치 전체 경로를 단독으로 증명하지 않는다.

    왜 그런가

    React 렌더링 신호를 Web Vitals, 요청 트레이스와 장치 신호에 연결해야 사용자 경험 범위를 판단할 수 있다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

  5. 05React Native 화면 끊김에서 JavaScript 프레임률(초당 화면 갱신 수)만 정상이면 UI 계층도 정상이라고 결론 내릴 수 있을까?

    정답

    아니다. React Native는 작업을 실행하는 흐름인 JavaScript 스레드와 네이티브 UI 스레드의 프레임률을 구분하므로 두 계층을 따로 확인해야 한다.

    왜 그런가

    같은 사용자 증상도 JavaScript 계산, 네이티브 화면 배치·그리기나 장치 자원에서 생길 수 있다.

    관련 설명 다시 읽기
    지금 어느 정도 기억났나요?

    선택한 상태와 다음 복습일은 이 브라우저에만 저장됩니다.

출처와 검증 범위

아래 날짜는 링크를 마지막으로 열어 본 날입니다. 문서 상단의 검증일은 글의 설명과 적용 범위를 다시 확인한 날입니다.

  1. What is OpenTelemetry?OpenTelemetry · 공식 문서 · 확인 2026-08-04
  2. Observability primerOpenTelemetry · 공식 문서 · 확인 2026-08-04
  3. SignalsOpenTelemetry · 공식 문서 · 확인 2026-08-04
  4. MetricsOpenTelemetry · 공식 문서 · 확인 2026-08-04
  5. LogsOpenTelemetry · 공식 문서 · 확인 2026-08-04
  6. TracesOpenTelemetry · 공식 문서 · 확인 2026-08-04
  7. ProfilesOpenTelemetry · 공식 문서 · 확인 2026-08-04
  8. ResourcesOpenTelemetry · 공식 문서 · 확인 2026-08-04
  9. JavaScriptOpenTelemetry · 공식 문서 · 확인 2026-08-04
  10. BrowserOpenTelemetry · 공식 문서 · 확인 2026-08-04
  11. Trace Context Level 1W3C · 표준 · 확인 2026-08-04
  12. Handling sensitive dataOpenTelemetry · 공식 문서 · 확인 2026-08-04
  13. Web VitalsGoogle web.dev · 공식 문서 · 확인 2026-08-04
  14. <Profiler>React · 공식 문서 · 확인 2026-08-04
  15. Performance OverviewReact Native · 공식 문서 · 확인 2026-08-04
  16. ProfilingReact Native · 공식 문서 · 확인 2026-08-04
이 문서의 마지막까지 읽었습니다.