
나의 AI 홈랩(Homelab)에 관측성(Observability) 추가하기
요약
개인용 AI 에이전트 홈랩 운영 중 발생하는 라우팅 상태, API 비용, 모델 성능 등을 모니터링하기 위해 관측성(Observability)을 구축하는 과정을 다룹니다. 설정 파일 수정을 통해 내장 UI에서 로그와 분석 데이터를 확인할 수 있도록 구성하는 방법을 설명합니다.
핵심 포인트
- AI 에이전트 운영 시 라우팅 및 비용 모니터링의 중요성
- 내장 UI를 통한 실시간 로그 및 비용 분석 기능 활용
- YAML 설정 시 database 키를 config 섹션 내에 중첩해야 하는 주의사항
Homelab AI 시리즈의 4부 — 1부 | 2부 | 3부
상황을 설명해 보겠습니다.
저의 개인용 AI 에이전트(AI agent)는 야간 크론 잡(cron jobs)을 실행하고 있습니다. 일정 요약, 이메일 요약, 작업 우선순위 지정 등 말이죠. 3부에서 vLLM Semantic Router를 통합한 이후로 3주 동안 조용히 이 작업들을 수행해 왔습니다.
그런데 저는 이것이 제대로 작동하고 있는지 전혀 알 길이 없습니다.
고장이 났기 때문이 아닙니다. 그것에 대한 관측성(visibility)이 전혀 없기 때문입니다. Mac Mini는 거실에 놓여 초록색 불빛을 조용히 깜빡이며 요청을 처리하고 있지만, 라우팅(routing)이 실제로 잘 작동하고 있는지, API 비용이 폭발하고 있지는 않은지, 혹은 로컬 Ollama 모델이 Gemini로 갔어야 할 프롬프트(prompts)를 억지로 처리하느라 고군분투하고 있는지는 전혀 알 수 없습니다.
저는 완전히 눈을 가린 채 비행하고 있었던 셈입니다.
실행되지 못한 계획
3부 이후, 저의 원래 관측성(observability) 로드맵은 야심 찼습니다. 저는 다음과 같은 완전한
$ git pull origin main
...
crates/agentgateway/src/ui.rs | 423 ++++++++++++++++++++++++
...
팀은 방금 완전히 새로운 내장 UI를 출시했습니다 — 분석 (Analytics) 대시보드, 실시간 로그 탐색기 (Logs Explorer), 그리고 비용 상세 내역 (Cost Breakdown) 뷰까지 모두 갖춰져 있었습니다. 제가 주말 내내 구축하려고 했던 모든 것이 이미 그곳에 있었습니다. 네이티브로. 바이너리 안에. 15000 포트에서 말이죠.
저는 docker-compose.yaml 파일을 닫았습니다. 다시는 열 일이 없을 것 같았습니다.
단 세 줄의 YAML. 그게 전부입니다.
내장 UI는 이미 http://localhost:15000/ui에서 서비스되고 있었습니다. 하지만 그곳으로 이동했을 때, 로그 (Logs)와 분석 (Analytics) 페이지에는 아무것도 나타나지 않았습니다. 그저 빈 차트와 다음과 같은 메시지만 있을 뿐이었습니다:
Logs API error — request log database is not configured
맞습니다. UI가 요청 로그 (request logs)를 기록할 장소가 필요했던 것입니다. 저는 여기서 Postgres 인스턴스를 설정하거나, 최소한 SQLite를 위한 Docker 컨테이너를 구축할 것이라고 예상했습니다.
대신, 저는 homelab_config.yaml에 다음과 같이 추가했습니다:
config:
modelCatalog:
- file: base-costs.json
...
그게 전부였습니다.
제가 겪은 한 가지 중요한 주의 사항(gotcha)은 database: 키가 반드시 config: 섹션 내부에 중첩(nested)되어야 한다는 점입니다. 처음에는 YAML의 최상위 레벨(top level)에 추가하려고 시도했다가 "unknown field" 유효성 검사 오류를 받았습니다. 설정 파서 (config parser)는 엄격합니다. 올바르게 중첩하기만 하면 그냥 작동합니다.
AgentGateway를 재시작했습니다. 몇 개의 테스트 요청을 보냈습니다. 대시보드를 새로고침했습니다.
차트들이 활성화되었습니다.
대시보드 내부에는 실제로 무엇이 들어있나
분석 (Analytics) 뷰
분석 (Analytics) 페이지는 모든 요청을 provider와 model별로 그룹화합니다. 저의 설정에서는 Pi가 보내는 모든 요청에 대해 세 가지 가능한 목적지가 있습니다:
- Ollama를 통한
qwen2.5-coder:7b— 로컬, 무료, 느림 - OpenAI를 통한
gpt-4o— 비쌈, 빠름, 최고의 추론 능력 - Google을 통한
gemini-2.5-flash— 저렴한 클라우드, 빠름, 훌륭한 컨텍스트 윈도우 (context window)
AgentGateway는 vLLM Semantic Router가 전달(forwarding) 전에 x-selected-model 헤더를 추가하기 때문에 어떤 모델이 각 요청을 처리했는지 알고 있습니다. 따라서 UI는 단순히 "요청이 발생했다"라고만 보여주는 것이 아니라, 어떤 모델이 요청을 받았는지, 얼마나 많은 토큰을 소비했는지, 그리고 내장된 모델 가격 카탈로그(model pricing catalog)를 사용하여 추정된 달러 비용이 얼마인지를 보여줍니다.
위의 24시간 스냅샷을 보면: 60회 호출, 13,929 토큰, 총 $0.0340. 이것이 Pi의 야간 작업(overnight jobs)을 실행하는 데 드는 전체 비용입니다. 상호작용당 1센트의 아주 작은 부분에 불과합니다.
그리고 라우팅(routing)이 제대로 작동하고 있음을 확인할 수 있습니다. 오른쪽의 트래픽 급증은 Pi의 새벽 3시 크론 배치(cron batch) 작업과 일치합니다. 모델별 상세 내역을 통해 코딩 작업이 클라우드 API 크레딧을 소모하지 않고 실제로 로컬 Ollama를 호출하고 있는지 확인할 수 있습니다.
로그 익스플로러 (The Logs Explorer)
이 화면은 저를 진심으로 놀라게 했습니다.
모든 개별 LLM 호출은 다음과 같은 항목을 포함하는 하나의 행(row)으로 나타납니다:
- HTTP 상태 (HTTP Status) —
200,400,404— 잘못된 상태는 놓치기 어렵습니다. - 지속 시간 (Duration) — 요청 수신부터 응답 전달까지의 총 시간
- 모델 (Model) — 제
MoM별칭이 아닌, 실제로 호출된 실제 모델 - 제공자 (Provider) —
gcp.gemini,openai,openai(Ollama는 OpenAI API 방식을 사용하므로openai로 표시됨) - 토큰 수 (Token counts) — 입력(input)과 출력(output)을 별도로 표시
- 추정 비용 (Estimated cost) — 모델 가격 카탈로그를 기준으로 한 요청당 달러 금액
위의 스크린샷을 보세요. 실제 요청들을 볼 수 있습니다: 각각 몇 센트의 몇 분의 일 수준인 gemini-2.5-flash 호출, 비용이 0인 qwen2.5-coder:7b 호출, 그리고 상단의 non-existent-model에 대한 몇 개의 404 오류 — 이들은 제 트래픽 테스트에서 발생한 시뮬레이션된 오류 요청들이며, 예상대로 정확히 나타나고 있습니다.
어떤 행이든 클릭하여 전체 요청 상세 정보(request detail)를 확인할 수 있습니다. 즉, Pi가 보낸 정확한 프롬프트(prompt)와 Pi가 받은 정확한 응답(response)을 볼 수 있다는 것입니다. Pi의 새벽 3시 캘린더 작업이 이상한 것을 보낼 때, 저는 가공되지 않은 JSON(raw JSON)을 확인할 수 있습니다. 이전에는 결코 불가능했던 일입니다.
전체 설정 (The Full Config)
이것을 구축하려는 분들을 위해, 제 전체 홈랩 AI 스택을 실행하는 완전한 homelab_config.yaml을 공유합니다:
# yaml-language-server: $schema=https://agentgateway.dev/schema/config
# 게이트웨이 수준 정책: ExtProc 사이드카(sidecar)로서의 시맨틱 라우터(Semantic Router)
...
관심사의 분리(separation of concerns)는 다시 한번 강조할 가치가 있습니다. 시맨틱 라우터(Semantic Router)는 API 키에 절대 손을 대지 않습니다. 프롬프트(prompt)를 분류하고, 헤더(header)를 설정한 뒤 바로 물러납니다. 다운스트림 인증(downstream auth)은 전적으로 AgentGateway가 담당합니다. 이는 프로덕션 Kubernetes 클러스터에서 사용하는 것과 동일한 설계 패턴입니다. 즉, 보안 태세(security posture)로부터 라우팅 지능을 분리(decoupled)하는 방식입니다.
왜 Grafana가 아닌가?
일부 사람들이 질문할 것을 알기에 이 부분에 대해 직접 말씀드리고자 합니다.
만약 전담 플랫폼 팀이 있는 엔터프라이즈 Kubernetes 클러스터를 운영 중이라면, 당연히 AgentGateway의 OpenTelemetry 데이터를 중앙 집중식 Datadog 또는 Prometheus 스택으로 내보내십시오. AgentGateway는 이를 기본적으로 지원합니다. OTLP 트레이스(traces)와 /metrics 엔드포인트를 방출합니다. 프로덕션 환경에서의 관측성(observability) 스토리는 매우 훌륭합니다.
하지만 홈랩을 운영 중이라면 어떨까요?
단일 노드 AI 게이트웨이를 위해 Prometheus + Grafana를 운영하는 것은 얻는 것에 비해 운영 부담(operational burden)이 엄청납니다. 두 개의 추가 서비스를 계속 실행하고 건강한 상태로 유지해야 하며, Grafana 대시보드 JSON을 작성 및 유지 관리해야 하고, Prometheus 경고 규칙(alerting rules)을 구성해야 하며, 스키마(schema)가 변경될 때 이 모든 것을 동기화된 상태로 유지해야 합니다.
AgentGateway의 내장 대시보드는 운영 오버헤드(operational overhead) 없이 제가 중요하게 생각하는 모든 지표(metric) — 토큰 사용량(token usage), 모델당 비용(cost per model), 지연 시간 분포(latency distribution), 에러율(error rates) — 를 제공합니다. SQLite 파일은 바이너리(binary) 바로 옆에 위치합니다. 유지 관리할 것도, 재시작할 것도, 프로비저닝(provision)할 것도 없습니다.
필요하지 않다면 관측성 스택(observability stack)을 구축하지 마십시오.
실제 가시성을 확보한 후 일주일간의 수치
실제 데이터를 갖게 되면 설정(setup)에 대한 사고방식이 바뀝니다:
| 지표 (Metric) | 눈먼 상태 (이전) | 대시보드 도입 후 |
|---|---|---|
| 라우팅 정확도 (Routing correctness) | "아마 괜찮겠지?" | 분석(Analytics)을 통해 모델별로 검증됨 |
| ... |
마지막 행이 가장 중요합니다. 제가 전혀 파악하지 못했던 세 가지 실제 문제들이 있었습니다. Gemini에 잘못된 날짜 범위를 보내는 캘린더 cron 작업, Pi의 요약 프롬프트(summarization prompt)에서 발생한 토큰화(tokenization) 엣지 케이스, 그리고 조용히 발생했던 API 키 로테이션(rotation) 실패 건이었습니다. 대시보드는 단순히 숫자만 제공한 것이 아니라, 저에게 _답(answers)_을 주었습니다.
완성된 홈랩 스택 (Homelab Stack)
네 개의 포스트, 거실에 있는 Mac Mini 한 대. 전체 그림은 다음과 같습니다:
Pi (Personal Agent)
│
▼ POST /v1/chat/completions model: "MoM"
...
- 에이전트 (The Agent) — 거실의 Mac Mini에서 24시간 내내 cron 작업과 개인 작업을 수행하는 Pi.
- 지능 계층 (The Intelligence Layer) — vLLM Semantic Router. mmBERT 임베딩(embeddings)을 사용하여 모든 프롬프트를 분류하고 약 1ms 내에 라우팅 헤더(routing headers)를 설정합니다.
- 데이터 평면 (The Data Plane) — Rust로 작성된 AgentGateway. 모든 API 키를 소유하고, 인증(auth)을 처리하며, 경로(routes)를 매칭합니다.
- 제어 평면 (The Control Plane) — SQLite를 기반으로 하는 AgentGateway의 내장 UI. 실시간 토큰 사용량, 비용, 지연 시간(latency), 그리고 에러를 보여줍니다.
전체 스택은 단일 바이너리(plus SR 컨테이너)로 실행됩니다. 인프라에 대한 클라우드 비용 지출은 제로입니다. Mac Mini는 이미 제 거실에 놓여 있었습니다.
다음 단계
지금이 자연스러운 휴식기처럼 느껴집니다. 스택은 안정적이고, 관측 가능하며, 솔직히 이 시리즈를 시작했을 때 기대했던 것보다 더 유능합니다.
제가 적극적으로 탐색하고 있는 몇 가지 사항은 다음과 같습니다:
- 스택의 Dockerizing (Dockerizing the stack) — Ollama, SR 컨테이너, 그리고 AgentGateway를 하나의
docker-compose.yaml로 묶어, 제가 아무것도 건드리지 않아도 Mac Mini가 재부팅 후 완전히 스스로 복구(self-heals)될 수 있도록 만드는 것입니다. - 더 많은 모델 카드 (More model cards) — 라우팅(routing)이 시맨틱(semantic)하게 이루어지므로, 이제 새로운 특화 모델을 추가하는 것은 SR의
config.yaml에 새로운 설명을 작성하는 것만으로 충분합니다. 나머지는 라우터가 알아서 처리합니다. - OTLP 내보내기 (OTLP export) — AgentGateway는 이미 OpenTelemetry 스팬(spans)을 방출합니다. 저는 이를 가벼운 alertmanager에 연결하여, 새벽 3시 실행 중에 Pi의 에러율이 임계값을 초과하여 급증할 때 알림을 받도록 만들고 싶습니다.
홈랩(homelab)이든 프로덕션(production) 환경이든 에이전트(agents)를 구축하고 있다면, AgentGateway + vLLM Semantic Router + 내장된 SQLite 관측성(observability)의 조합은 현재 제가 알고 있는 가장 완전한 단일 노드 AI 인프라 스택입니다. YAML의 난무도 없고, 정상적인 경로(happy path)를 위한 외부 의존성도 없습니다. 그저 설정 파일 하나, 바이너리 하나, 그리고 초록색 불이 들어온 Mac Mini뿐입니다.
그리고 이것은 제 거실에서 24시간 7일 내내 조용히 돌아가고 있습니다. 🏠
설정에 대해 궁금한 점이 있으신가요? 댓글로 남겨주세요 — 매일 확인합니다. 그리고 비슷한 것을 구축하셨다면, 어떻게 응용하셨는지 꼭 보고 싶습니다.
#ai #agents #observability #homelab #agentgateway #vllm #sqlite #llm #opensource
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기