Dev.Chan64's Blog

홈으로 가기

CloudWatch 중심 관측 개선과 OpenTelemetry, ADOT 도입기

클라우드 환경에서 관측성을 개선할 때 가장 먼저 부딪히는 문제는 “무엇을 어디까지 로그로 남길 것인가”가 아닙니다. 더 본질적인 문제는 인프라가 책임져야 할 관측과 애플리케이션이 책임져야 할 관측을 분리하지 못할 때 운영 복잡도와 비용이 함께 커진다는 점입니다.

이번 글에서는 AWS 기반 백엔드에서 관측 체계를 다시 정리하면서, CloudWatch 중심의 인프라 관측과 OpenTelemetry 기반의 내부 추적을 어떻게 연결했는지 정리합니다.

문제 정의

초기 상태의 문제는 크게 네 가지였습니다.

여기서 중요한 판단은 “로그를 더 많이 남기자”가 아니라 “인프라와 애플리케이션의 관측 책임을 나누자”였습니다.

관측 책임 분리

이번 개선에서 세운 원칙은 단순했습니다.

이 원칙을 기준으로 보면, 인프라 계층의 요청 수나 지연 시간까지 애플리케이션 로그로 다시 만들 필요는 없습니다. 반대로 비즈니스 실패 원인이나 서비스 내부 병목은 인프라 메트릭만으로는 알 수 없습니다.

전체 아키텍처

이번에 정리한 관측 구조는 아래와 같습니다.

flowchart LR
  Client["Client"] --> APIGW["Amazon API Gateway"]
  APIGW --> ALB["Application Load Balancer"]
  ALB --> ECS["ECS Fargate Service"]

  ECS --> App["Backend Application"]
  ECS --> ADOT["ADOT Collector Sidecar"]

  App --> CWLogs["CloudWatch Logs"]
  App --> OTLP["OTLP Trace Export"]
  OTLP --> ADOT
  ADOT --> XRay["AWS X-Ray"]

  APIGW --> CW["CloudWatch Metrics"]
  ALB --> CW
  ECS --> CW
  CWLogs --> Dashboard["CloudWatch Dashboard / Logs Insights"]
  CW --> Dashboard
  XRay --> Dashboard

핵심은 두 갈래입니다.

이 구조를 택하면 CloudWatch와 X-Ray를 AWS 운영 경험 안에서 함께 사용할 수 있으면서도, 애플리케이션 계측 자체는 OpenTelemetry 표준 위에 둘 수 있습니다.

CloudWatch 중심으로 인프라 관측 보강

가장 먼저 한 일은 AWS 인프라 관측 지점을 보강하는 것이었습니다.

이 단계의 목적은 애플리케이션 로그로 인프라 상태를 대체하지 않도록 만드는 것입니다.

예를 들어 요청 수, 4xx/5xx 비율, edge latency 같은 값은 API Gateway와 ALB가 더 정확하게 알고 있습니다. 이런 값까지 애플리케이션에서 중복 집계하면 운영 관점의 기준점이 흔들립니다.

로그 정책: 기본값을 낮추고 조사 시에만 확장

관측성을 강화한다고 해서 로그를 더 많이 남기는 것은 좋은 전략이 아닙니다. CloudWatch Logs 비용은 보통 에러 로그보다 정상 요청 로그와 반복 성공 로그에서 더 크게 증가합니다.

그래서 로그 정책은 아래처럼 가져갔습니다.

이 접근의 장점은 명확합니다.

또한 반복 성공 로그와 대형 payload 로그를 제거하고, 실패 로그에는 식별자와 문맥만 구조적으로 남기도록 정리했습니다. 비용 최적화에서 중요한 것은 로그 레벨보다 로그의 형태와 빈도였습니다.

요청 상관관계와 구조화 로그

다음 단계는 요청 단위 상관관계를 맞추는 일이었습니다.

실제 운영에서는 “에러가 났다”보다 “어느 요청에서, 어떤 문맥으로, 어떤 의존성 호출 중 실패했는가”가 더 중요합니다. 이를 위해 다음 기준을 맞췄습니다.

이렇게 해두면 CloudWatch Logs Insights에서 같은 요청을 기준으로 서버 로그를 조회할 수 있고, 이후 분산 추적을 붙였을 때도 연결이 쉬워집니다.

왜 OpenTelemetry를 선택했는가

내부 추적 표준으로는 OpenTelemetry를 선택했습니다. 이유는 단순히 최신 표준이라서가 아니라, 관측 데이터를 특정 APM 제품의 SDK에 종속시키고 싶지 않았기 때문입니다.

OpenTelemetry를 선택하면 다음 이점이 있습니다.

이번 단계에서는 로그, 메트릭, 트레이스를 한 번에 다 해결하려 하지 않았습니다. 우선은 trace부터 최소 범위로 붙여 실제 요청 흐름이 보이는지 확인하는 것을 목표로 삼았습니다.

왜 ADOT Collector Sidecar를 선택했는가

OpenTelemetry를 붙인 뒤 바로 애플리케이션에서 X-Ray로 직접 전송하는 방법도 검토했습니다. 하지만 최종적으로는 ADOT Collector를 sidecar로 두는 방향이 더 적절하다고 판단했습니다.

그 이유는 세 가지였습니다.

초기 구조를 sidecar로 잡은 이유도 비슷합니다. 애플리케이션과 Collector를 같은 태스크 안에서 로컬 엔드포인트로 연결하면 시작 비용이 낮고, 추후 필요하면 별도 Collector 서비스로 확장할 수 있습니다.

OpenTelemetry PoC에서 먼저 확인한 것

전면 도입 전에 먼저 확인한 것은 “정말로 동작하는가”였습니다.

PoC에서 확인한 질문은 다음과 같았습니다.

PoC의 의미는 기능 추가보다 리스크 제거에 있습니다. 관측 도입은 보통 코드보다 런타임 환경, 패키지 해석, 배포 구조에서 더 자주 문제를 만듭니다.

구축 과정에서 얻은 교훈

1. 관측성은 로거 교체로 끝나지 않는다

실제 운영 가능한 관측성은 다음이 함께 맞물릴 때 비로소 성립합니다.

즉, 로거 라이브러리를 바꾸는 것은 시작일 뿐입니다.

2. 비용은 로그 레벨보다 로그 형태에 더 민감하다

비용을 줄이는 가장 효과적인 방법은 에러 로그를 덜 남기는 것이 아니라, 다음을 줄이는 것이었습니다.

운영성은 유지하면서 비용만 줄이려면, 실패 로그는 살리고 성공 로그를 집계하거나 샘플링하는 방식이 더 효과적입니다.

3. 인프라 관측과 애플리케이션 관측은 분리해야 한다

인프라 메트릭은 AWS가 잘합니다. 애플리케이션 내부 문맥은 애플리케이션이 잘합니다. 이 경계를 분명히 해야 중복 계측과 과도한 로그를 피할 수 있습니다.

4. OpenTelemetry의 성공 여부는 플랫폼 준비에 달려 있다

OTel은 애플리케이션 코드 몇 줄 추가로 끝나는 기능이 아닙니다. 실제 운영에서 가치를 만들려면 Collector 배치, IAM 권한, exporter 경로, 대시보드 연계까지 플랫폼이 함께 준비되어야 합니다.

현재 단계의 결과

이번 개선을 통해 얻은 결과는 다음과 같습니다.

아직 끝난 것은 아닙니다. 하지만 이제는 “로그를 더 남길 것인가”를 고민하는 단계에서 “어떤 요청 흐름이 실제로 병목을 만들고 있는가”를 볼 수 있는 단계로 이동할 준비가 되었습니다.

다음 단계

앞으로의 과제는 비교적 분명합니다.

관측성은 한 번 구축하고 끝나는 기능이 아니라, 운영 경험을 바탕으로 계속 다듬는 플랫폼 역량에 가깝습니다. 이번 작업은 그 출발점을 CloudWatch와 OpenTelemetry 위에 다시 세운 과정이었습니다.


홈으로 가기
태그: 프로젝트