오래된 데이터가 보일 때 확인할 순서

오래된 데이터가 보일 때 요청, API, worker와 출처를 차례로 확인하는 운영 절차

한강자리의 백엔드는 집에 둔 작은 서버의 K3s cluster에서 실행된다. 사용자가 오래된 주차 정보를 봤다면 요청 도달, API 상태와 worker의 마지막 수집을 차례로 확인한다.

사용자용 API는 Cloudflare edge와 Tunnel을 거쳐 K3s ingress로 들어온다. Tunnel로 원본 서버를 감추고 사용자 API와 운영 접근 경로를 분리했다.

서버 위치와 관계없이 사용자는 API의 응답 속도와 데이터 최신성을 본다. 운영 절차에는 작은 서버에서도 요청 경로, 수집 상태와 복구 가능성을 확인하는 항목을 넣었다.

사용자 요청의 API 도달 확인

첫 확인은 사용자 요청이 어떤 경로를 지나 API까지 도착하는지다. 이 경로가 막혔는지, API 안에서 특정 기능만 실패하는지, 데이터가 오래된 것인지는 서로 다른 문제다.

flowchart LR
  Public["iOS 앱 / 위젯<br/>Cloudflare edge"] --> Private["비공개 진입 경로<br/>Cloudflare Tunnel · K3s ingress"]
  Private --> API["FastAPI 서비스"]
  API --> Redis["Redis"]
  API --> PG["Postgres"]

브랜드 사이트와 지원/개인정보 페이지는 API와 분리했다. 정적 웹과 앱 API는 장애 성격이 다르므로 실행 환경별로 상태를 확인한다.

flowchart TB
  Site["hangangjari.app<br/>브랜드 · 지원 · 개인정보"] --> Pages["정적 사이트"]
  APIName["API 도메인"] --> Edge["Cloudflare edge"]
  Edge --> Tunnel["Cloudflare Tunnel"]
  Tunnel --> Runtime["K3s cluster"]

터널은 origin을 감춘 채 엣지 네트워크에서 서비스로 요청을 전달한다. 사용자 요청과 운영 접근은 서로 다른 경로를 사용한다.

장애 분류에서도 사용자 요청 경로와 운영 제어면을 따로 확인한다. 두 경로의 상태를 구분해야 복구 대상을 정할 수 있다.

오래된 값의 확인 순서

K3s 안의 API, worker, 상태 저장소, ingress와 metrics·logs를 오래된 값의 확인 순서에 맞춰 정리했다.

구성역할
FastAPI APIiOS 앱과 위젯이 읽는 앱 API
주차 worker주차 상태 수집
나들이 worker행사, 공지, 시설, 실시간 상황 수집
예측 worker예측 만들기와 home summary warmup
알림 worker후보 만들기, 보내기 규칙 확인, outbox 발송
Postgres/PostGIS기준 데이터, 이력, 감사 기록
Rediscache, 최신 상태, 보조 index
K3s ingress사용자 API routing
Prometheus/Grafana/logsmetrics, logs, dashboard
flowchart TB
  Desired["서버 상태 저장소<br/>원하는 상태"] --> GitOps["GitOps 동기화"]
  GitOps --> API["API 배포"]
  GitOps --> Workers["워커 배포"]
  GitOps --> State["Postgres / Redis"]
  GitOps --> Ingress["인그레스"]
  API --> Signals["메트릭 · 로그"]
  Workers --> Signals
  State --> Signals

운영 목록에는 배포 경로, 백업, metrics·logs와 복구 방법을 포함했다.

원인 후보를 줄이는 대시보드

대시보드는 사용자 제보 뒤 확인할 원인 후보를 줄이는 신호를 모은다.

flowchart TD
  Checks["확인할 항목"] --> APIQ["API<br/>상태 · 지연 · 오류율"]
  Checks --> WorkerQ["워커<br/>마지막 성공 · 행 수 · 최신성"]
  Checks --> DataQ["데이터<br/>캐시 적중/미스 · 예측 실행 · outbox 적체"]
  Checks --> InfraQ["K3s<br/>ingress · GitOps 상태 · 백업 상태"]
  APIQ --> Triage["실패 구간 분류"]
  WorkerQ --> Triage
  DataQ --> Triage
  InfraQ --> Triage

초기 분류에 사용하는 신호는 다음과 같다.

  • API가 살아 있는가.
  • protected route가 정상적으로 거절·허용되는가.
  • 특정 endpoint latency가 튀고 있는가.
  • worker가 최신 데이터를 계속 수집하는가.
  • 출처별 마지막 성공 시각이 오래됐는가.
  • Redis cache가 비정상적으로 비어 있는가.
  • forecast가 최신 run을 만들고 있는가.
  • push outbox가 쌓이고 있지 않은가.
  • DB backup과 restore drill이 정상인가.

API와 worker가 내부 metrics를 노출하면 수집기가 주기적으로 가져간다.

제보 뒤 확인할 구성 요소 상태

문제가 생기면 요청 경로와 구성 요소의 상태로 실패 위치를 먼저 좁힌다.

flowchart TD
  Alert["사용자 제보 또는 스모크 실패"] --> Public{"사용자 API 상태 정상?"}
  Public -->|아니오| Runtime{"ingress와 K3s가 정상인가?"}
  Runtime -->|예| Edge["엣지와 터널 확인"]
  Runtime -->|아니오| Pods["pod와 GitOps 상태 확인"]
  Public -->|예| Feature{"특정 API만 실패하는가?"}
  Feature -->|예| Fresh{"최신성이 떨어졌는가?"}
  Fresh -->|예| Worker["워커와 수집 실행 확인"]
  Fresh -->|아니오| Cache["캐시/화면용 응답과 DB 조회 확인"]
  Feature -->|아니오| Client["클라이언트 캐시 또는 위젯 스냅샷 확인"]

이 순서로 API 중단, 출처 실패, 오래된 cache와 클라이언트 snapshot을 구분한다.

복구 우선순위에 따른 데이터 분류

백업 상태는 파일 생성과 복구 연습 결과로 확인한다.

한강자리에서는 DB 백업 상태와 복구 가능성도 확인 대상에 포함한다. 공공데이터는 다시 수집할 수 있는 것도 많다. 하지만 사용자 설정, push subscription, 앱 event, forecast/backtest 이력은 사라지면 복구가 어렵다.

그래서 다시 만들 수 있는 데이터와 반드시 남겨야 하는 데이터를 구분해야 한다. Redis cache가 비는 것과 Postgres의 기준 데이터가 손상되는 것은 같은 장애가 아니다. 복구 연습은 이 차이를 실제로 확인하는 과정이다.

오래된 값에서 원인까지 가는 순서

오래된 데이터가 보이면 요청 경로와 API 상태를 확인하고 특정 기능의 worker·출처 최신성, cache와 클라이언트 snapshot 순으로 범위를 좁힌다. Postgres 데이터는 백업과 복구 연습을 확인하고 Redis 조회값은 재생성 경로를 확인한다.

Comments

댓글

    이미지 확대