1. Observability, AIOps

sangyeob·2026년 4월 12일

AIOps 스터디 첫 주차 내용으로, AIOps가 정확히 어떤 개념인지 정리하고 밀접한 관련이 있는 Observability에 대해서도 함께 정리합니다.

Observability in the AI-Native Era 의 아래 챕터 내용을 정리했습니다.

  • Chapter 1, Observability: The Art of Turning Data into Insights
  • Chapter 3, From Observability to AIOps and the Use Cases it Solves Today

Chapter1. Observability: The Art of Turning Data into Insights

1. What is observability?

Monitoring의 시작과 한계

1990년대~2000년대 초, IT 시스템을 운영한다는 건 비교적 단순했다. 서버 몇 대, 잘 알려진 애플리케이션 몇 개. CPU가 90%를 넘으면 알림을 보내고, 디스크 여유 공간이 5% 미만이면 누군가 달려가서 처리했다. SNMP, JMX 같은 표준 프로토콜로 OS와 애플리케이션 메트릭을 긁어오는 방식은 당시엔 충분했다. 서버 이름도 sql-prod-1, app-frontend-4 같이 기억하기 쉬운 이름을 붙일 수 있었다. CMDB(Configuration Management Database)에 모든 걸 수동으로 기록해도 관리가 됐다.

그런데 세상이 바뀌었다. 물리 서버 몇 대가 수백 개의 VM이 됐고, 모놀리식 앱이 수백 개의 마이크로서비스로 쪼개졌다. 여러 가용 영역에 걸쳐 파드가 배포되고, 서버리스 함수가 이벤트에 반응하며, SaaS API와 온프레미스 시스템이 혼재하는 하이브리드 환경이 됐다. 소규모 환경에서도 9개 앱이 3,304개 마이크로서비스, 10,000개 이상의 파드, 142개 호스트, 7개 글로벌 데이터센터에 걸쳐 동작하는 게 현실이다.

이 복잡도에서 단일 메트릭 + 정적 임계값 방식은 쉽게 무너질 수 있다. 수천 개의 파드에 각각 임계값을 설정하고 관리하는 건 불가능에 가깝고, 설정한다 해도 동적으로 스케일링되는 환경에서는 의미가 없다.

monitoring과 observability의 차이

GPT에 물어보면 이렇게 답한다:

"Observability는 외부 출력(로그, 메트릭, 트레이스)을 통해 시스템의 내부 상태를 이해할 수 있는 특성이다. Monitoring은 사전 정의된 메트릭과 임계값으로 시스템 헬스를 추적하는 프로세스다. Observability는 proactive하고 탐구적이며, 왜 문제가 발생했는지 이해할 수 있게 한다. Monitoring은 reactive하며, 문제가 발생한 후 알려준다."

핵심은 여기에 있다. 모니터링은 미리 알고 있는 것에 반응하고, Observability는 알지 못했던 것을 탐색할 수 있게 한다. 정적 시스템에서는 모니터링으로 충분했지만, 동적이고 복잡한 클라우드 네이티브 환경에서는 Observability가 필수다.

AIOps 1.0은 왜 실패했는가

2016년 Gartner가 AIOps를 정의하며 "ML과 빅데이터 분석으로 IT 운영을 자동화하고 강화한다"는 비전을 제시했다. 초기 목표는 여러 Observability 도구에서 오는 신호들을 상관 분석해 알림 노이즈를 줄이는 것이었다.

하지만 초기 AIOps는 약속을 지키지 못했다. 이유는 명확하다: 비표준화된, 단절된 데이터셋. 온프레미스와 클라우드에서 오는 데이터를 표준화하는 데 막대한 수작업이 필요했고, 로그·메트릭·트레이스·이벤트를 연결하는 표준도 없었다. ROI를 증명하기도 어려웠다.

AIOps 2.0 — 이제는 다르다

2026년 현재, AIOps가 원래 약속을 이행할 수 있는 조건이 갖춰졌다. 핵심은 다음 5가지 자동화 능력이다:

  • 자동 컴포넌트 검색: CMDB를 손으로 관리하는 대신, 시스템이 스스로 컴포넌트와 관계를 발견한다
  • 자동 베이스라이닝: 수십만 개의 메트릭에 임계값을 수동으로 설정하는 대신, 시스템이 스스로 "정상" 범위를 학습한다
  • 자동 이상탐지: 계절성, SLO, 컴포넌트 간 의존성을 고려해 이상 징후를 탐지한다
  • 자동 RCA: 엔드투엔드 의존성 기반으로 이상 신호들을 연결해 근본 원인을 찾는다
  • 자동 remediation: 서비스 재시작, 배포 롤백, IaC 기반 환경 조정 등 교정 액션을 트리거하고 검증한다

소방관처럼 불을 끄는 것에서, 불이 나기 전에 예방하는 것으로의 전환이다.


2. Three pillars and beyond: use cases for logs, metrics, and traces

메트릭 (Metrics)

메트릭은 서버, 프로세스, 데이터베이스, 애플리케이션 같은 entity에서 수집하는 수치 데이터다. CPU 사용률, 메모리 소비량, 서비스 응답시간, 실패율 등이 여기에 해당한다. 시간에 걸쳐 지속적으로 수집하면 시스템 동작을 추세로 파악할 수 있고, 알림 설정과 성능 최적화에 활용된다.

메트릭 수집의 주요 과제는 high cardinality, 고유한 데이터가 많아지는 문제이다다. 예를 들어 사용자 이름이나 IP 주소를 메트릭 차원으로 추가하면, 수십억 개의 고유 값이 생겨 분석이 불가능해진다. 게다가 기술 메트릭(요청 수)에 사용자 이름을 포함하면 조직 내 누구나 해당 메트릭을 통해 사용자 정보를 열람할 수 있어 개인정보 문제가 생길 수 있다.

로그 (Logs)

로그는 가장 오래된 Observability 신호다. 코드를 짜본 사람이라면 누구나 printconsole.log를 써봤을 것이다. 현대 로깅 프레임워크는 timestamp, log level(ERROR/WARNING/INFO/DEBUG), context(request ID, application ID), content(실제 메시지) 같은 표준 필드를 구조화된 형태로 출력한다. Fluentd, Logstash, OpenTelemetry 같은 에이전트가 로그를 수집하고, 파드·네임스페이스·클러스터 정보로 추가 enriching한다.

로그 수집의 가장 큰 과제는 볼륨이다. 시스템은 엄청난 양의 로그를 생성하고, 그 중 일상 운영에 유의미한 것은 일부에 불과하다. 오래된 레거시 시스템의 비구조화된 로그도 골칫거리다. 빠른 디버깅을 위해 추가한 DEBUG 로그를 지우지 않고 방치하는 것도 흔한 실수다. 로그는 중요하지만, 올바른 로깅 문화와 자동화된 검사 없이는 비용만 잡아먹는 데이터 늪이 된다.

트레이스 (Distributed Traces)

분산 트레이스는 메트릭/로그/트레이스 중 가장 최근에 제시된 개념이다. 단일 요청이 여러 서비스를 통과하는 전체 여정을 추적해, 각 구간의 지연시간과 동작을 파악할 수 있게 한다.

2000년대 초 Dynatrace, AppDynamics, New Relic 같은 APM 벤더들이 Java/.NET 바이트코드를 자동 계측하는 방식으로 도입했다. 웹 요청이 들어와서 애플리케이션 서버, 큐, 미들웨어, 백엔드 서비스, 데이터베이스를 거쳐 응답이 나가는 전체 흐름을 엔드투엔드로 볼 수 있게 됐다.

기술적 핵심은 trace context 전파다. 첫 서비스에서 생성된 고유 trace ID를 HTTP 헤더, 메시지 속성, 스레드 로컬 스토리지 등을 통해 마지막 서비스까지 전달해야 한다. 이 복잡한 전파 문제를 OpenTelemetry가 표준화했다. 각 트레이스는 고유 ID를 가지고, 웹 요청·DB 호출·메서드 실행 등 개별 작업은 span으로 표현되며, span들은 parent-child 관계로 트리를 구성한다.

trace 수집의 주요 과제는 과도한 계측, 중복 데이터, 샘플링이다. 독점 에이전트에서 OpenTelemetry 기반 개발자 직접 계측으로 전환이 늘어나면서, 이 세 가지 문제를 개발팀이 직접 고민해야 하는 상황이 됐다.

Beyond the three pillars: use cases based on events, profiling, and real users

메트릭·로그·트레이스만으로는 충분하지 않을 수 있다. 현대 Observability는 다음 신호들도 포함하는 경우가 있다.:

  • SDLC 이벤트: "내 빌드가 어디 있지?", "어떤 Git 커밋이 프로덕션을 망가뜨렸지?" — Jira, GitHub, GitLab, Argo CD, Flux 같은 DevOps 도구에서 이벤트를 수집해 아티팩트의 전체 생명주기를 추적한다. DORA 메트릭 자동화, 배포와 장애의 자동 상관분석이 가능해진다.
  • 비즈니스 이벤트: "신기능 출시 이후 매출이 늘었나?" 로그·트레이스·메트릭에서 비즈니스 지표를 추출해 실시간 보고를 가능하게 한다. 예: e-커머스의 장바구니 볼륨과 구매 완료율을 지역별로 실시간 집계.
  • 실사용자 행동(RUM): 앱 오픈, 화면 전환, 프레임 리로드 등 실제 사용자 경험 데이터
  • 코드 프로파일링: 상세한 Java/.NET 스택 트레이스
  • 보안/컴플라이언스: 취약 코드 함수·라이브러리 탐지, 규제 프레임워크 미준수 설정 탐지

주요 표준 open source

이 모든 신호를 수집하고 분석하는 방식도 오픈소스 표준으로 수렴하고 있다.

OpenTelemetry(OTel): 가장 중요한 표준. 트레이스·메트릭·로그의 생성·수집·전송을 표준화한 CNCF 프로젝트. 저장·분석 백엔드가 아닌 수집 프레임워크다. OTel Collector가 핵심 컴포넌트로, receivers → processors → exporters 구조로 데이터를 정규화·샘플링·enriching하며 여러 백엔드로 전달한다. 대부분의 상용 Observability 플랫폼이 OTLP를 지원한다.

Prometheus: 2012년 SoundCloud에서 시작, 2016년 CNCF 합류. 메트릭 특화, 고카디낼리티 시계열 DB, PromQL. HTTP endpoint scraping 방식으로 동작하며 Alertmanager와 연동해 알림을 처리한다. 사실상 클라우드 네이티브 메트릭 표준이다.

Grafana / Perses: Grafana는 Prometheus의 사실상 기본 시각화 도구로 방대한 커뮤니티 대시보드를 보유한다. 단, 대시보드 파일 포맷이 비표준이라 다른 솔루션과 호환되지 않는다. Perses는 이 문제를 해결하기 위한 벤더 중립 오픈 대시보드 스펙으로, CNCF 샌드박스 단계에 있다.


3. Observability and distributed systems

점점 복잡해지는 분산 시스템

분산시스템의 정의는, 엄밀히 말하면, 단일 서버에서만 동작하지 않는 모든 시스템이다. 이 정의는 수십 년 전부터 그대로지만, 달라진 건 규모와 동적성이다.

물리 서버 몇 대가 수백 개의 VM이 됐고, VM은 다시 수천 개의 쿠버네티스 파드와 서버리스 함수로 쪼개졌다. 배포 주기는 분기에서 주, 주에서 하루, 이제는 분 단위 자동화로 단축됐다. 컴포넌트들은 퍼블릭 클라우드, 프라이빗 클라우드, 온프레미스에 걸쳐 퍼졌다. 규모가 커질수록, 속도가 빨라질수록, 분산이 넓어질수록 — 전통적인 방식으로 이 시스템을 관리하는 건 더 이상 현실적이지 않다.

Observability로 분산 시스템 이해하기

분산 시스템을 책임지는 엔지니어라면 항상 다섯 가지 질문에 답할 수 있어야 하며, 시스템의 Observability를 잘 설정함으로써 모두 답할 수 있게 된다.:

  • Inventory: 시스템에 어떤 컴포넌트가 있나? (호스트, 노드, 파드, 서버리스 함수, DB 등)
  • Dependencies: 컴포넌트들이 어떻게 연결되고 서로 영향을 주나? (수평: 어떤 서비스가 어떤 서비스를 호출하나 / 수직: 어떤 프로세스가 어떤 호스트에서 실행되나)
  • Interface/API: consumer에 대한 분산시스템의 바운더리는 어떻게 구성되어있는가?
  • Health: 모든 컴포넌트가 예상대로 동작 중인가, 아니면 이상 징후가 있나?
  • SLA와 root cause: 엔드투엔드 크리티컬 트랜잭션에 문제가 있고, 왜 그런가?

공유 인프라와 Noisy Neighbor

분산 시스템에서 인프라는 대부분 공유된다. 같은 쿠버네티스 노드의 파드들은 CPU·메모리를 공유하고, 같은 물리 서버의 VM들은 디스크 I/O를 공유한다.

Noisy Neighbor 문제: resource limits 설정 없이 배포된 파드 하나가 CPU·메모리·네트워크·디스크를 과도하게 점유해 같은 노드의 다른 파드들을 느리게 만들거나 크래시시키는 상황. 모니터링 포인트: 특정 프로세스가 이웃 대비 10배 이상 자원을 지속적으로 사용하면 자동 알림.

Right-sizing: 반대로 지속적인 저사용률은 인프라 다운사이징의 신호다. FinOps 팀이 Observability 데이터를 활용해 자원 낭비를 줄이는 게 현대적인 접근이다.

동기·비동기 통신과 중간 레이어 관찰

분산시스템에서 Trace 수집을 통해, 엔드유저(브라우저, 모바일)부터 미들웨어, 마이크로서비스, 백엔드 DB까지 트랜잭션 전체를 따라갈 수 있다. HTTP든 메시지 큐든, trace context를 caller에서 callee로 전파하는 방식으로 동작한다.

하지만 트레이스만으로는 통신 문제를 완전히 파악하기 어려운 경우가 있다. 트레이스에는 caller의 발신 타임스탬프와 callee의 수신 타임스탬프가 찍히는데, 그 차이가 어떤 트레이스에서는 10ms, 다른 트레이스에서는 10초라면? 아예 타임아웃이 찍혀서 요청이 callee에 도달하지 못한 경우라면? 트레이스는 이 질문에 답하지 못한다.

이를 정확히 파악하기 위해서는 trace 외에 추가로, 동기·비동기 통신을 가능하게 하는 중간 레이어들 — 네트워크, 커넥션 풀, 큐 — 을 함께 관찰해야 한다.

Chapter3. From Observability to AIOps and the Use Cases it Solves Today

기존 모니터링 방식 (대시보드 + 정적 알람)으로는 부족하다.

Static Thresholds

"서버 몇 대, 예측 가능한 트래픽. CPU 90% 넘으면 알림" - Static thresholds은 정적 인프라 환경에서는 잘 작동했다. 하지만 2026년은 다르다. 파드가 수백 개이고, KEDA나 Karpenter가 실시간으로 스케일링한다. 여기에 Static thresholds을 그대로 적용하면 수만개의 불필요한 threasholds를 설정해야 한다.

KEDA나 Karpenter처럼 동적 스케일링이 작동하는 환경에서는 "정상이 무엇인지"가 실시간으로 바뀐다. 정적 임계값을 걸어봤자 의미가 없어 시스템이 스스로 정상 범위를 학습하게 해야 한다. 베이스라인을 정하는 방식은 크게 3가지이다.

  • Auto-adaptive baselining: 최근 7일 같은 rolling window 기반으로 임계값이 자동 조정된다. 시스템 동작이 점진적으로 변하면 베이스라인도 따라간다.
  • Multi-dimensional baselining: 서비스 엔드포인트별, 지역별로 각각 다른 베이스라인을 계산한다. "전체 평균"이 아니라 맥락에 맞는 기준을 적용할 수 있다.
  • Seasonal baselining: 업무 시간과 야간, 평일과 휴일처럼 반복되는 계절성 패턴을 학습한다. 매주 월요일 오전에 트래픽이 급증하는 게 "정상"이라면, 그날만 알림이 울리는 일을 막을 수 있다.

그렇다고, Static Threshold가 불필요한 것은 아니다. 여전히 API rate limit, SLA/SLO, worker thread 같은 well-defined, easily predictable한 수치의 경우 유효하게 동작할 수 있다.

Beyond CPU and memory: cloud-native golden signals

CPU, 메모리, 디스크, 네트워크는 여전히 중요한 알림 지표이다. Google SRE 핸드북의 4 golden signals(latency, traffic, errors, saturation)도 마찬가지다. SRE와 ITOps 팀은 이 지표들을 기반으로 VM 크기를 조정하고, 행업된 프로세스를 재시작하고, 로드밸런서 뒤에 트래픽을 분산시켜왔다.

그런데 Kubernetes가 이 작업들을 상당 부분 자동화했다. 자동화가 일어난 곳에서는 알림의 초점도 달라져야 한다.

  • 프로세스 재시작: Kubernetes가 알아서 한다. 그러면 "파드가 응답하지 않음"에 알림을 걸 게 아니라, "파드가 비정상적으로 자주 재시작됨"이나 "재시작이 계속 실패함"에 알림을 걸어야 한다.
  • 파드 스케일링: Kubernetes가 수직·수평 스케일링을 자동으로 처리한다. 알림은 스케일링 자체가 실패하거나 서비스 중단을 유발할 때에 집중해야 한다.
  • 클러스터 스케일링: 노드가 부족하면 cluster autoscaler가 새 노드를 프로비저닝한다. 알림은 이 프로비저닝이 제때 완료되는지, 지연이 파드 배포에 영향을 주는지에 집중해야 한다.

자동화가 레이어마다 깊어질수록, 우리가 직접 반응해야 하는 지점도 달라진다. 클라우드 네이티브 스택의 각 레이어에 맞는 새로운 golden signals를 정의할 필요가 있으며 다음과 같다.

  • Resource: network ingress/egress 볼륨 베이스라이닝. 급등·급락은 debug 로그가 켜졌거나 sampling rate가 잘못 설정됐다는 신호일 수 있다
  • Orchestration: 스케줄링·배포 지연시간. Pending 파드 증가는 클러스터가 요청을 소화 못 한다는 신호
  • Workload: 파드 실패율, 실패 원인, 재시작 실패 횟수. 워크로드 유형별로 시작 시간을 베이스라이닝
  • Platform service: queue 길이, 대기 시간, rate limit 사용률 베이스라이닝
  • Service: SLO는 모든 API에 걸지 말고 비즈니스 critical path의 엔드 컨슈머 API에만
  • Application: 동시 접속 유저 수, 트랜잭션 처리량. synthetic 테스트로 핵심 트랜잭션 가용성 검증
  • Observability: 수집 파이프라인 자체도 관찰해야 한다. 드랍 신호 비율은 0이 정상이므로 정적 임계값으로 알림 가능

Context is king: the quality of observability data

데이터가 많다고 좋은 게 아니다. AI가 제대로 동작하려면 고품질이어야 하고, 컨텍스트가 풍부해야 한다. Garbage in, garbage out — 옵저버빌리티도 예외가 아니며, 이런 데이터를 생성하려면 어떻게 해야할까?

Pets to cattle: 시맨틱 규약의 필요성

  • Pets: 개별적으로 애정을 가지고 관리하는 대상
  • Cattle: 표준화되어 대체 가능한 대상

예전엔 서버에 Joe, Sally, Hugo 같은 이름을 붙이고 각자 대시보드를 만들었다. Kubernetes 파드는 다르다. my-critical-svc라는 워크로드를 만들면 파드 이름은 my-critical-svc-1694, my-critical-svc-4352처럼 재시작할 때마다 바뀐다. 개별 엔티티를 추적하는 게 불가능하다.

이제 대시보드는 이름이 아닌 메타데이터로 필터링해야 한다. 그러려면 조직 전체가 합의한 표준화된 시맨틱 규약이 필요하다. 규약이 없으면 스케일이 불가능하다.

Enriching observability data across the stack

로그 한 줄에 API 호출 정보만 있어선 안 된다. 파드, 워크로드, 네임스페이스, 노드, 클라우드 리전까지 함께 있어야 한다. 그래야 이런 질문에 답할 수 있다: "이 에러가 특정 리전에서만 발생하는가?", "특정 Kubernetes 버전에서만 생기는가?", "특정 배포 설정과 연관이 있는가?" 아래 방법으로, observability data를 풍부하게 만들 수 있다.

인프라 태그: Terraform, Ansible 같은 IaC로 VM을 생성할 때 붙이는 태그(Environment, Owner, CostCenter 등)를 수집되는 모든 신호에 동일하게 enriching한다. 태그 하나가 여러 가지를 동시에 해결한다. Owner:SalesUSEast 태그가 붙은 로그는 해당 팀만 볼 수 있도록 접근 제어를 걸 수 있고, Environment:Dev 태그가 붙은 트레이스는 2스프린트 후 자동 삭제해 스토리지 비용을 줄일 수 있다.

배포 레이블·어노테이션: Kubernetes Deployment에 버전, 환경, 오너십 정보를 명시하면 해당 파드에서 수집되는 모든 신호에 자동으로 붙는다. 이를 통해, 버전별 응답시간·에러율 비교, 신버전이 구버전보다 실패율이 높으면 자동 알림, preproduction과 production 동작 비교 후 프로모션 결정 등이 가능해진다.

SDLC (Software Development Life Cycle) 추적

Jira, GitHub, GitLab, Argo CD, Jenkins 같은 DevOps 도구에서 이벤트를 수집해 옵저버빌리티 백엔드에 연결하면 세 가지가 가능해진다.

  • 첫째, 실시간 아티팩트 인벤토리: 어떤 서비스의 어떤 버전이 어디에, 누가 배포했는지 자동으로 파악된다. 대부분의 조직에서 이 질문에 답하는 게 생각보다 어렵다.
  • 둘째, DORA 메트릭 자동화: Git 커밋부터 배포까지의 lead time, 배포 빈도 같은 엔지니어링 효율 지표를 자동으로 집계한다.
  • 셋째, 배포-장애 자동 상관분석: "이 Git 커밋이 프로덕션을 깼나?"를 자동으로 답하고, 원인으로 지목된 변경사항에 대해 롤백 PR을 자동으로 연다. 성숙한 조직이 자동 remediation의 표준으로 채택하는 방식이다.

DevOps 도구 자체도 관찰해야 한다

"왜 Jira가 느리지?", "왜 빌드 파이프라인이 안 돌지?" — 이 문제들은 대개 사람들이 불평하기 시작하고 나서야 발견된다. 원인은 단순한 경우가 많다. Jenkins 파이프라인이 공유 인프라 문제로 느려졌거나, 잘못 설정된 MCP 서버가 GitHub API를 과도하게 호출해 rate limit에 걸렸거나. 하지만 자동으로 감지되지 않으니 피해가 커진 후에야 인지한다.

Jira, GitHub, Argo, Harbor 같은 도구에도 동일한 옵저버빌리티와 알림을 설정해야 한다. OpenTelemetry의 확산으로 이런 도구들도 점점 OTel을 지원하고 있다. 엔지니어를 지원하는 도구가 멈추는 건, 비즈니스 서비스가 멈추는 것만큼 치명적이다.

얼마나 enriching하고, 얼마나 샘플링할까

데이터는 생성되는 곳과 최대한 가깝게 enriching하는 게 가장 효율적이다. 벤더 에이전트는 수집 시점에 자동으로 enriching하고, OTel Collector는 processor를 통해 파이프라인에서 규칙 기반으로 enriching한다.

그렇다고 모든 데이터를 다 저장할 필요는 없다. 트랜잭션의 99.9%가 성공한다면, 그 99.9%를 전부 상세 저장하는 건 낭비다. 샘플링 전략 세 가지:

  • Probabilistic: 일정 비율(예: 5%)만 저장. 간단하지만 드문 실패 케이스를 놓칠 수 있다
  • Adaptive: 트래픽량에 따라 샘플링 비율을 자동 조정. 피크 타임에 과도한 데이터 수집을 방지한다
  • Rule-based: 특정 URL, 느린 요청, 특정 IP 범위 등 규칙 기반으로 선택. 설정과 유지관리 비용이 따른다

샘플링 결정 시점도 중요하다. Head-based는 트레이스 시작 시점에 결정해 가볍지만, 결과를 모르는 상태에서 결정한다. Tail-based는 모든 span이 수집된 후 결정해 정확하지만 메모리를 많이 쓴다. 일반적으로 head-based로 시작하고, 크리티컬 트랜잭션이나 규제·컴플라이언스 요건이 있는 케이스에만 tail-based를 조합하는 게 실용적이다.

AIOps: reducing the noise with anomaly and root cause detection

다른 작업을 하고 있는데 Slack으로 이런 메시지가 온다:

"Argo CD sync(PR-342)가 payment 서비스의 실패율을 높이고 있습니다. frontend 서비스에서 java.lang.abcdException이 발생해 HTTP 500 에러가 사용자에게 전달되고 있습니다. PR을 롤백하는 것을 권장합니다."

공상과학처럼 들리지만 지금 이미 가능하다. context-enriched observability 데이터, 자동 베이스라인과 ML, 그리고 LLM의 조합이다. 이게 어떻게 동작하는지 분해해보자.

Step 1: 이상 이벤트 탐지

출발점은 모든 레이어에서 이상 동작을 감지하는 것이다. 임계값이나 베이스라인이 깨지는 순간, 특정 컴포넌트에서 이상 이벤트가 발생했다고 볼 수 있다.

예를 들어 유저 로그인 API가 평소보다 느려졌다고 하자. 이 API는 Kubernetes 클러스터에서 실행 중이고, 큐와 DB에 의존한다. 헬스 히트맵으로 시각화하면 패턴이 보인다 — DB 쿼리 시간이 느려지고 1분 후 business API가 degraded 상태가 되고, 그 후 application 레이어까지 실패한다. 인간의 눈으로도 패턴을 읽을 수 있다.

하지만 이상탐지만으로는 부족하다. 이 단순한 예시에도 이미 놓친 게 많다.

  • Scope: 현실에서는 수백 개의 앱, 수천 개의 API 엔드포인트가 있다. 비즈니스 영향이 없는 이상에까지 알림을 남발하면 노이즈만 쌓인다.
  • Dependencies: "DB가 느려서 business API가 느려졌다"고 가정했지만, 반대일 수도 있다. business API가 DB에 너무 많은 데이터를 요청했고, 그로 인해 메모리 압박 → GC 증가 → 성능 저하로 이어진 것일 수도 있다. 의존성 정보 없이는 인과관계를 알 수 없다.
  • Shared resources: 같은 클러스터의 다른 서비스가 네트워크 대역폭을 독점하고 있진 않은가? 공유 인프라의 noisy neighbor도 원인 후보다.
  • External events: resource limits 설정이 변경됐거나, 새 커밋이 배포됐을 수도 있다. SDLC 이벤트를 함께 보지 않으면 놓친다.

이상 탐지만으로는 추측밖에 할 수 없다. 의존성, 공유 자원, 외부 이벤트까지 포함한 context-enriched 데이터가 있어야 진짜 원인을 찾을 수 있다.

Step 2: 점들을 연결해 root cause 찾기

컨텍스트가 갖춰지면 의존성 모델을 따라 네 가지 방향으로 원인을 추적한다.

  • Horizontal (call chain): 어떤 서비스가 어떤 서비스를 호출하고, callee의 응답(지연, 실패율, 처리량)이 caller에 어떤 영향을 주는가. DB 쿼리 시간이나 반환 row 수가 business API 성능에 어떻게 이어지는지 파악할 수 있다.
  • Vertical (runs on): 어떤 컴포넌트가 어떤 컴포넌트 위에서 실행되는가. Java 런타임의 GC가 business API 성능에 미치는 영향, 그 GC가 orchestration 레이어의 resource limits에 의해 어떻게 영향받는지를 추적할 수 있다.
  • Network connectivity: 서비스 간 네트워크 품질이 point-to-point 연결에 영향을 주는가.
  • Cross-stack: 우리 시스템 바깥의 다른 앱이나 스택도 봐야 한다. DB가 느린 게 우리 business API 때문이 아니라, 스케줄 기반 배치 잡을 돌리는 다른 reporting 서비스가 DB를 과부하시키고 있는 것일 수 있다. 이 시각이 없으면 "DB가 문제"라는 잘못된 결론을 내린다.

네 가지를 모두 연결하면 비로소 진짜 root cause에 도달한다 — "배치 잡이 DB를 과부하시켜 business API가 느려지고, 엔드유저에게 영향이 갔다."

Step 3: 증거를 설명 가능하게 만들기

root cause를 찾았다고 끝이 아니다. 의존성 다이어그램을 그릴 수 있는 전문가만 이해한다면 의미가 없다.

Step 2의 모든 과정은 자동화할 수 있다. 많은 옵저버빌리티 플랫폼이 이미 메타데이터를 기반으로 데이터를 연결하고, 의존성 트리를 따라 자동으로 원인을 추적한다. 속도는 데이터 품질과 저장 구조에 달려 있다. 품질이 좋을수록 빠르고 정확하다.

마지막 단계는 LLM이다. 수집된 증거 — 이상 목록, 의존성 정보, 관련 외부 이벤트 — 를 LLM에 넣으면 세 가지를 인간이 이해할 수 있는 언어로 돌려준다:

  • Finding: 영향이 무엇인가 (1,070명의 사용자가 영향받고 있다)
  • Root cause: 왜 그런가 (Argo CD sync가 높은 실패율을 유발했다)
  • Recommendation: 무엇을 해야 하는가 (PR-342를 롤백하라)

데이터 품질이 좋을수록, 의존성 정보가 풍부할수록, 설명도 더 정확해진다. Context is king이 단순한 구호가 아닌 이유가 여기에 있다.

0개의 댓글