1. 왜 ChatGPT App에 메트릭과 SLO가 필요한가
두 가지 팀의 상태를 상상해 봅시다.
첫 번째 팀은 “대충 되는 것 같다”를 신조로 삼습니다. 사용자가 지원 채널에 불만을 올리거나 화난 트윗을 쓰지 않는 한 괜찮다고 생각하죠. 가끔 누군가 로그를 열어 길게 늘어선 문자열을 휙휙 넘겨보고는 고개를 끄덕이며 탭을 닫습니다.
두 번째 팀은 몇 개의 간단한 대시보드를 갖추고 있습니다:
- 주요 MCP 도구의 p95 레이턴시.
- MCP와 체크아웃의 error‑rate.
- 웹훅 가용성.
- 퍼널 기준 결제 전환율.
그리고 3–5개의 SLO가 있습니다: “도구 recommend_gifts 호출의 95% — 2초 이내”, “MCP‑tools 오류 비율 < 1%”, “체크아웃 가용성 ≥ 99.5%”, “위젯 → 성공 결제 전환율 ≥ 10%”.
두 번째 방식이라면 여러분은 다음을 할 수 있습니다:
- 사용자 불만 이전에도 앱에 무언가 문제가 있음을 빠르게 알아차립니다;
- 모든 변경(새 추천 알고리즘, SDK 마이그레이션, 새 프로바이더 요금제)의 효과를 계량화해 측정할 수 있습니다;
- 스토어와 리뷰 모듈에 도달했을 때 “우리는 품질 기준이 있고, 그 기준을 얼마나 충족하는지 알고 있다”고 자신 있게 말할 수 있습니다.
우리는 아주 명확한 것들을 이야기할 겁니다: p95가 무엇인지, 왜 평균보다 나은지, error‑rate와 availability를 어떻게 계산하는지, 웹훅이 포함된 커머스 부분에서 어떤 메트릭이 중요한지, 그리고 이 모든 것을 바탕으로 단순하지만 유용한 SLO를 어떻게 구성하는지. 우리의 학습용 앱인 GiftGenius — 추천 MCP 도구, 체크아웃, 결제 웹훅이 있는 커머스 시나리오 — 를 예로 들어 살펴보겠습니다.
2. ChatGPT App의 기본 메트릭: 무엇을 측정할 것인가
레이턴시: 평균 대신 p50/p95/p99
레이턴시는 작업 시작부터 논리적 종료까지의 시간입니다. 우리 스택에는 이런 작업이 몇 가지 있습니다:
- MCP 도구 recommend_gifts 호출(선물 추천);
- ACP에서 체크아웃 intent를 생성하는 도구 호출;
- 성공 결제 웹훅 처리.
사용자가 ChatGPT에서 체감하는 전체 지연은 우리가 전적으로 통제하지 못합니다. 플랫폼 기여분(모델 추론, OpenAI 네트워크 지연)이 있고, 우리가 통제하는 부분 — 도구, 백엔드, DB, 결제사 — 이 있습니다. 레이턴시에 대한 SLI(Service Level Indicator — 서비스 품질의 측정 가능한 지표)로는 보통 우리의 부분, 즉 App/MCP로 요청이 들어온 시점부터 우리 서버의 응답이 준비될 때까지를 측정합니다.
여기서 평균 응답 시간은 착시를 일으킬 수 있습니다. 만약 90%의 요청은 100ms에 오고, 10%는 5초가 걸린다면 평균은 약 0.5초로 “초록불”처럼 보일 겁니다. 하지만 10번째 사용자마다 5초 멈춤을 보게 되고 — UX는 확연히 나빠집니다.
그래서 퍼센타일을 사용합니다: p50(중앙값), p95, p99. p95는 요청의 95%가 그 값보다 낮은 시간 안에 처리된다는 경계입니다. SRE 가이드가 강조하듯, 퍼센타일은 “이상치가 평균에 숨지 못하게” 하고 분포의 꼬리에 있는 불행한 5–10% 사용자의 삶을 보이게 만듭니다.
간단히 이렇게 생각하면 됩니다: p50은 “평균적” 사용자의 삶을 말하고, p95/p99는 항상 “뭔가 느린” 인내심 강한 사용자들의 고통을 보여줍니다.
Error‑rate: 실패 요청의 비율
Error‑rate는 일정 기간 동안 전체 요청 수 대비 실패한 요청 수의 비율입니다. 주요 데이터 원천은 보통 구조화된 로그이거나 label이 붙은 메트릭입니다 status="success" | "error".
우리 스택에서 자연스러운 error‑rate는 다음과 같습니다:
- MCP 도구 레벨: recommend_gifts 호출 중 오류로 끝난 비율(예외, 외부 API의 HTTP 5xx, 타임아웃);
- ACP/체크아웃 레벨: 주문 생성 시도가 실패한 비율(API 오류, 결제사 장애 등);
- 웹훅 핸들러 레벨: 처리에 실패한 웹훅의 비율.
까다로운 지점: ChatGPT App에는 “조용한” 오류가 있습니다. 예를 들어 MCP 도구가 오류를 반환했고, 모델이 사과한 뒤 기술적 오류를 헤더로 노출하지 않은 채 대화를 이어갔다고 합시다. 형식상 ChatGPT는 사용자에게 자연스러운 답을 보여주지만, 신뢰성 관점에서 여러분의 스택은 실패한 것입니다. 그래서 error‑rate는 “최종 GPT UX 응답”이 아니라 엔지니어링 상태를 기준으로 계산하는 것이 중요합니다.
Availability: 서비스 가용성
Availability는 일정 기간 동안 성공적으로 처리된 요청의 비율입니다. 개념적으로는 error‑rate의 보완값으로, “얼마나 성공했는가”를 봅니다. 고전적 예: availability = successful_requests / total_requests * 100%.
우리 스택에 적용하면:
- MCP 서버 가용성: 지난 1시간 동안 ChatGPT에서 보낸 JSON‑RPC 호출 중 올바른 응답으로 끝난 비율;
- 체크아웃 API 가용성: /api/checkout 호출 중 HTTP 2xx로 끝난 비율;
- 웹훅 엔드포인트 가용성: 결제사에서 들어온 웹훅에 대해 우리가 올바른 응답(보통 HTTP 200)을 반환한 비율.
결제 제공사 문서에서 가령 99.9% 가용성을 보장한다고 하는데 여러분 쪽은 97%라면, 문제는 대개 그쪽이 아니라 여러분 쪽입니다.
커머스 메트릭: 전환과 퍼널
GiftGenius는 커머스 시나리오입니다. 여기서는 기술(빠른 응답, 적은 오류)뿐 아니라 비즈니스 성과 — 추천이 얼마나 자주 유료 주문으로 이어지는가 — 도 중요합니다.
여기서 전환 퍼널이 등장합니다:
- 위젯이 노출된 사용자(view);
- 선물을 선택한 사용자(selection);
- “주문 진행”을 누른 사용자(checkout started);
- 주문 상태가 “결제 완료”가 된 사용자(paid).
이 퍼널에서 “위젯 → 결제” 전환율을 정의할 수 있는데, 이것 역시 SLI — 서비스 품질의 측정 가능한 지표 — 입니다. 예를 들어 “하루 동안 성공 결제 수 / 위젯을 본 사용자 수 = 7%”. 레이턴시가 갑자기 증가하거나 체크아웃이 간헐적으로 타임아웃으로 실패하면, 퍼널은 예상치 못한 지점에서 좁아질 수 있습니다.
Instant Checkout을 사용하는 경우
설명한 커머스 메트릭은 Agentic Commerce Protocol 기반의 Instant Checkout에도 동일하게 적용됩니다. 이 경우 “자체” /api/checkout 대신 표준화된 Agentic Checkout API가 있습니다: ChatGPT는 여러분의 REST 엔드포인트인 POST /checkout_sessions, POST /checkout_sessions/{id}, POST /checkout_sessions/{id}/complete (선택적으로 cancel 및 GET)을 호출하며, 매번 장바구니와 체크아웃의 “진짜” 상태를 여러분으로부터 받습니다.
메트릭 관점에서는 아무것도 바뀌지 않습니다: p95 레이턴시, error-rate, availability를 임의의 /api/checkout이 아니라 이 표준 엔드포인트들 기준으로 계산하면 됩니다. “체크아웃의 p95 레이턴시 < 3초, error-rate < 2%” 같은 SLO는 자체 API가 아니라 checkout_sessions 호출에 그대로 적용됩니다.
별도의 세계: 웹훅 메트릭
웹훅은 비동기 이벤트(예: 결제사의 payment_succeeded)로, 주문의 라이프사이클을 전진시킵니다. 웹훅 처리가 나쁘면, 앱이 보기 좋게 선물을 추천하더라도 주문이 “결제 대기” 혹은 어떤 미정 상태에 “멈춰” 버릴 수 있습니다.
Stripe/결제사와 직접 연동하지 않고 Instant Checkout을 사용한다면, 결제사 웹훅의 역할은 Agentic Checkout의 order events가 맡습니다: 여러분의 백엔드는 OpenAI로 order.created, order.updated 같은 이벤트를 지정된 웹훅 URL로 보냅니다. 이는 동일한 부류의 개체입니다: 최종 주문 상태에 영향을 미치는 비동기 이벤트이며, 단지 수신자가 여러분의 프런트엔드가 아니라 ChatGPT일 뿐입니다.
따라서 동일한 메트릭 — success rate, latency, error-rate — 을 Stripe 웹훅이 아니라 OpenAI 측으로 보내는 여러분의 order‑event 웹훅 기준으로 계산하면 됩니다. SLO에는 “7일 동안 99% 이상의 order.* 이벤트가 전달 및 성공 처리, 처리 지연의 p95 < 500ms”라고 직접 명시할 수 있고 — 이는 Instant Checkout에 정확한 SLI/SLO가 됩니다.
웹훅에서 보통 보는 지표:
- webhook success rate — 재시도 포함, 비즈니스 로직이 성공적으로 끝난 웹훅 비율;
- webhook latency — 웹훅 수신부터 처리 완료까지의 시간;
- webhook error rate — 검증 실패, DB 불가, 타임아웃 등으로 웹훅 처리가 실패한 비율.
예를 들어 다음과 같은 SLO를 둘 수 있습니다: “7일 동안 웹훅의 99% 이상이 성공 처리” 그리고 “웹훅 처리 지연의 p95 < 500ms”.
3. GiftGenius에서 메트릭을 기술적으로 측정하는 방법
이제 이론에서 코드로 넘어갑니다. 추후 p95, error‑rate 같은 메트릭으로 집계할 수 있도록 어디에 측정을 심을지 정해야 합니다.
여기서는 특정 Prometheus나 Datadog을 끌어오지 않고, 간단한 logMetric 함수나 JSON 이벤트 로깅이 있다고 가정합니다. 그 위에 어떤 관측 시스템이든 필요한 그래프를 만들 수 있습니다.
MCP 도구의 레이턴시 측정
TypeScript 기반의 GiftGenius MCP 서버와 recommend_gifts 도구가 있다고 가정합시다. 비즈니스 로직을 타이머로 감쌉니다:
// mcp/tools/recommendGifts.ts
import { logMetric } from "../observability/metrics"; // 가상의 helper
export async function recommendGiftsTool(input: RecommendInput) {
const startedAt = performance.now(); // 시작 시각
try {
const result = await recommendGifts(input); // 비즈니스 로직
const duration = performance.now() - startedAt;
logMetric("tool_latency_ms", duration, {
tool: "recommend_gifts",
status: "success",
});
return result;
} catch (error) {
const duration = performance.now() - startedAt;
logMetric("tool_latency_ms", duration, {
tool: "recommend_gifts",
status: "error",
error_type: "exception",
});
throw error;
}
}
여기서 logMetric은 stdout에 JSON 로그만 찍어도 됩니다:
// observability/metrics.ts
export function logMetric(
name: string,
value: number,
labels: Record<string, string | number>
) {
// 실제로는 여기서 Prometheus/DataDog 클라이언트를 사용합니다
console.log(
JSON.stringify({
type: "metric",
name,
value,
labels,
timestamp: new Date().toISOString(),
})
);
}
이 접근으로 tool_latency_ms 이벤트 스트림을 얻습니다. 여기서 label tool과 status로 성공 호출만의 p95를 계산하거나, 반대로 오류로 끝나는 요청이 얼마나 오래 걸렸는지 볼 수 있습니다.
error‑rate 계산
비슷한 방식으로 별도의 오류 메트릭을 로깅할 수 있습니다:
// 같은 도구 핸들러 내부
logMetric("tool_error_total", 1, {
tool: "recommend_gifts",
error_type: "external_api_timeout",
});
성공한 요청의 경우:
logMetric("tool_success_total", 1, {
tool: "recommend_gifts",
});
그다음 메트릭 시스템에서 error_rate = tool_error_total / (tool_error_total + tool_success_total) 을 기간 기준으로 계산합니다. 이는 메트릭 시스템 쪽에서 집계하며; 애플리케이션에서는 이벤트를 꼼꼼히 내보내는 것이 중요합니다.
최소주의를 원한다면, 별도의 error_total 없이 로그만으로도 충분합니다. 그 경우 error‑rate는 status 필드로 계산합니다.
체크아웃/ACP 메트릭
Next.js의 체크아웃 엔드포인트도 동일한 논리입니다: 핸들러를 타이머로 감싸고 상태를 집계합니다.
// app/api/checkout/route.ts
import { NextRequest, NextResponse } from "next/server";
import { logMetric } from "@/observability/metrics";
export async function POST(req: NextRequest) {
const startedAt = performance.now();
try {
const body = await req.json();
const result = await createCheckoutSession(body); // ACP/Stripe 호출
const duration = performance.now() - startedAt;
logMetric("checkout_latency_ms", duration, { status: "success" });
logMetric("checkout_total", 1, { status: "success" });
return NextResponse.json(result, { status: 200 });
} catch (error) {
const duration = performance.now() - startedAt;
logMetric("checkout_latency_ms", duration, { status: "error" });
logMetric("checkout_total", 1, { status: "error" });
return NextResponse.json(
{ error: "Checkout failed" },
{ status: 500 }
);
}
}
이제 checkout_latency_ms의 p95와 checkout_total의 error‑rate를 볼 수 있습니다. 이 SLI를 바탕으로 “p95 < 3초, error‑rate < 2%” 같은 SLO를 쉽게 세울 수 있습니다.
웹훅 메트릭
물론 웹훅도 마찬가지입니다. 어떤 메트릭이 중요한지(2절 참고)를 이미 이야기했으니, 이제 코드에서 어떻게 수집하는지 보겠습니다. 여기서는 시간뿐 아니라 성공 처리 여부가 특히 중요합니다: 그렇지 않으면 사용자가 결제했는데도 주문이 “paid”로 넘어가지 않을 수 있습니다.
// app/api/webhooks/payment/route.ts
import { NextRequest, NextResponse } from "next/server";
import { logMetric } from "@/observability/metrics";
export async function POST(req: NextRequest) {
const startedAt = performance.now();
try {
const payload = await req.text(); // 원시 페이로드
const sig = req.headers.get("stripe-signature") || "";
const event = verifyStripeSignature(payload, sig); // 서명 검증
await handlePaymentEvent(event); // 주문 상태 업데이트
const duration = performance.now() - startedAt;
logMetric("webhook_latency_ms", duration, {
type: event.type,
status: "success",
});
logMetric("webhook_total", 1, {
type: event.type,
status: "success",
});
return new NextResponse("ok", { status: 200 });
} catch (error) {
const duration = performance.now() - startedAt;
logMetric("webhook_latency_ms", duration, {
type: "unknown",
status: "error",
});
logMetric("webhook_total", 1, {
type: "unknown",
status: "error",
});
return new NextResponse("error", { status: 500 });
}
}
이 이벤트를 기반으로 다음과 같은 SLI를 정의할 수 있습니다:
- webhook success rate = success / (success + error);
- payment_succeeded에 대한 webhook_latency_ms의 p95.
그리고 이에 대한 SLO를 “7일 동안 웹훅의 99% 이상이 성공 처리, p95 < 500ms”처럼 명시할 수 있습니다.
4. 퍼센타일 통계: 한 걸음 더
우리는 이미 여러 번 p50/p95/p99에 의존했습니다. 이제 그것이 정확히 무엇을 의미하는지 좀 더 형식적으로 보겠습니다. 실제 운영에서는 퍼센타일을 메트릭 시스템이 계산하지만, 내부에서 무슨 일이 일어나는지 이해하는 것이 유용합니다.
퍼센타일 pX는 측정값의 X%가 그 값보다 낮게 위치하는 지점을 뜻합니다. 레이턴시 배열을 오름차순으로 정렬하면, p95는 “꼬리”, 즉 최대값 쪽에 가깝게 위치합니다. 코드(예: Node에서 특정 값 집합의 p95를 로컬로 계산하고 싶다면)는 대략 이렇게 구현할 수 있습니다:
// 간단한 퍼센타일 계산 함수
export function percentile(values: number[], p: number): number {
if (values.length === 0) return 0;
const sorted = [...values].sort((a, b) => a - b);
const index = Math.ceil((p / 100) * sorted.length) - 1;
return sorted[Math.max(0, Math.min(index, sorted.length - 1))];
}
이런 함수를 테스트나 간단한 스크립트에서 사용해 데이터로 놀아 보면서 p95가 평균과 얼마나 다른지 확인할 수 있습니다. 프로덕션에서는 Prometheus, Datadog, New Relic 같은 “어른”들이 이 기능을 담당합니다.
5. SLI, SLO, SLA: 쉽게 설명하기
세 글자 모두 겁나 보이지만 실제로는 아주 간단합니다.
SLI — Service Level Indicator
SLI는 구체적인 측정 지표, 즉 공식입니다. 예:
- 지난 24시간 동안 recommend_gifts 도구의 p95(latency);
- 지난 7일 동안 MCP 도구의 error‑rate;
- 한 주간 위젯 → 성공 결제 전환율.
SLI는 목표나 약속이 아니라, 그저 “체온계”입니다.
SLO — Service Level Objective
SLO는 SLI에 대한 목표, 즉 서비스 “건강” 조건입니다. 예:
- “p95(latency recommend_gifts) < 2초(7일 롤링 창)”;
- “모든 MCP‑tools의 error‑rate < 1%(30일 롤링)”;
- “체크아웃 API 가용성 ≥ 99.5%(분기)”;
- “위젯 → 성공 결제 전환율 ≥ 15%(월간)”
좋은 실천은 먼저 현재 수준을 측정하고, 이미 유지 가능한 수준보다 약간 더 엄격한 SLO를 설정하는 것입니다. 그렇지 않으면 “불가능 미션”이나 “이미 충분”이 되어 버립니다.
SLA — Service Level Agreement
SLA는 내부 목표가 아니라 사용자나 파트너와의 외부 계약입니다. SLA에는 의무(예: “99.9% uptime”)와 위반 시 결과(보상, 벌금, 구독 연장 등)가 명시됩니다. 대개 SLO는 SLA보다 더 엄격하여, “오류 예산”을 위한 여지를 둡니다.
학습용 GiftGenius 범위에서는 SLA가 필요 없겠지만, 아래 계단은 이해해 둡시다:
SLI → SLO → SLA
지표 → 목표 → 대외적 약속
Error budget(오류 예산)
Error budget은 쉽게 말해 허용 가능한 “비완벽함”의 양입니다. 만약 SLO가 “30일 동안 가용성 99.9%”라면, 0.1%가 오류 예산이며 다음에 “사용”할 수 있습니다:
- 다운타임이 있는 계획 릴리스;
- 실험;
- 예상치 못한 인시던트.
예산을 “다 써버렸다면”(예: 실제로 한 달 가용성이 99.5%였다면), 새 기능은 잠시 멈추고 안정성을 고쳐야 합니다.
6. GiftGenius를 위한 특수 메트릭: 커머스 + 웹훅
모든 내용을 모아 GiftGenius를 하나의 제품으로 바라봅시다.
퍼널과 전환
간단한 사용자 여정을 가정해 보겠습니다:
flowchart TD A[GiftGenius 위젯이 있는 App을 열었다] --> B[추천을 받음] B --> C[선물을 선택함] C --> D['결제로 이동'을 클릭] D --> E[결제 성공]
각 단계마다 이벤트를 로깅할 수 있습니다:
logMetric("funnel_step_total", 1, {
step: "widget_view",
});
logMetric("funnel_step_total", 1, {
step: "gift_selected",
});
logMetric("funnel_step_total", 1, {
step: "checkout_started",
});
logMetric("funnel_step_total", 1, {
step: "checkout_paid",
});
그다음 widget_view와 checkout_paid 단계의 이벤트 수를 알고 있으면 전환율을 계산할 수 있습니다: paid / view * 100%. 그리고 SLO를 “전환율 ≥ 10%”처럼 설정합니다. 전환율이 갑자기 3%까지 떨어졌는데, 기술적 SLI(latency/error‑rate)는 정상처럼 보인다면, 문제는 UX, 모델 지침(프롬프트), 상품 피드 품질일 가능성이 있으며, 인프라 문제는 아닐 수 있습니다.
전환의 일부로서 웹훅 메트릭
이미 웹훅의 기술 메트릭과 구현을 논의했습니다. 이제 그것을 전환과 연결하는 것이 중요합니다: 커머스 시나리오에서 웹훅은 매우 중요합니다. 사용자에게는 “결제가 완료”로 보이지만, 최종 주문 상태는 여러분의 백엔드가 payment_succeeded를 얼마나 빠르게 수신하고 처리하느냐에 달려 있습니다.
SLI (웹훅 기준):
- webhook success rate;
- webhook latency p95;
- 대략적 가용성 webhook_endpoint_availability.
웹훅의 success rate가 떨어지면, 여러분은 실제로 주문을 잃는 것입니다.
7. SLO 기반의 간단한 알럿
완성형 알림 시스템은 운영 쪽 주제에 가깝지만, 지금 당장 기초를 잡아둘 수 있습니다.
아이디어는 개별 오류마다 알림을 보내는 것이 아니라, SLO 위반에 대해 알림을 보내는 것입니다. 이는 흔히 symptom‑based alerts라고 하며 — 서비스 저하의 증상에 기반한 알럿입니다: “오류가 발생했다”가 아니라 “서비스가 약속한 수준보다 체계적으로 나빠졌다”에 관심을 둡니다.
전형적 예시:
- 최근 5분 동안 MCP 도구 error‑rate > 2% (SLO는 < 1%);
- 최근 10분 동안 recommend_gifts 레이턴시의 p95 > 3초(SLO는 2초);
- 최근 15분 동안 성공적인 checkout_paid가 하나도 없음 — 통합 장애 의심;
- 최근 10분 동안 webhook success rate < 95%.
알럿 메시지는 “Alert: metric 123 > 456” 같은 기계어가 아니라 사람 친화적이어야 합니다. GiftGenius의 “Slack 알림” 예:
[ALERT][GiftGenius] High error rate on MCP tools:
error_rate = 3.2% (>1% SLO) for last 5 minutes.
Impact: part of users cannot receive gift recommendations.
Actions: check MCP logs and external gift API health.
이런 메시지는 SLO와 연결되어 on‑call 개발자가 문제의 규모를 빠르게 파악하게 도와줍니다.
8. 미니 실습: GiftGenius를 위한 SLO를 정해 보자
우리 앱을 위한 SLO 세트를 정식화해 봅시다. 메트릭 시스템을 풀로 깔지 않아도, 종이에만 적어도 됩니다.
“시작용” 예시:
- 주요 MCP 도구 recommend_gifts에 대해:
- SLI: 최근 7일 간 성공 호출의 p95(latency).
- SLO: p95(latency) < 2초.
- MCP 도구 오류에 대해:
- SLI: error‑rate = errors / (errors + successes) (30일).
- SLO: error‑rate < 1%.
- 체크아웃 API에 대해:
- SLI: availability = 전체 요청 대비 HTTP 2xx 비율.
- SLO: availability ≥ 99.5%(월간).
- 결제 웹훅에 대해:
- SLI: webhook success rate.
- SLO: 7일 동안 웹훅 성공 처리 ≥ 99%; 처리 지연의 p95 < 500ms.
- 비즈니스 성과에 대해:
- SLI: 월간 위젯 → 유료 주문 전환율.
- SLO: 전환율 ≥ 10–15%(니치에 따라).
이 정도의 작은 세트만으로도 의사결정의 “골격”을 제공합니다: 새 모델 버전을 배포하거나, 프롬프트나 추천 알고리즘을 바꾸고, p95와 error‑rate가 SLO 범위 안에 있으면서 전환율이 상승했다면 — 아마도 실험은 성공적입니다.
자체 체크아웃 엔드포인트 대신 Instant Checkout을 사용한다면, “체크아웃 API”는 사실상 Agentic Checkout 호출(/checkout_sessions create/update/complete)이며, “결제 웹훅”은 OpenAI 방향의 order events(order.created, order.updated)입니다. 메트릭과 SLO 문구는 동일하고, 바뀌는 것은 구체적인 프로토콜뿐입니다.
9. 메트릭과 SLO 작업에서 흔한 실수
오류 1: 평균 응답 시간만 측정한다.
평균은 편리하지만 위험합니다. 느린 요청의 꼬리를 쉽게 가립니다. ChatGPT App에서는 이것이 치명적일 수 있습니다: 대부분의 사용자가 빠르게 응답을 받더라도, 소수 사용자에게 반복적으로 5–10초 지연이 발생하면 “앱이 항상 느리다”로 체감됩니다. 레이턴시에는 항상 최소한 p50과 p95를 사용하고, 평균(mean)만 보지 마세요.
오류 2: SLI, SLO, SLA를 문서와 머릿속에서 혼동한다.
가끔 개발자가 “우리 SLA는 p95 < 2초”라고 쓰는데, 이는 외부 사용자에게 어디에도 명시되지 않고, 어떠한 의무도 수반하지 않습니다. 실제로 이것은 SLO입니다. SLA는 위반 시 결과가 있는 고객과의 계약입니다. 이것들을 섞어 버리면, 여러분이 실제로 무엇을 누구에게 약속하는지 불분명해집니다.
오류 3: 알럿과 SLO의 연결 고리가 없다.
고전적 함정 — “모든 오류”마다, 모든 타임아웃마다, 메트릭이 0.01만 변해도 알림을 쏘는 것입니다. 그 결과 on‑call 엔지니어는 알림 지옥을 살게 되고, 결국 보지 않게 됩니다. 훨씬 유용한 접근은 SLO 위반에 대해 알럿을 만드는 것입니다: error‑rate가 목표 수준을 크게 초과하거나 p95가 경계 밖으로 “튀어나갔을” 때 사람을 깨우는 편이 낫습니다.
오류 4: 웹훅과 비동기 부분의 메트릭을 무시한다.
이미 이야기했듯, 웹훅과 비동기 처리를 무시하는 것은 흔한 문제입니다. 많은 팀이 주요 HTTP API 응답만 추적하고, 웹훅과 백그라운드 처리를 보지 않습니다. 커머스 시나리오에서는 바로 거기에 가장 불편한 버그가 숨어 있습니다: 결제는 완료되었지만 웹훅이 처리되지 않아 주문이 “멈춤”. 웹훅의 success rate와 latency 메트릭이 없으면, “다 잘 된다”고 오래 착각하다가 회계 숫자와 DB가 크게 어긋나기 시작할 수 있습니다.
오류 5: 비현실적 SLO 또는 SLO 부재.
가끔 SLO를 “100% uptime”이나 “오류 전무”처럼 정합니다. 실제로는 달성 불가능하고 팀을 좌절하게 만듭니다. 다른 극단은 아예 SLO를 정의하지 않고 “그럭저럭 괜찮다” 모드로 사는 것입니다. 황금률은 현재 SLI를 먼저 측정하고, 조금 더 엄격하지만 달성 가능한 목표를 세운 뒤, 시스템이 성숙해짐에 따라 점진적으로 강화하는 것입니다.
오류 6: 제품과 연결되지 않은, 형식적인 메트릭.
이런 경우도 있습니다: 메트릭 시스템에는 그래프가 가득하고, p95, p99, 수십 개의 대시보드가 있지만, “이 선이 튀면 무엇이 피해를 보나? 사용자? 매출? 평판?”이라는 간단한 질문에 아무도 답하지 못합니다. 특히 LLM 제품에서는 기술 지표(latency, error‑rate)를 비즈니스 메트릭(전환, 성공 결제)과 연결하는 것이 중요합니다. 그렇지 않으면 관측 가능성은 보기 좋지만 쓸모없는 TV가 되어버립니다.
GO TO FULL VERSION