대부분의 팀은 취향에 따라 로컬 또는 클라우드를 선택합니다. 세 가지 측정 지표는 어떤 설계 논쟁보다 빠르게 결론을 내립니다.
함정은 '로컬 우선(local-first)'을 아키텍처로 간주하는 것입니다. 그것은 예산 클래스 문제입니다. 모든 호출 지점에는 레이턴시 상한선, 비밀 경계, 그리고 오프라인 요구 사항이 있습니다. 이 세 가지를 명확히 하면 논쟁의 대부분은 사라집니다.
각 호출 지점에 대해 세 개의 프로브(probe)를 실행하세요. 하나의 판결을 출력하고 다음으로 넘어가세요.
첫 번째 프로브: 레이턴시 상한선 (the latency ceiling)
로컬 추론에는 네트워크 홉이 없습니다. 이것이 빠르다는 것과 같지는 않습니다. 토큰 생성은 벽 시계 시간(wall clock)을 지배하며, 사용자가 불편함을 느끼는 곳은 p95입니다.
실제 프롬프트 길이로 측정하세요. 'Hello'는 여러분의 작업 부하가 아닙니다. 한 번 워밍업한 후 최소 서른 번 실행하여 샘플링해야 합니다. 백분위수(Percentile)는 양이 필요합니다. 다섯 개의 샘플로는 아무것도 유용하게 알려주지 못합니다.
아래의 하네스(harness)는 제안입니다. 저는 이것을 여러분의 스택에 대해 실행해 본 것이 아니므로, 결과가 아닌 시작 형태로 간주하세요.
# triage.py — proposal, unexecuted here.
import json, time, urllib.request
...
백분위수 헬퍼 함수는 의도적으로 지루하게 유지됩니다. 코드가 작을수록 신뢰하기 쉽습니다.
def pct(samples, q):
ordered = sorted(samples)
idx = max(0, min(len(ordered) - 1, int(round(q * (len(ordered) - 1)))))
...
Ollama는 기본 포트로 11434를 사용하고, llama.cpp의 서버는 8080을 기본으로 합니다. 프로브를 실제로 실행하는 곳에 겨냥한 다음, 티켓에서 적어둔 상한선과 p95를 비교하세요.
여러분이 작성하지 않은 상한선은 요구 사항이 아닙니다. 그것은 느낌일 뿐입니다.
두 번째 프로브: 비밀 경계 (the secret boundary)
각 호출 지점에서 하나의 질문을 던지세요. 이 정확한 페이로드(payload)가 기기를 벗어날 수 있습니까?
티켓에는 세션 토큰이 담겨 있습니다. 로그에는 쿠키가 담겨 있고, 프롬프트에는 고객 식별자가 담겨 있습니다. 아무도 그것들을 제3자에게 전송할 의도가 없지만, 요청 본문(request bodies)에 끊임없이 나타납니다.
SECRET_HINTS = (
이것은 데이터 손실 방지 시스템이 아니라 스모크 테스트입니다. 명백한 사례는 잡아내지만 인코딩된 사례는 놓칩니다. 그래도 실행해 보세요. 왜냐하면 명백한 사례들이 프로덕션에 도달하는 경우이기 때문입니다.
히트가 서버 경로를 자동으로 차단하지 않습니다. 먼저 마스킹(redaction)이 필요합니다. 헤더를 제거하고, 식별자를 해시하며, 형태는 유지하세요. 그런 다음 다시 측정해야 합니다. 왜냐하면 프롬프트 크기가 방금 변경되었기 때문입니다.
## Probe three: 오프라인 테스트
Wi-Fi가 아니라 소켓을 끊으세요. 목표는 불안정한 실패(flaky one)가 아니라 결정론적 실패(deterministic failure)여야 합니다.
import socket
def with_sockets_dead(fn):
...
호출 지점(call site)을 이 가드 안에 넣어 실행해 보세요. 만약 예외가 발생하고 폴백 분기(fallback branch)가 없다면, 그것은 클라우드에 의존적이라는 의미입니다. 그건 허용됩니다. 아무도 기록하지 않았을 때만 문제가 됩니다.
오프라인 기능은 제품 결정 사항입니다. 또한 비용이기도 합니다. 로컬 전용 경로는 모델 저장소, 업데이트, 그리고 느린 기기를 위한 계획이 필요합니다.
## 판정 함수(verdict function)
세 개의 부울 값과 두 개의 숫자가 한 줄의 텍스트를 만듭니다. 그 한 줄이 전체 결과물입니다.
def verdict(p95_ms, budget_ms, hits, offline_ok):
if not offline_ok:
return "local-only: offline requirement"
...
| 오프라인 필요 여부 | 페이로드 내 비밀 정보 포함 여부 | 로컬 p95 vs 예산 | 판정(Verdict) |
| :--- | :--- | :--- | :--- |
| Yes | Either | Either | Local only |
| ... |
테이블은 의도적으로 직설적입니다. 실제 시스템에는 예외가 있으며, 모든 예외는 깨지는 숫자를 명시해야 합니다.
## 무료 서버가 행(row)을 얻는 경우
세 개의 행이
테이블의 서버 행을 테스트하는 데 사용하세요. 이 프롬프트를 로컬에서 사용했을 때와 비교하여 p95를 측정해 보세요. 측정값만 유지하고 열정적인 설명은 버리세요.
무료 용어는 변합니다. 플랜을 구축하기 전에 현재 할당량과 한도를 확인하세요. 저는 여기서 구체적인 숫자를 언급하지 않는데, 무료 티어의 숫자는 시간이 지나면 부정확해지기 때문입니다.
무료 티어는 측정 기준(measuring stick)으로 취급하고, 용량 계획(capacity plan)으로 취급해서는 안 됩니다.
## 명시할 가치가 있는 한계점들
노트북에서 측정한 로컬 지연 시간은 공유 호스트로 전이되지 않습니다. 콜드 스타트가 단발성 호출을 지배할 수 있으므로, 따뜻한(warm) 상태와 차가운(cold) 상태를 분리하여 테스트하세요. 30개의 샘플은 서비스 수준 목표(SLO)라기보다는 대략적인 p95를 제공합니다. 비밀 스캔은 키워드 매칭이며 인코딩된 페이로드는 놓칠 수 있습니다. 벽시계 시간(wall clock)은 답변 품질에 대한 아무것도 알려주지 않으며, 이는 별도의 평가 세트가 필요합니다.
또한 조용한 실패 모드도 존재합니다. 잘못된 답변을 400ms 만에 하는 로컬 모델이 정확한 답변을 900ms에 제공하는 서버 호출보다 더 나쁠 수 있습니다. 숫자를 최적화하기 전에 품질을 측정하세요.
## 누가 이것을 건너뛰어야 하는가
엄격한 데이터 거주지 규칙(data-residency rules)을 가진 팀은 무료든 아니든 어떠한 제3자에게도 페이로드를 전송해서는 안 됩니다. 용량을 소유하지 않으면서 엄격한 지연 시간 SLO를 약속하는 스타트업 역시 무료 서버에 의존해서는 안 됩니다. 그리고 이미 유휴 GPU 하드웨어를 보유하고 있는 팀은 단순히 측정만 하고 논쟁 자체를 건너뛰어야 합니다.
이 워크플로우는 중간 단계의 사람들을 위한 것입니다. 실제 프롬프트, 실제 상한선(ceiling), 그리고 강력한 사전 지식(prior)이 없는 사람들이 대상입니다.
세 가지 숫자를 적으세요. 그러면 벤더 질문이 훨씬 쉬워질 겁니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31