챕터 6

비용·지연 설계 — LLM 파이프라인에 결정모델 끼워넣기

결정모델을 앞단에 두고 LLM을 뒤로 물리면 같은 파이프라인이 훨씬 싸고 빨라집니다. 하이브리드 구조로 지연과 단가 이득을 실제 숫자로 계산하고, 병렬 배칭·레이트리밋 백오프·신뢰도 폴백·컨텍스트 한계까지 프로덕션에서 걸리는 지점을 정리합니다. 이 장을 마치면 어느 단계에 결정모델을 끼워 비용을 줄일지 설계할 수 있습니다.

앞단은 싸게, 뒤단만 비싸게

5장에서 스코어링·추출·안전 점검처럼 구조화된 출력이 필요한 작업들을 봤습니다. 이제 그 조각들을 하나의 파이프라인으로 엮을 차례입니다. 핵심 질문은 하나입니다. 비싼 LLM을 언제 부르고, 언제 부르지 않을 것인가.

답의 골격은 이미 앞 장들에 있습니다. 들어오는 요청 전부를 LLM에 태우지 말고, 값싼 결정모델이 앞에서 걸러 꼭 필요한 것만 뒤로 넘기는 구조입니다. LangChain 공식 블로그도 "개방형 추론·생성에는 LLM을, 그 과정의 빠르고 구조화된 결정에는 Jev를" 쓰라고 정리합니다.

결정모델이 문지기, LLM이 전문가

파이프라인을 사람 조직에 비유하면 이해가 빠릅니다. 결정모델은 접수 창구입니다. 들어온 요청을 분류하고, 위험한 것을 차단하고, 어느 부서로 보낼지 정합니다. LLM은 그 안쪽의 전문가라서, 창구가 넘겨준 소수의 요청에만 시간을 씁니다.

Jev (TypeSafe AI)가 이 창구 역할을 맡으면, 실제 LLM 호출량이 눈에 띄게 줄어듭니다. 스팸·중복·단순 조회처럼 굳이 문장 생성이 필요 없는 요청이 앞에서 정리되기 때문입니다. 모델 티어를 고르는 라우팅도 같은 자리에서 일어납니다. 요청 복잡도를 Score로 채점해 저비용 모델과 고성능 모델을 가르고, 여러 LLM을 오가는 OpenRouter 같은 게이트웨이 앞에 결정모델을 세워 "어디로 보낼지"를 값싸게 판정하는 식입니다.

코드가 제어 흐름을 소유한다

TypeSafe 문서가 반복해서 강조하는 설계 원칙이 있습니다. "코드가 결정론적 작업을 처리하고 제어 흐름을 소유한다. 모델은 시스템이 프로그래밍 가능한 상식을 필요로 하는 지점에만 등장한다."

즉 파이프라인의 뼈대는 코드가 잡습니다. 결정모델은 "이 문의가 긴급한가", "이 도구 호출이 위험한가" 같은 의미적 판단만 맡고, 그 결과를 받아 실제로 분기하고 액션을 실행하는 것은 코드입니다. 환불 처리 예시로 보면 (1) 관련 맥락으로 state를 구성하고 (2) 독립 질문들을 한 번의 호출로 병렬 요청한 뒤 (3) 코드에서 결정론적 체크와 결합해 자동 처리 또는 사람 검토로 라우팅합니다.

숫자로 계산하는 이득

이 구조가 왜 이득인지는 지연과 단가를 나란히 놓으면 분명해집니다. 결정 한 건을 LLM으로 처리할 때와 결정모델로 처리할 때의 공식 수치는 다음과 같습니다.

지연과 단가를 나란히 놓으면

항목 결정모델 (Jev) 비교 LLM
응답 지연(종단 간) 70~500ms 3~329초
상대 속도 기준 40~200배 느림
입력 단가(100만 토큰) $0.042 $0.20~$10
출력 단가 무료 별도 과금
모델 버전 jev-1.13.0 모델별 상이

Jev 지연 70~500ms · 입력 100만 토큰당 $0.042 · 출력 무료 (typesafe.ai)

숫자가 커지는 지점은 트래픽입니다. 결정 한 건의 절대 비용은 어느 쪽이든 크지 않지만, 같은 판단을 초당 수백·수천 건 반복하면 40~200배의 속도 차와 수 배~수백 배의 단가 차가 그대로 청구서와 응답시간에 반영됩니다. 앞단 필터로 LLM 호출 자체를 줄이는 이유가 여기 있습니다.

병렬 배칭 — 한 번에 묻기

같은 state에 여러 질문을 던질 때는 콜을 쪼개지 말고 한 요청에 묶어야 합니다. TypeSafe 문서가 공개한 실측이 이 차이를 못박습니다.

GDPR 문서에 13개 질문: 배치 1콜 $0.000497 / 0.27초 vs 개별 13콜 $0.006090 / 2.71초 → 약 12.2배 저렴, 10배 빠름 (docs.typesafe.ai)

이유는 단순합니다. 긴 문서가 모든 요청의 토큰을 지배하는데, 질문을 13번 따로 부르면 그 문서를 13번 지불하고, 한 번에 묶으면 한 번만 지불합니다. 질문들은 한 요청 안에서 독립적·병렬적으로 평가되므로 순서도 무관하고, 질문을 하나 더 붙여도 응답 시간은 거의 늘지 않습니다. 추가되는 것은 그 질문 자체의 적은 토큰 비용뿐입니다.

레이트리밋에 부딪히는 지점

싸고 빠른 대신, 대량으로 밀어 넣다 보면 한도에 걸립니다. 프로덕션 설계에서 가장 먼저 대비해야 할 실무 이슈입니다.

250k·1,200, 그리고 429

공식 한도는 초당 250,000 토큰, 분당 1,200 요청입니다. 이를 넘기면 429 Too Many Requests가 돌아오고, 에러 메시지는 "Back off and retry after a short delay"로 안내합니다.

레이트리밋: 250,000 tokens/sec · 1,200 requests/min, 초과 시 429 (docs.typesafe.ai)

지수 백오프와 큐

문서의 권장은 명확합니다. 429나 529(Overloaded) 응답을 받으면 즉시 재시도하지 말고 지수 백오프(재시도 간격을 점점 늘리는 방식)로 다시 시도하라는 것입니다. 공식 SDK는 기본적으로 백오프 재시도와 retry-after 헤더 처리를 자동으로 해 줍니다.

직접 HTTP를 호출한다면 이 로직을 손으로 넣어야 합니다. 실무에서는 앞단에 큐를 두고 유입 속도를 한도 안으로 눌러 주는 편이 안전합니다. 앞서 본 배칭도 레이트리밋 완화책으로 쓸모가 있습니다. 질문을 묶으면 요청 건수 자체가 줄어 분당 1,200 요청 한도에 여유가 생깁니다.

한도는 고정값이 아니다

한 가지 더 주의할 점은 이 한도가 상수가 아니라는 것입니다. 문서는 레이트리밋이 "수요에 따라 동적으로 조정되며 예고 없이 변경될 수 있다"고 명시합니다. 출시 초기 수요가 몰려 API가 일시적으로 서비스 불가였다는 보도도 이 설명과 맞물립니다. 더 높은 한도는 엔터프라이즈 플랜(sales@typesafe.ai)으로 열립니다. 즉 429를 예외가 아니라 정상 경로의 일부로 보고 처리 코드를 짜 두어야 합니다.

확신이 낮을 때 어디로 보낼까

결정모델이 앞단을 지킨다고 해서 모든 판단을 자동으로 흘려보내면 안 됩니다. 애매한 건은 뒤로 넘기는 폴백 경로가 필요합니다.

신뢰도 3단계 밴드

TypeSafe 문서는 신뢰도를 세 구간으로 나눠 운영하라고 안내합니다.

신뢰도 처리 방식
높음 자동 실행
중간 확인 요청·검토 플래그·추가 정보 수집
낮음 실행하지 않고 사람에게 라우팅 또는 다른 시스템으로 폴백

"지능형 시스템이 정직한 불확실성을 표현하지 못하면 신뢰할 수 없다"는 것이 이 설계의 전제입니다. 여기서 하이브리드 구조가 다시 맞물립니다. 낮은 신뢰도의 폴백 대상이 곧 뒤단의 LLM이거나 사람 검토자입니다. 다만 문서 자체는 폴백처를 "다른 시스템"이라고만 표현하고 LLM 에스컬레이션을 명시하지는 않습니다. LLM으로 넘기는 구체적 연결은 LangChain의 하이브리드 패턴에서 나온 해석으로 보는 편이 정확합니다.

임계값은 하나의 숫자가 아니다

밴드의 경계값을 어디에 둘지는 작업의 중대성에 따라 달라집니다. 문서는 "같은 시스템 안에서도 결과의 중대성에 따라 액션별로 다른 임계값을 적용하라"고 안내합니다. 예를 들어 기본은 0.5를 바닥으로 두더라도, 백업 삭제처럼 되돌릴 수 없는 작업은 0.9 이상으로 더 높게 잡는 식입니다.

보편적으로 통하는 임계값은 없습니다. 문서도 "정확한 임계값은 도메인과 모델 성능에 의존하므로 보수적으로 시작해 조정하라"고만 말합니다. 신뢰도가 보정됐다는 것도 예측 그룹 단위의 성질이지 개별 답의 정답을 보장하는 것은 아니므로, 임계값은 실제 데이터로 검증하며 맞춰 가야 합니다.

설계할 때 걸리는 한계들

이득이 큰 구조지만 넘을 수 없는 제약도 분명히 있습니다. 파이프라인을 그리기 전에 미리 알아 두어야 나중에 다시 뜯지 않습니다.

64k 컨텍스트와 텍스트 전용 입력

요청당 컨텍스트는 최대 64k 토큰이고, 그중 state와 질문을 합쳐 32k까지입니다. 긴 문서 전체를 한 번에 넣기 어렵다면 앞단에서 쪼개거나 요약해 태워야 합니다. 그리고 입력은 텍스트 전용입니다. 문자열·JSON 객체·텍스트 배열은 받지만 이미지·오디오·비디오는 아직 지원하지 않으므로, 멀티모달 입력이 필요한 판단은 다른 단계에서 텍스트로 변환한 뒤 넘겨야 합니다.

한 가지 더, state에 결정과 무관한 내용을 잔뜩 실으면 정확도가 떨어진다고 문서가 경고합니다. 컨텍스트는 넉넉히 채우는 대상이 아니라 판단에 필요한 만큼만 담는 대상입니다.

캐싱은 아직 공식 경로가 아니다

LLM 파이프라인이라면 프롬프트 캐싱으로 반복 비용을 깎는 경우가 많습니다. Jev는 사정이 다릅니다. 공식 문서(api·models·state·parallel_questions)에는 프롬프트 캐싱이나 응답 캐싱에 대한 명시적 가이드가 없습니다. 현재 문서가 제시하는 유일한 효율화 수단은 앞서 본 병렬 배칭입니다.

따라서 반복 요청을 줄이고 싶다면 캐싱을 기대하기보다 애플리케이션 층에서 직접 결과를 캐시하거나, 질문을 배치로 묶어 콜 수를 줄이는 쪽을 먼저 설계하는 편이 안전합니다. 공식 캐싱 기능이 나온다면 그때 붙이면 됩니다.

정리

결정모델을 앞단에 세우면 같은 파이프라인의 지연과 비용이 함께 내려갑니다. 값싼 판단이 대부분을 걸러 내고, 비싼 LLM은 꼭 필요한 소수 요청에만 붙기 때문입니다. 여기에 병렬 배칭으로 콜을 줄이고, 429에는 지수 백오프로 대응하며, 낮은 신뢰도는 폴백으로 넘기고, 64k·텍스트 전용이라는 한계 안에서 state를 설계하면 프로덕션에서 무너지지 않는 구조가 됩니다.

다음 장에서는 시리즈를 마무리하며 실제 착수를 다룹니다. console.typesafe.ai 가입과 API 키, Playground와 최소 요청 예시, 스키마 설계, 그리고 레이트리밋·신뢰도 정책·버전 관리를 담은 프로덕션 체크리스트까지 "시작하기"를 정리하겠습니다.