이 글은 eolma의 2026년 7월 관측성 설계·운영 문서를 바탕으로 정리한 초안입니다. 계정, 토큰, 내부 인스턴스 식별자는 제외했습니다.
홈 서버를 운영 경로에 추가하기 전에 먼저 답해야 할 질문이 있었다. “홈 서버가 동작하는가?”가 아니라 **“문제가 생겼을 때 어디서, 어떤 신호로, 얼마나 빨리 알 수 있는가?”**였다.
관측성 도입에서 흔한 실수는 Grafana, Prometheus, OpenTelemetry를 한 제품처럼 취급하는 것이다. eolma에서는 도구 목록보다 먼저 데이터의 생성·수집·저장·조회 경로를 분리해 보았다. 그 결과 메트릭은 즉시, 트레이스와 로그는 조건부로 도입하는 단계적 설계를 선택했다.
관측성은 세 가지 질문에 답한다
| 신호 | 주로 답하는 질문 | eolma에서의 예 |
|---|---|---|
| 메트릭 | 언제부터, 얼마나 자주 문제가 생겼는가? | HTTP 5xx 비율, p95 지연, JVM heap, 디스크 사용률 |
| 트레이스 | 요청 한 건이 정확히 어디에서 느려졌는가? | API → DB → 객체 저장소로 이어지는 요청 구간 |
| 로그 | 그 시점에 어떤 예외와 맥락이 있었는가? | 배포·기동 메시지, DB 연결 실패, 예외 stack trace |
세 신호는 서로 대체재가 아니다. 5xx 비율 증가라는 메트릭으로 이상 구간을 찾고, 같은 시간대의 트레이스로 병목 구간을 좁힌 뒤, 연결된 로그에서 구체적인 예외를 읽는 흐름을 목표로 했다.
flowchart LR A["애플리케이션 · JVM · 서버"] --> B["수집·가공\nPrometheus · Alloy"] B --> C["저장\nMimir · Tempo · Loki"] C --> D["대시보드 · 탐색 · 알림"] D --> E["장애 감지와 원인 분석"]
기존 구성은 버리지 않았다
eolma 백엔드에는 이미 Spring Boot Actuator, Micrometer, Prometheus registry가 있었다. Spring Boot는 Micrometer를 통해 여러 모니터링 시스템용 registry를 자동 구성할 수 있고, Prometheus registry가 있으면 Actuator endpoint로 메트릭을 노출한다. 이 기반을 새 도구로 교체하는 대신, 이미 안정적으로 scrape하던 Prometheus를 첫 번째 수집 경로로 유지했다. Spring Boot의 Metrics 문서가 이 구성의 출발점이다.
| 구성요소 | 맡긴 역할 | 이번 선택 |
|---|---|---|
| Actuator + Micrometer | 애플리케이션과 JVM 메트릭 생성·노출 | 유지 |
| Prometheus | endpoint scrape, 로컬 시계열 보관, PromQL 질의 | 유지하고 Cloud로 remote_write 추가 |
| Grafana | 여러 데이터 저장소의 조회와 시각화 | 로컬 화면은 유지, Cloud 화면은 외부 관제에 사용 |
| Grafana Cloud | 외부 저장소, 대시보드, alert, synthetic check | 메트릭과 외부 가용성부터 도입 |
| OpenTelemetry Java Agent + Grafana Alloy | trace·로그 수집과 가공 | 개인정보 처리 규칙 검증 뒤 도입 |
Prometheus와 Grafana가 겹쳐 보이지만 역할은 다르다. 전자는 메트릭을 수집·저장하는 엔진이고, 후자는 Prometheus를 포함한 저장소를 조회해 대시보드와 알림을 제공하는 UI·운영 계층이다. 이 구분을 해 두면 “Grafana를 설치했으니 메트릭이 저장된다” 같은 착각을 피할 수 있다.
왜 메트릭부터 시작했나
첫 번째 목표는 홈 서버가 운영 경로에 들어오기 전, 클라우드와 홈 서버를 같은 화면에서 비교하는 것이었다. 기존 Prometheus가 이미 애플리케이션·JVM·호스트 메트릭을 수집하고 있었으므로 다음 경로가 가장 작은 변경이었다.
flowchart LR A["Spring Boot\nMicrometer · Actuator"] <-->|"scrape"| P["Prometheus"] N["node exporter"] <-->|"scrape"| P P -->|"remote_write"| G["Grafana Cloud metrics"] G --> D["Dashboard · Alert"]
이 결정에는 두 가지 이유가 있었다.
- 기존 로컬 대시보드와 PromQL 질의를 깨지 않고, 외부 관제만 추가할 수 있다.
- 홈 서버와 클라우드 인스턴스에 동일한 label 계약을 적용해
project,service,instance,environment,role같은 축으로 분리해 볼 수 있다.
동일한 메트릭 이름이라도 인스턴스 라벨이 없다면 전환 뒤 어느 서버가 요청을 처리했는지 알 수 없다. 반대로 라벨을 너무 세분화하면 시계열 수와 비용이 커진다. eolma에서는 운영자가 실제로 비교할 축만 고정하고, 요청 ID나 사용자 식별자처럼 카디널리티가 커지는 값은 메트릭 label로 넣지 않았다.
트레이스와 로그를 나중으로 미룬 이유
OpenTelemetry는 계측 API와 OTLP 같은 표준을 제공하고, Grafana Alloy는 Prometheus scrape와 OpenTelemetry 수신·가공을 함께 수행할 수 있는 수집기다. 둘은 경쟁 관계가 아니라 표준과 그 표준을 사용하는 수집기 구현에 가깝다. OpenTelemetry 문서와 Grafana Alloy 문서를 함께 읽으면 이 역할 분담이 더 분명해진다.
하지만 “자동 계측이 가능하다”는 사실이 “바로 운영에 켜도 안전하다”는 뜻은 아니다. URL query, SQL 문장, 예외 메시지, 객체 key, 인증 정보가 span attribute나 로그에 섞일 수 있다. 개인 가계 데이터를 다루는 eolma에서는 이 위험이 특히 컸다.
따라서 순서를 바꿨다.
- 메트릭과 외부 synthetic check로 가용성·자원 상태를 먼저 감시한다.
- 소스 로그의 민감 정보 여부를 점검하고, 불필요한 capture 옵션을 끈다.
- Alloy filter·transform에서 제거 규칙을 한 번 더 적용한다.
- 필요한 trace부터 샘플링해 활성화한다.
- 로그는 PII·토큰·presigned URL 제거가 검증된 뒤에만 전송한다.
이 순서는 데이터를 더 많이 모으는 것보다 안전하게 설명 가능한 데이터만 모으는 것을 우선한다.
알림은 반드시 한 번 울려 봐야 한다
대시보드에 그래프가 나온다고 알림 경로가 검증된 것은 아니다. eolma에서는 node exporter 중단, synthetic API check 실패, 디스크 사용률, JVM heap, HTTP 5xx·지연, connection pool 같은 조건을 각각 규칙으로 만들었다. 그리고 임시 조건으로 실제 alert를 발생시켜 메일 수신을 확인한 다음, 운영 임계값과 pending 시간을 복원했다.
이 과정에서 얻은 기준은 단순하다.
| 검증 대상 | 확인해야 할 것 |
|---|---|
| 데이터 수집 | remote_write 실패가 없고, 앱·호스트 시계열이 모두 보이는가 |
| 외부 가용성 | 서비스 바깥의 probe가 공개 API와 홈페이지를 확인하는가 |
| 알림 전달 | 실제 firing과 resolved 알림이 운영자에게 도달하는가 |
| 전환 검증 | 주 서버와 fallback 서버의 요청·host 메트릭이 같은 대시보드에서 분리되는가 |
특히 synthetic check는 애플리케이션 내부 health와 다르다. 서버 내부에서 health가 UP이어도 DNS, TLS, 프록시, 네트워크 문제로 사용자는 접속하지 못할 수 있다. 그래서 외부 관점의 check를 별도로 두었다.
이번 설계의 결론
eolma에서 관측성은 “Grafana Cloud를 설치했다”로 끝나는 작업이 아니었다. 기존 메트릭 경로를 보존한 채 외부 관제와 알림을 먼저 만들고, 홈 서버 전환의 성공·실패를 인스턴스별 신호로 확인할 수 있게 하는 작업이었다.
다음 단계의 과제도 남아 있다. trace는 필요한 구간부터 샘플링과 개인정보 제거 규칙을 검증하며 활성화해야 하고, 로그 전송은 더 엄격한 검토가 필요하다. 그러나 이 순서를 지키면 새로운 신호를 추가해도 기존 운영 경로를 잃지 않고, “문제가 없다”가 아니라 “문제가 없음을 어떤 데이터로 확인했는가”를 설명할 수 있다.