grep

DevOps

모니터링에서 옵저버빌리티로 더 나은 시스템 이해를 위한 여정

양현진Cople(코플)/공통플랫폼개발팀여기어때

2025년 8월 7일

원문에서 보기 ↗

안녕하세요. 여기어때컴퍼니 공통플랫폼개발팀 코플 입니다.

여기어때는 오늘도 빠르게 성장하고 있습니다. 서비스 MAU(월간 활성 사용자)는 420만 이상에 도달 했으며 많은 사용자가 서비스를 사용하는 만큼 시스템의 복잡도는 더욱 높아지고 있습니다.

서비스 성장에 발 맞추어 품질과 안정성을 확보하기 위해서 모니터링 체계를 세우고 지속적으로 관리하기 위한 노력을 기울이고 있습니다. 하지만 더 다양한 측면의 문제를 발견하고 해결하기 위해서 옵저버빌리티의 정의와 필요성을 소개하고자 합니다. 옵저버빌리티는 단순한 모니터링 도구의 업그레이드가 아닌 시스템 파악하는 방식의 근본적인 변화를 의미합니다.

새벽 3시의 알림 메시지

새벽 3시. 잠에서 깨어나게 만든 슬랙 모니터링 알림에는 “API 에러카운트가 30개를 초과했다”는 경고였습니다.

핀포인트에서 확인해보니 서비스 API에서 에러 카운트가 급증했지만 왜 에러가 발생했는지는 명확하지 않습니다. 소강 상태가 되었고 다시 잠들려고 하는데 이번엔 CPU 사용률 경고가 울립니다. 여러 모니터링 도구에서 조각조각 정보를 확인하며 아침은 밝아옵니다. 이런 유사한 경험은 시스템을 운영하면서 종종 겪게 됩니다.

이미 APM 도구나 모니터링 시스템을 사용하고 있지만 여전히 이런 일이 흔히 일어납니다. 개별 도구에서 제공하는 정보들은 유용하지만 전체적인 그림을 그리기 위해서는 여러 도구를 오가며 정보의 퍼즐을 맞춰야합니다. 마치 여러 개의 현미경으로 각각 다른 부분을 보면서 코끼리 전체를 파악하려는 것과 같습니다.

모니터링 도구 간 연결의 부재

실제로 장애 상황에서는 이런 일이 벌어집니다. 핀포인트에서 트레이스를 확인해보니 특정 API에서 에러 카운트가 급증했다고 나오면 관련된 API를 찾아서 문제 상황을 파악하기 시작합니다. 특정 API에서 에러가 발생했다고 해서 반드시 해당 서버나 서비스의 자체의 문제인 것은 아닙니다. 연동된 서비스의 문제일수도 있고 특정 인프라의 문제일 수도 있습니다.

CPU와 Memory 메트릭은 그라파나에서 확인하고 키바나에서 에러 로그를 검색하고 필요하다면 직접 인스턴스나 파드에 접속해서 문제를 파악하거나 ArgoCD, Rancher 등을 활용하는 등 다양한 방식으로 다양한 분석을 진행합니다. 개별 도구들은 훌륭하지만 이들 사이의 연결고리를 찾는 것은 전적으로 개발자의 몫입니다.

가장 큰 문제는 각 도구가 서로 다른 시간 축과 데이터 형식을 사용한다는 점입니다. 핀포인트는 5분 단위로 트레이스를 수집한다면 그라파나는 3분 간격으로 메트릭을 표시하고 키바나의 로그는 실시간이지만 수집되는 시간대 설정이 다를 수 있습니다. 게다가 각 도구마다 필터링 방식도 다릅니다.

만약 새벽 3:32분에 문제가 발생했다고 해서 모든 모니터링 도구에서 3:32분 데이터를 조회한다고 해도 동일한 시간대의 데이터를 확인할수 있는 것은 아닙니다.

추론에 의존하는 장애 대응

결국 우리는 정보의 퍼즐 피스를 모두 가지고 있지만 전체 그림이 무엇인지 맞춰야 하는 상황에 놓이게 됩니다. APM은 “에러 카운트가 증가했다”고 말하고, 인프라 모니터링은 “CPU는 정상이다”라고 하고, 로그는 “특정 시간에 에러가 발생했다”고 제각각 다른 방식으로 정보를 전달합니다. 이 모든 정보를 연결해서 “실제로 무엇이 일어났는지” 파악하는 것은 온전히 엔지니어의 추론과 경험에 의존하게 됩니다.

더욱 문제가 되는 것은 이런 상황에서 결국 오랜 경험을 가진 시니어 개발자나 해당 시스템을 오래 담당한 엔지니어에게 의존하게 된다는 점입니다. 신입 개발자나 입사 한지 얼마되지 않는 엔지니어는 이 모든 도구들 사이의 연관관계를 파악하기까지 일정 시간이 소요됩니다. 그 과정에서 장애 해결은 더욱 지연되고 장애의 여파는 커지게 됩니다.

사후 분석의 어려움

장애를 해결했다고 끝이 아닙니다.

예를 들어 여기어때에서는 장애가 발생하게 되면 5Why 방식을 통해서 다시 한번 장애에 대해서 분석을 진행합니다. “왜 API 에러가 발생했는가?”, “그 시점에 CPU는 어땠지? Memory?”, “왜 그때 리소스 사용량이 높았는가?”, “배포는 언제했는가?” 와 같은 여러 질문을 거쳐 장애에 대한 근본적인 원인을 찾고 분석을 진행하게 됩니다.

이때 시간이 지나면서 일부 도구의 데이터는 삭제되거나 접근이 어려워진다는 점입니다. 로그 보관 기간이 서로 다르고, 메트릭 수집 주기도 달라서 완전한 재현이 불가능한 경우가 발생할 수 있습니다.

결국 명확한 근본 원인을 찾지 못해 “그때 뭔가 문제가 있었던 것 같은데…” 라는 애매한 결론을 내리거나, 더 나쁜 경우에는 “누군가의 실수”라고 결론짓게 되는 경우가 발생하게 됩니다. 실제 문제의 근원적인 부분은 시스템적인 문제임에도 불구하고 개인의 책임으로 돌리는 Blame Culture 가 형성되기 쉬운 환경이 되는 것입니다.

모니터링의 한계: 나무만 보고 숲을 놓치다.

1. 메트릭의 함정

기존 모니터링 시스템은 주로 메트릭(Metrics) 위주로 구성됩니다. CPU, Memory, 디스크 I/O 같은 인프라 지표들을 수집하고 임계치를 설정해서 경고를 보내는 방식입니다.

# 모니터링 경고 시나리오
CPU Usage: 85% (Warning)
Memory Usage: 92% (Critical)
Disk I/O: 234 IOPS (Normal)

하지만 이런 지표들만으로는 왜 문제가 발생했는지 알기 어렵습니다. 예를 들어, CPU 사용률이 85%라는 동일한 지표라도 그 원인은 천차만별입니다. 갑작스런 트래픽 증가일 수도 있고, 무한 루프가 발생한 코드일 수도 있고, 데이터베이스 쿼리 최적화 문제일 수도 있고, 가비지 컬렉션이 과도하게 발생하는 것일 수도 있습니다. 같은 숫자지만 해결 방법은 완전히 다릅니다. 단순한 시스템 메트릭 지표만으로는 근본적으로는 어떤 문제인지 파악하기 어렵습니다.

2. 사일로(Silo) 현상

각 팀이 서로 다른 모니터링 도구를 사용합니다. SRE팀은 그라파나와 프로메테우스로 서버 리소스를 모니터링하고, 개발팀은 핀포인트로 애플리케이션 성능을 추적하고, 로그 분석은 키바나를 활용합니다. 문제가 발생하면 각자 자신의 도구에서 확인하고 전체적인 상황을 파악 위해서는 여러 도구를 오가며 정보를 수집해야 합니다. 실제로 상황에서는 이런 대화가 오갑니다.

각 팀은 영역에서 시스템은 “정상”이라고 판단할만한 지표가 분명합니다. 하지만 실제 서비스에서의 발생하는 문제를 파악하기에는 각 지표에 대한 연관 관계를 추론하기란 무척 어려운일이고 그로 인해서 더 많은 시간을 소요하게 합니다.

3. 사후 대응의 한계

전통적인 모니터링은 수동적으로 수집되는 모니터링 환경에 대응하게 됩니다. 문제가 발생한 후에 알림을 받고 원인을 찾기 시작합니다.

예를 들어 “Memory 사용률 85% 초과” 알림이 오면 서버에 접속해서 프로세스를 확인하고 “API 응답시간 5초 초과” 알림이 오면 어떤 API인지 찾아보고 “디스크 사용률 90%” 알림이 오면 어느 디렉토리가 용량을 차지하는지 조사해야 합니다.

단순한 오류나 임계치 문제를 넘어서 연쇄 장애 상황에서는 문제가 커지게됩니다. 데이터베이스 응답이 느려지면 API 타임아웃이 발생하고 이로 인해 애플리케이션에서 관리하던 큐가 쌓이고 결국 Memory 부족으로 이어질 수 있습니다. 하지만 모니터링 알림은 “Memory 부족”, “API 타임아웃”, “큐 적체”를 각각 독립적인 문제로 보고하기 때문에 근본 원인인 데이터베이스 성능 저하를 파악하기까지 일정 시간이 소요됩니다.

마이크로서비스 환경에서는 이 문제가 더욱 복잡해집니다. 예를 들어 사용자가 특정 시설의 객실을 선택 → 예약 → 결제 → (예약 확인) 알림 서비스를 거쳐가는 상황에서 어느 지점에서 문제가 발생했는지 각 서비스의 마이크로 서비스 단위로 확인을 하게되면 각 서비스에 이해를 가지고 있는 개발자가 없으면 문제 해결에 어려움이 발생하게 됩니다. 각 서비스마다 별도의 로그와 메트릭이 있고 서비스 간의 의존성과 호출 관계를 추적하기 위해서는 트레이스 추적이 안되는 한계에 도달할수 있습니다.

마치 대형 아파트 단지에서 화재 경보기가 울렸는데 어느 동 몇 층에서 불이 났는지도 모르는 채로 일단 모든 곳을 뛰어다니며 찾아야 하는 것과 같습니다. 이미 피해가 발생한 상태에서 그것도 어디서 시작된 문제인지도 확실하지 않은 상황에서 수습에 나서는 격입니다.

옵저버빌리티: 시스템의 전체 모습을 파악하다.

옵저버빌리티(Observability)는 제어 이론에서 나온 개념으로, 시스템의 외부 출력만을 관찰해서 내부 상태를 얼마나 정확하게 추론할 수 있는지를 나타내는 척도입니다.

소프트웨어 시스템에서 옵저버빌리티는 단순히 “시스템이 잘 돌아가고 있나?”를 확인하는 것을 넘어서 “사용자가 주문 버튼을 클릭했을 때 결제 서비스에서 3초 지연이 발생한 이유가 데이터베이스 커넥션 풀 부족 때문이었다”와 같이 구체적인 인과관계를 파악할 수 있는 능력을 의미합니다.

즉, 시스템이 생성하는 로그, 메트릭, 트레이스 데이터를 통해 복잡한 분산 시스템 내부에서 일어나는 모든 상호작용과 데이터 흐름을 실시간으로 추적하고 이해할 수 있게 하는 것입니다.

모니터링 vs 옵저버빌리티

기존의 모니터링과 옵저버빌리티는 근본적으로 다른 접근 방식을 가집니다.

블랙박스 vs 화이트박스

옵저버빌리티의 세 기둥

옵저버빌리티는 ‘세 기둥(Three Pillars)’이라고 불리는 세 가지 핵심 데이터 유형으로 구성됩니다. 이 세 요소가 서로 연결되고 상호보완될 때 비로소 시스템의 전체적인 모습을 파악할 수 있습니다.

1. 메트릭(Metrics)

시간에 따라 변화하는 숫자 데이터의 시계열입니다. 전통적인 모니터링에서 사용하던 CPU, Memory 사용률과 같은 기본 지표를 넘어서 비즈니스 맥락과 기술적 세부사항이 풍부하게 포함된 고차원 메트릭을 의미합니다.

단순히 “HTTP 요청 수”를 기록하는 것이 아니라 서비스명, 엔드포인트, HTTP 메소드, 응답 상태, 사용자 유형, 플랫폼 등의 다양한 차원(Dimension)을 함께 수집합니다. 예를 들어 “회원들이 모바일에서 /users API 호출 시 에러율이 평소보다 3배 높다”와 같은 구체적인 패턴을 파악할 수 있게 해줍니다.

특정 메트릭을 수집한다고 한다면 다음과 같은 다양한 관점으로 데이터를 분석할 수 있습니다.

int requestCount = 1000;
// Spring Boot + Micrometer
@RestController
public class UserController {
    
    private final Counter requestCounter;
    
    public UserController(MeterRegistry meterRegistry) {
        this.requestCounter = Counter.builder("http_requests_total")
                .tag("service", "user-api")
                .tag("endpoint", "/users")
                .tag("method", "GET")
                .register(meterRegistry);
    }
    
    @GetMapping("/users")
    public ResponseEntity<List<User>> getUsers(HttpServletRequest request) {
        // 비즈니스 로직...
        List<User> users = userService.getUsers();
        
        requestCounter.increment(
            Tags.of(
                "status_code", "200",
                "platform", getPlatformFromRequest(request),
                "user_type", getCurrentUserType()
            )
        );
        
        return ResponseEntity.ok(users);
    }
}

예제의 수집된 메트릭을 통해 다음과 같은 분석을 진행할 수 있게 됩니다.

# 플랫폼별 요청 패턴 분석
sum(rate(http_requests_total[5m])) by (platform)

# 사용자 유형별 에러율 비교
sum(rate(http_requests_total{status_code=~"5.."}[5m])) by (user_type) 
/ sum(rate(http_requests_total[5m])) by (user_type)
# 특정 조건의 복합 분석
sum(rate(http_requests_total{platform="mobile", user_type="elite_plus"}[5m]))

단순한 숫자 하나가 아니라 “회원들이 모바일에서 평소보다 50% 더 많이 API를 호출하고 있다”거나 “모바일 앱에서 오는 요청의 에러율이 웹보다 3배 높다” 등과 같이 단순히 시스템만을 모니터링하는 것이 아닌 서비스 비즈니스의 구체적인 인사이트를 얻을 수 있게 되는 것입니다.

2. 로그(Logs)

애플리케이션과 시스템에서 발생하는 이벤트들을 텍스트 형태로 기록한 데이터입니다. 전통적인 로그가 단순히 텍스트 파일에 “2025–08–04 09:00:00 ERROR 예약 처리 실패”와 같이 저장되는 것과 달리 옵저버빌리티에서의 로그는 구조화된 JSON 형태로 풍부한 컨텍스트 정보를 포함합니다.

각 로그 이벤트는 trace ID, span ID와 같은 추적 식별자를 포함하여 메트릭 및 트레이스 데이터와 연결될 수 있으며, 이를 통해 “특정 사용자의 특정 요청에서 발생한 문제”를 정확히 추적할 수 있습니다.

실제 수집되는 구조화된 로그는 다음과 같은 형태입니다:

{
  "timestamp": "1754265600",
  "severity_text": "ERROR",
  "message": "예약 처리 실패",
  "trace_id": "abc123def456",
  "span_id": "span789",
  "user_id": "user_12345",
  "platform": "mobile",
  "user_type": "elite_plus",
  "error_type": "room_not_available",
  "service_name": "reservation-api",
}

이를 통해 trace_id: abc123def456 인 요청에 대한 모든 로그를 한번에 조회할 수도 있게 되고, 모바일에서 접속한 회원의 예약 처리 시 발생한 모든 로그를 한 번에 조회할 수 있으며, 해당 요청과 연관된 메트릭과 트레이스 정보도 함께 분석할 수 있습니다. 다양한 컨텍스트를 통해서 다각도로 로그를 분석할 수도 있게 되는 것입니다.

3. 트레이스(Traces)

분산 시스템에서 하나의 사용자 요청이 여러 마이크로서비스를 거쳐가는 전체 경로와 각 단계에서의 처리 시간, 성공/실패 여부를 추적하는 데이터입니다. 마이크로서비스 아키텍처에서는 하나의 비즈니스 트랜잭션이 수십 개의 서비스 호출로 이루어질 수 있기 때문에 필수적입니다. 예를 들어, 사용자가 “숙박 예약”을 하는 과정은 다음과 같은 복잡한 서비스 간 상호작용으로 이루어집니다.

일반적인 예시

각 span은 서비스 호출의 시작/종료 시간, 성공/실패 상태, 에러 정보 등을 포함하며 모든 span들이 동일한 trace ID로 연결되어 전체 요청의 생명주기를 완전히 추적할 수 있습니다.

전체 예약 응답시간이 2초가 걸렸을 때 트레이스 분석을 통해 “결제 서비스 → PG사 API 호출”이 1.2초 를 차지하는 병목 지점임을 즉시 파악할 수 있습니다. 또한 같은 trace ID(abc123)를 가진 모든 로그와 메트릭을 연결해서 볼 수 있어 “특정 PG사에서만 평균 1.5초 지연”, “오후 2–3시 사이에만 지연 발생” 같은 구체적인 패턴도 분석할 수 있게 됩니다.

실무에서 느끼는 차이

옵저버빌리티 도입 전후의 가장 큰 차이는 문제 해결 속도와 정확성입니다.

기존 모니터링에서는 장애 발생 시 여러 도구를 순차적으로 확인하며 각각의 정보를 머릿속으로 연결해야 했습니다. 핀포인트에서 어떤 API에 문제가 있는지 확인하고 그라파나에서 인프라 상태를 점검하고 키바나에서 관련 로그를 찾아가며 하나씩 퍼즐을 맞춰가는 과정이었습니다. 이 과정에서 각 팀이 자신의 영역만 확인하다 보니 전체적인 그림을 파악하기 어렵습니다.

반면 옵저버빌리티에서는 하나의 trace ID를 통해 문제가 된 요청의 전체 처리 과정을 즉시 추적할 수 있습니다. 어떤 사용자가 언제 어떤 요청을 했고 그 요청이 시스템을 거쳐가면서 어느 지점에서 문제가 발생했는지를 실시간으로 파악할 수 있습니다. 더 중요한 것은 같은 패턴의 다른 실패 요청들과의 공통점을 자동으로 분석해서 근본 원인을 빠르게 찾을 수 있다는 점입니다.

조직 전반의 경험 변화

가장 체감할 수 있는 변화는 추측에서 확신으로의 전환입니다. 과거에는 “아마도 이런 문제일 것 같다”라고 추정하며 여러 가능성을 탐색해야 했다면 옵저버빌리티의 데이터가 명확한 답을 제시해주게 됩니다.

또한 장애 대응이 개인의 경험과 역량에 크게 의존하지 않게 됩니다. 신입 개발자라도 시스템이 제공하는 트레이스와 연관 데이터를 통해 숙련된 개발자와 비슷한 수준으로 문제를 분석할 수 있습니다. 이는 팀 전체의 대응 능력을 향상시키고 특정 개인에게만 의존하는 위험을 줄여줍니다.

SRE팀의 경험도 크게 달라집니다. 기존에는 개발팀에서 “서버에 문제가 있는 것 같다”고 요청하면 일단 요청 받은 서버 그룹군을 점검해야 했지만, 이제는 구체적인 trace ID와 함께 “이 요청에서 어떤 서비스에 문제가 있는지” 정확한 정보를 받을 수 있어 훨씬 효율적으로 대응할 수 있습니다.

비즈니스 팀과의 소통에서도 큰 개선점이 생길 수 있습니다. “시스템에 문제가 있어서 느려요”라는 막연한 보고 대신, “회원의 모바일 예약에서만 평균 2초 지연이 발생하고 있으며 PG사 API 응답 지연이 원인입니다”와 같은 구체적이고 비즈니스 맥락이 포함된 정보를 제공할 수 있게 됩니다.

투명한 시스템을 향한 여정

그 동안 여기어때에서는 많은 개발자들과 엔지니어들이 앞서 기술한 취약점을 보완해가며 시스템을 운영해왔지만 한계를 가지고 있는 것은 부정할 수 없습니다.

새벽 3시, 알림이 울렸을 때의 상황을 다시 상상한다면 과거의 우리는 “또 무슨 일이지?”라는 막연한 걱정으로 여러 모니터링 도구을 확인하며 퍼즐 조각을 모으고 맞춰야 합니다. 하지만 옵저버빌리티가 완전히 구현 된다면 우리는 “오후 2시 17분, user_abc123의 모바일 예약 요청이 결제 서비스에서 1.2초 지연되었으며, PG사 API 응답 시간이 평상시보다 300% 증가한 것이 원인입니다. 또한 동일한 패턴으로 지난 10분간 127건의 유사한 지연이 발생했고 모두 해당 PG사 관련 요청입니다”라는 구체적이고 실행 가능한 정보를 즉시 받게 될 것입니다.

문화적 변화

옵저버빌리티는 기술적 도구를 넘어 조직 문화의 변화를 이끕니다. “누군가의 실수”를 찾는 문화에서 “시스템의 개선점”을 찾는 문화로의 전환입니다. 데이터가 명확한 근거를 제시하기 때문에 추측과 추론에 의존하던 장애 대응이 과학적 분석으로 바뀝니다. 신입 개발자와 시니어 개발자 간의 장애 대응 능력 격차가 줄어고 팀 간 사일로 현상이 해소하며 무엇보다 사용자 경험을 정량적으로 측정하고 개선할 수 있게 됩니다. “고객이 불편해한다”는 추상적 피드백이 “모바일 사용자의 예약 완료율이 웹 대비 15% 낮으며 결제 단계에서 이탈이 집중되고 있다”는 구체적 개선 포인트로 변환됩니다.

점진적 발전

완전한 시스템을 하루아침에 구축할 수는 없습니다. 작은 변화들이 누적되어 점진적 개선으로 이어질 것입니다. 한 번에 모든 서비스를 계측하기보다 핵심 비즈니스 플로우 부터 시작해서 각 단계에서 얻은 인사이트를 바탕으로 다음 단계를 설계해 나갈 예정입니다.

여기어때만의 옵저버빌리티

모든 조직의 옵저버빌리티는 고유합니다. 여기어때의 비즈니스 특성, 기술 스택, 조직 문화에 맞는 맞춤형 옵저버빌리티 생태계를 구축할 예정합니다. 이후에 어떤 구성으로 여기어때에서 옵저버빌리티 생태계를 운영하고 있는지 공유 하겠습니다.

여행플랫폼의 특성상 계절성, 이벤트성 트래픽 패턴이 명확하고 복잡한 사용자 플로우가 존재합니다. 이런 도메인 특성을 반영한 메트릭과 대시보드, 알림 시스템을 구축함으로써 단순히 “시스템이 잘 돌아가는지”를 넘어 “비즈니스가 건강하게 성장하고 있는지”를 실시간으로 파악할 수 있게 될 것입니다. 단순한 기술적 개선이 아닌 조직 전체의 문제 해결 능력과 사용자 경험 품질을 한 단계 끌어올린 전환점이었다고 평가할 수 있기를 바랍니다.

긴 글을 읽어 주셔서 감사합니다.