JUN0.DEV
JUN0.DEV

GRIT 모니터링 구성: Prometheus + Loki + Grafana + Spring Actuator

Published on
  • avatarJunyoung Yang

GRIT를 만들면서 기능 구현만으로는 충분하지 않다고 느꼈다. 실시간 화상 스터디 서비스는 사용자가 방에 들어와 있는 동안 문제가 생기면 바로 체감된다. 그래서 운영 중 요청이 늘거나 에러가 발생했을 때 최소한 어디를 확인해야 할지 준비가 필요했다.

처음에는 로그만 확인하면 될 것 같았지만, 응답 시간이나 요청 수, 에러 비율 같은 것은 로그보다 메트릭으로 보는 편이 더 적절했다. 반대로 특정 문제의 상세 맥락은 로그가 필요했다.

그래서 Spring Actuator, Prometheus, Loki, Grafana를 도입해 기본적인 모니터링 구성을 만들었다.

처음 보인 문제

GRIT는 실시간 서비스 특성이 있었다. 사용자가 방에 입장하고, 마이크 권한을 받고, 타이머와 발표 상태를 공유한다. 이런 기능은 단순 CRUD보다 운영 중 상태를 더 자주 확인해야 한다.

특히 확인하고 싶었던 것은 아래와 같았다.

  • API 요청 수와 응답 시간
  • 에러 발생 추이
  • 특정 시간대 로그
  • 애플리케이션 상태와 JVM 지표
  • 배포 이후 문제가 생겼을 때 확인할 기본 화면

운영 준비 없이 기능만 만들면 문제가 생겼을 때 로그를 추측으로 뒤지게 된다. 그런 상태를 피하려고 했다.

해결 방안

Spring Boot 애플리케이션에서는 Actuator를 통해 기본적인 상태와 메트릭을 노출할 수 있었다. 그래서 먼저 Actuator endpoint를 열고 Prometheus가 읽을 수 있는 형태로 메트릭을 제공했다.

이때 중요한 것은 모든 endpoint를 무작정 여는 것이 아니라, 운영에서 필요한 항목을 구분하는 것이었다. 상태 확인과 메트릭 수집에 필요한 endpoint를 중심으로 노출 범위를 정리했다.

적용 및 구현

Prometheus는 애플리케이션의 메트릭 endpoint를 주기적으로 scraping하도록 구성했다. Grafana는 Prometheus를 datasource로 연결해 요청 수, 응답 시간, JVM 관련 지표를 확인하는 대시보드 역할을 맡겼다.

처음부터 완벽한 대시보드를 만들려고 하지는 않았다. 먼저 운영 중 확인해야 할 최소 지표를 정하는 데 집중했다.

  • 서비스가 살아 있는지
  • 요청이 들어오고 있는지
  • 응답 시간이 급증하는지
  • 에러가 늘어나는지
  • JVM 메모리나 스레드 상태가 이상한지

이 정도만 보여도 문제가 생겼을 때 처음 볼 화면이 생겼다.

로그 연결

메트릭은 이상 징후를 보여주지만, 왜 그런 일이 생겼는지는 로그를 확인해야 하는 경우가 많다. 그래서 Loki를 도입해 애플리케이션 로그를 Grafana에서 함께 조회할 수 있게 구성했다.

로그를 파일이나 콘솔에서만 보면 시간대와 서비스별로 따라가기 불편하다. Grafana에서 메트릭을 보다가 같은 시간대의 로그로 바로 넘어갈 수 있으면 문제를 좁히기 쉬워진다.

이 구성의 목적은 로그 저장 자체보다, 메트릭과 로그를 같은 화면에서 이어서 보는 것이었다.

정리한 기준

이 작업을 하면서 모니터링은 나중에 추가하는 장식이 아니라고 생각했다. 기능이 정상 동작하는지 확인하는 것과, 운영 중 어디가 이상한지 파악하는 것은 다른 문제였다.

정리한 기준은 이렇다.

  • 서비스 상태를 한눈에 볼 수 있는가
  • 요청 수와 응답 시간이 숫자로 보이는가
  • 문제가 생긴 시간대의 로그를 바로 찾을 수 있는가
  • 배포 후 최소한의 확인 루틴이 있는가

마무리

GRIT 모니터링 구성은 거창한 관측성 플랫폼을 만든 작업은 아니었다. 하지만 운영을 생각하면 반드시 필요한 시작점이었다.

Spring Actuator, Prometheus, Loki, Grafana를 구성하면서 기능 구현 이후에 무엇을 확인해야 하는지 조금 더 명확해졌다. 실시간 서비스는 잘 동작하는 것만큼, 문제가 생겼을 때 어디서부터 확인할 수 있는지도 중요했다.