# 옵저버빌리티 입문

> 옵저버빌리티의 핵심 개념

---

Site [llms.txt](/ko/llms.txt)

---

## 옵저버빌리티란? {#what-is-observability}

옵저버빌리티(observability)를 통해 시스템의 내부 동작을 알지 못해도 시스템에
질문을 던져 외부에서 시스템을 이해할 수 있다. 또한 새롭게 발생한 문제, 즉
"문제가 존재하는지조차 알지 못했던 문제(unknown unknowns)"를 쉽게 진단하고
해결할 수 있다. "왜 이런 일이 발생했는가?"라는 질문에 답하는 데에도 도움이 된다.

시스템에 이러한 질문을 하려면 애플리케이션이 충분히 계측되어 있어야 한다. 즉,
애플리케이션 코드가 [트레이스](/docs/concepts/signals/traces/),
[메트릭](/docs/concepts/signals/metrics/),
[로그](/docs/concepts/signals/logs/)와 같은 [시그널](/docs/concepts/signals/)을
생성해야 한다. 문제 해결에 필요한 모든 정보를 이미 확보하고 있어 개발자가 계측을
추가할 필요가 없다면, 애플리케이션이 충분히 계측된 것이다.

[오픈텔레메트리(OpenTelemetry)](/docs/what-is-opentelemetry/)는 시스템에
옵저버빌리티를 제공하기 위해 애플리케이션 코드를 계측하는 메커니즘이다.

## 신뢰성과 메트릭 {#reliability-and-metrics}

**텔레메트리(telemetry)** 는 시스템과 그 동작에서 생성되는 데이터를 의미한다.
데이터는 [트레이스](/docs/concepts/signals/traces/),
[메트릭](/docs/concepts/signals/metrics/), [로그](/docs/concepts/signals/logs/)
형태로 제공될 수 있다.

**신뢰성(reliability)** 은 "서비스가 사용자가 기대하는 대로 동작하는가?"라는
질문에 답한다. 시스템이 100% 가동 중이더라도 사용자가 검은색 신발 한 켤레를
장바구니에 추가하기 위해 "장바구니에 추가"를 클릭했을 때 검은색 신발이 추가되지
않는 경우가 있다면, 그 시스템은 **신뢰하기 어려운** 시스템일 수 있다.

**메트릭(metrics)** 은 인프라 또는 애플리케이션에 관한 수치 데이터를 일정 기간에
걸쳐 집계한 값이다. 시스템 오류율, CPU 사용률, 특정 서비스의 요청률 등을 예로 들
수 있다. 메트릭과 오픈텔레메트리의 관계를 자세히 알아보려면
[메트릭](/docs/concepts/signals/metrics/)을 참고한다.

**SLI**, 즉 서비스 수준 지표(Service Level Indicator)는 서비스 동작을 측정한
값을 나타낸다. 좋은 SLI는 사용자의 관점에서 서비스를 측정한다. 웹 페이지가
로드되는 속도를 SLI의 예로 들 수 있다.

**SLO**, 즉 서비스 수준 목표(Service Level Objective)는 신뢰성을 조직이나 다른
팀에 전달하는 수단이다. 하나 이상의 SLI를 비즈니스 가치에 연결하여 이를
달성한다.

## 분산 트레이싱 이해하기 {#understanding-distributed-tracing}

분산 트레이싱을 사용하면 복잡한 분산 시스템에서 요청이 전파되는 과정을 관찰할 수
있다. 분산 트레이싱은 애플리케이션이나 시스템의 상태를 더 명확히 보여주고,
로컬에서 재현하기 어려운 동작을 디버깅할 수 있게 한다. 비결정적인 문제가 자주
발생하거나 로컬에서 재현하기에 너무 복잡한 분산 시스템에서는 분산 트레이싱이
필수적이다.

분산 트레이싱을 이해하려면 구성 요소인 로그, 스팬, 트레이스의 역할을 이해해야
한다.

### 로그 {#logs}

**로그(log)** 는 서비스나 기타 구성 요소에서 생성되는 타임스탬프(timestamp)가
포함된 메시지이다. [트레이스](#distributed-traces)와 달리 로그가 특정 사용자
요청이나 트랜잭션과 반드시 연관되는 것은 아니다. 소프트웨어의 거의 모든 곳에서
로그를 찾을 수 있다. 과거에는 개발자와 운영자가 시스템의 동작을 이해하기 위해
로그에 크게 의존했다.

로그 예시:

```text
I, [2021-02-23T13:26:23.505892 #22473]  INFO -- : [6459ffe1-ea53-4044-aaa3-bf902868f730] Started GET "/" for ::1 at 2021-02-23 13:26:23 -0800
```

로그는 일반적으로 호출된 위치와 같은 컨텍스트 정보가 부족하므로 코드 실행을
추적하는 데 충분하지 않다.

로그가 [스팬](#spans)의 일부로 포함되거나 트레이스 및 스팬과 연관되면 훨씬 더
유용해진다.

로그와 오픈텔레메트리의 관계를 자세히 알아보려면
[로그](/docs/concepts/signals/logs/)를 참고한다.

### 스팬 {#spans}

**스팬(span)** 은 단일 작업 혹은 실행 단위를 나타낸다. 스팬은 요청이 수행하는
특정 작업을 추적하여 해당 작업이 실행되는 동안 어떤 일이 일어났는지 보여준다.

스팬에는 이름, 시간 관련 데이터,
[구조화된 로그 메시지](/docs/concepts/signals/traces/#span-events), 추적하는
작업에 대한 정보를 제공하는
[기타 메타데이터(즉, 속성)](/docs/concepts/signals/traces/#attributes)가
포함된다.

#### 스팬 속성 {#span-attributes}

스팬 속성은 스팬에 연결된 메타데이터이다.

다음 표는 스팬 속성의 예시다.

| 키                          | 값                                                                                 |
| :-------------------------- | :--------------------------------------------------------------------------------- |
| `http.request.method`       | `"GET"`                                                                            |
| `network.protocol.version`  | `"1.1"`                                                                            |
| `url.path`                  | `"/webshop/articles/4"`                                                            |
| `url.query`                 | `"?s=1"`                                                                           |
| `server.address`            | `"example.com"`                                                                    |
| `server.port`               | `8080`                                                                             |
| `url.scheme`                | `"https"`                                                                          |
| `http.route`                | `"/webshop/articles/:article_id"`                                                  |
| `http.response.status_code` | `200`                                                                              |
| `client.address`            | `"192.0.2.4"`                                                                      |
| `client.socket.address`     | `"192.0.2.5"` (클라이언트가 프록시를 통해 연결)                                    |
| `user_agent.original`       | `"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0"` |

스팬과 오픈텔레메트리의 관계를 자세히 알아보려면
[스팬](/docs/concepts/signals/traces/#spans)을 참고한다.

### 분산 트레이스 {#distributed-traces}

**분산 트레이스(distributed trace)** 는 흔히 **트레이스(trace)** 라고 불리며,
단일 요청(애플리케이션이나 최종 사용자가 보낸 요청)이 마이크로서비스 또는
서버리스 애플리케이션과 같은 아키텍처의 여러 서비스를 거쳐 전파되는 경로를
기록한다.

트레이스는 하나 이상의 스팬으로 구성된다. 첫 번째 스팬은 루트 스팬이다. 각 루트
스팬은 요청의 시작부터 끝을 나타낸다. 부모 스팬 아래의 하위 스팬은 요청 중
발생한 일(또는 요청을 구성하는 단계)에 대한 더 자세한 컨텍스트를 제공한다.

예를 들어 사용자가 웹 페이지를 로드하면 초기 HTTP 요청은 API 게이트웨이, 백엔드
서비스, 데이터베이스를 거칠 수 있다. 각 단계는 하나의 스팬으로 표현되며, 이들이
함께 요청의 전체 처리 경로를 보여주는 단일 트레이스를 구성한다.

트레이싱 없이는 분산 시스템의 성능 문제에 대한 근본 원인을 찾기 어려울 수 있다.
트레이싱은 요청이 분산 시스템을 흐르는 동안 내부에서 발생하는 일을 작은 단위로
나누어 보여주므로 분산 시스템을 디버깅하고 이해하는 데 따르는 부담을 줄여준다.

많은 옵저버빌리티 백엔드는 다음과 같은 워터폴 다이어그램으로 트레이스를
시각화한다.

![트레이스 예시](/img/waterfall-trace.svg '트레이스 워터폴 다이어그램')

워터폴 다이어그램은 루트 스팬과 하위 스팬 사이의 부모-자식 관계를 보여준다.
스팬이 다른 스팬을 감싸면 중첩 관계도 나타낸다.

트레이스와 오픈텔레메트리의 관계를 자세히 알아보려면
[트레이스](/docs/concepts/signals/traces/)를 참고한다.
