메인으로
지유 · 최고기술책임자(CTO) · 오늘의 기술 칼럼

답이 흔들리는 자리는 프롬프트가 아니다

같은 질문에 어제와 다른 답이 나올 때, 우리는 대개 프롬프트를 들여다봅니다. 그런데 이번 달 서빙 엔진 릴리스를 읽으면 흔들리는 자리가 그 아래층에 있습니다.

초록 법률 답변에서 재현성은 취향이 아니라 요건입니다. 같은 질의에 다른 결론이 나오면 '왜 이 답이 나왔는가'를 사후에 설명할 수 없고, 설명할 수 없는 판단은 근거로 쓸 수 없기 때문입니다. 그런데 재현성을 깨뜨리는 변수는 프롬프트나 모델 이름보다 훨씬 아래에 있습니다. 본 칼럼은 vLLM v0.23.0 과 v0.24.0, LlamaIndex v0.14.23 의 변경 목록을 나란히 놓고, 샘플러 구현·기본 실행 경로·수치 정밀도·상태 초기화라는 네 층에서 같은 요청이 어떻게 갈라지는지를 확인합니다. 그리고 그 네 층을 기록하지 않으면 답변 로그가 재현 좌표로 기능하지 못한다는 점을 정리합니다.

장애 보고서에서 가장 자주 보는 문장은 '어제는 됐는데요'입니다. 법률 답변에서는 이 문장이 특히 무겁습니다. 같은 조문과 같은 판례를 주고 같은 질문을 했는데 결론이 달라지면, 두 답 중 하나가 틀렸다는 것보다 둘 중 어느 쪽이 왜 나왔는지 모른다는 것이 더 큰 문제이기 때문입니다. 그래서 우리는 프롬프트를 버전으로 묶고 검색 결과를 기록하고 모델 이름을 핀으로 박습니다. 그것으로 충분하다고 믿기 쉽습니다. 그런데 이번 달 서빙 엔진의 변경 목록을 읽으면 그 믿음이 한 층 얕다는 것이 드러납니다. vLLM v0.23.0 은 408 commits from 200 contributors 를, v0.24.0 은 571 commits from 256 contributors 를 담았고, 그 안에는 샘플러를 갈아 끼우고 기본 실행 경로를 넓히고 수치 정밀도를 손보는 변경이 함께 들어 있습니다. 우리가 아무것도 바꾸지 않아도 답이 흔들릴 수 있는 자리가 그만큼 있다는 뜻입니다.

핵심 기술 개념

샘플러 구현차(sampler implementation drift)

같은 온도·같은 시드라도 토큰을 고르는 코드가 다르면 결과가 갈릴 수 있다는 것. vLLM v0.23.0 은 Model Runner V2 에 FlashInfer sampler (#42472) 를 넣었고 ROCm 경로에서는 AITER top-k/top-p sampler 를 기본으로 켰다 (#43331). v0.24.0 은 more accurate FP32 Gumbel sampling (#45996) 과 V2 GPU 샘플러의 min_tokens off-by-one fix (#46243) 를 실었다. '더 정확해졌다'는 곧 '이전 결과와 달라진다'는 말이기도 하다.

기본 실행 경로의 이동(default path migration)

설정을 바꾸지 않았는데 실행되는 코드 경로가 바뀌는 것. v0.23.0 에서 Model Runner V2 는 Qwen3 에 더해 Llama and Mistral dense models 의 기본이 되었고 (#43458), v0.24.0 에서는 quantized models by default (#44446) 와 GraniteMoE by default (#45461) 로 범위가 더 넓어졌다. 기본값은 선택의 부재가 아니라 릴리스가 대신 한 선택이다.

상태 초기화 누수(state carry-over)

앞선 실행의 흔적이 다음 실행에 남아 결과를 바꾸는 것. 커널 층에서는 v0.23.0 의 zeroing of freshly allocated KV blocks for hybrid + FP8 KV cache (#43990) 가 그 자리이고, 오케스트레이션 층에서는 LlamaIndex v0.14.23 의 deep copy initial_state to prevent mutation leaks across runs (#21780) 가 같은 유형이다. 층은 달라도 증상은 하나다 — 단독으로 돌리면 재현되지 않는다.

기술 심층 분석

1

같은 시드로도 달라진다 — 고르는 코드가 바뀌기 때문에

재현성 논의는 보통 온도와 시드에서 멈춥니다. 온도를 0 으로 두면 결정적이고, 시드를 고정하면 같은 표본이 나온다는 전제입니다. 그런데 그 전제는 '토큰을 고르는 코드가 같다'를 조용히 깔고 있습니다. vLLM v0.23.0 은 Model Runner V2 에 FlashInfer sampler (#42472) 를 도입했고, ROCm 경로에서는 AITER top-k/top-p sampler 를 기본으로 켰습니다 (#43331). v0.24.0 은 여기에 more accurate FP32 Gumbel sampling (#45996) 을 더했습니다. 마지막 항목이 특히 정직한 이름입니다 — 더 정확해졌다는 것은 이전이 덜 정확했다는 뜻이고, 덜 정확했던 쪽으로 이미 나간 답변들이 있다는 뜻이기 때문입니다. 같은 릴리스에는 V2 GPU 샘플러의 min_tokens off-by-one fix (#46243) 도 있습니다. 경계값 하나가 어긋나 있었다는 것인데, 그 어긋남은 예외를 던지지 않고 그냥 '조금 다른 답'으로 나타납니다. 법률 답변에서 조금 다른 답은 조금 다른 결론이 아니라 다른 결론입니다.

2

기본값은 릴리스마다 넓어진다 — 내가 고르지 않은 경로

Model Runner V2 의 적용 범위가 두 릴리스에 걸쳐 어떻게 넓어졌는지를 보면 기본값의 성질이 드러납니다. v0.23.0 에서 MRv2 는 Qwen3 에 더해 Llama and Mistral dense models 의 기본이 되었고 (#43458), v0.24.0 에서는 quantized models by default (#44446) 와 GraniteMoE by default (#45461) 가 추가됐습니다. 우리 설정 파일에는 이 변화가 한 줄도 나타나지 않습니다. 업그레이드 한 번이 실행 경로를 갈아 끼우고, 그 경로는 자기만의 샘플러와 자기만의 그래프 캡처 방식을 갖습니다. 같은 릴리스에 breakable CUDA graphs (#44050) 가 함께 들어온 것도 같은 맥락입니다. 문제는 이 이동이 잘못이라는 것이 아닙니다. 대부분의 경우 더 빠르고 더 좋습니다. 문제는 언제 이동했는지 우리 기록에 남지 않는다는 것입니다. 답변 로그에 모델 이름만 적혀 있으면, 두 달 전 답을 재현하려 할 때 우리는 그때의 실행 경로를 복원할 수 없습니다.

3

정밀도는 성능 설정이 아니라 답의 일부다

양자화와 KV 캐시 dtype 은 보통 '메모리와 속도의 손잡이'로 분류됩니다. 그런데 v0.24.0 이 MRv2 에서 quantized models by default (#44446) 를 켠 것과 같은 릴리스에 FP8 KV-cache fix (#45720) 와 FlashMLA sparse accuracy fix (#36616) 를 함께 실은 것을 보면, 이 손잡이가 정확도 축에 직접 닿아 있다는 것을 알 수 있습니다. v0.23.0 의 compressed-tensors 쪽 변경도 같은 방향을 가리킵니다 — v0.24.0 에는 compressed-tensors KV-cache-scheme rejection (#45312) 이 들어 있는데, 어떤 조합은 아예 거부하는 편이 낫다는 판단입니다. 법률 답변의 관점에서 이것을 다시 쓰면 이렇게 됩니다. 정밀도를 낮추면 답이 '조금' 달라지는데, 그 조금이 인용 조문 번호의 마지막 자리이거나 결론 어미의 적극·소극일 수 있습니다. 그래서 정밀도는 배포 설정이 아니라 답변의 속성으로 기록해야 하는 값입니다.

4

상태가 새는 층은 커널만이 아니다

재현되지 않는 버그의 가장 흔한 정체는 '앞 실행이 남긴 것'입니다. 커널 층에서 그 자리는 v0.23.0 의 zeroing of freshly allocated KV blocks for hybrid + FP8 KV cache (#43990) 입니다. 새로 할당한 블록을 0 으로 채우지 않으면 이전 요청의 잔상이 섞일 수 있다는 것이고, 그 증상은 '가끔 이상한 답'입니다. 그런데 같은 유형이 훨씬 위층에도 있습니다. LlamaIndex v0.14.23 의 deep copy initial_state to prevent mutation leaks across runs (#21780) 은 워크플로의 초기 상태가 실행 간에 공유돼 오염되던 것을 고친 것입니다. 같은 릴리스의 preserve IndexNode obj during model dump (#21776) 와 match missing metadata for NE and NIN filters (#21785) 도 넓게 보면 한 부류입니다 — 값이 있는데 없는 것으로 읽히거나, 없어야 할 것이 남아 있는 자리입니다. 층이 달라도 진단법은 같습니다. 단독으로 돌리면 재현되지 않고, 순서를 바꾸면 나타납니다.

5

그래서 무엇을 기록해야 재현 좌표가 되는가

위 네 층을 합치면 '답변을 재현하는 데 필요한 최소 좌표'가 무엇인지 답이 나옵니다. 모델 이름과 프롬프트 버전만으로는 부족합니다. 최소한 서빙 엔진의 버전, 실제로 선택된 실행 경로(예: Model Runner V2 인지), 가중치의 양자화 방식, KV 캐시 dtype, 그리고 샘플링 파라미터와 샘플러 구현까지가 한 묶음이어야 합니다. vLLM v0.23.0 이 config validation rejecting 0/negative knobs (#43794, #44057, #44207) 를 넣은 것은 이 방향의 작은 신호입니다 — 의미 없는 설정을 조용히 받아들이지 않겠다는 것이니까요. 우리가 할 일은 그 다음입니다. 받아들인 설정을 답변 옆에 붙여 보관해야 합니다. 그러지 않으면 두 달 뒤 '이 답이 왜 이렇게 나왔나'라는 질문에 우리가 내놓을 수 있는 것은 추정뿐이고, 법률 서비스에서 추정은 근거가 아닙니다.

기술적 트레이드오프

긴장 관계 재현성을 최대로 하려면 실행 경로를 얼어붙여야 하는데, 그러면 릴리스마다 오는 정확도 개선과 성능 향상을 포기하게 됩니다. 반대로 항상 최신을 따라가면 답변은 점점 좋아지지만 어제의 답을 오늘 복원할 수 없습니다.

실무적 해소 둘 중 하나를 고르는 문제가 아니라 무엇을 언제 얼리는가의 문제로 바꾸는 것이 해법입니다. 실행 경로는 계속 최신을 따라가되, 답변마다 그때의 좌표(엔진 버전· 실행 경로·양자화·KV dtype·샘플러)를 함께 적어 두면 재현은 '그 좌표로 되돌아가는 일'이 됩니다. 즉 얼려야 하는 것은 실행 환경이 아니라 그 실행이 무엇이었는지에 대한 기록입니다. 기록이 있으면 업그레이드는 위험이 아니라 그냥 변경이 되고, 기록이 없으면 업그레이드는 매번 되돌릴 수 없는 사건이 됩니다.

이 주장이 틀리는 조건

반증 조건 샘플러 구현·기본 실행 경로·수치 정밀도·상태 초기화를 모두 고정했는데도 같은 요청의 결론이 계속 갈라지면 네 층을 원인으로 본 이 글의 진단은 틀린다. 반대로 이 네 층을 기록하지 않은 로그로도 어제의 답이 복원되는 경우, 재현 좌표라는 축도 성립하지 않는다. 판을 올렸을 때 결론 변동률이 프롬프트 변경보다 작게 관측된다면 층위 진단도 버려야 한다. 이 관찰 중 하나라도 확인되면 기록 처방을 철회한다.

법마디 OS에 적용한다면

법마디 OS 의 답변 경로는 조문·판례를 검증한 뒤 생성으로 넘기는 구조라, 검증 층이 잡아내는 것은 '없는 조문'이지 '같은 조문에 대한 다른 결론'이 아닙니다. 그래서 서빙 좌표가 기록되지 않으면 재현 불가능한 결론 차이는 어느 게이트에도 걸리지 않고 지나갑니다. 우선 할 일은 코드를 고치는 것이 아니라 지금 무엇이 기록되고 있는지 세는 것입니다. 답변 한 건을 열어 모델 이름 외에 서빙 좌표가 몇 개나 남아 있는지 확인하고, 비어 있는 자리를 목록으로 만듭니다. 그다음이 배선입니다. 그리고 업그레이드 때는 같은 질의 묶음을 전후로 돌려 결론이 갈린 항목만 사람이 봅니다 — 전부를 보려 하면 아무도 안 보게 되기 때문입니다. 이 순서를 지키면 '어제는 됐는데요'가 장애 보고가 아니라 좌표 조회로 바뀝니다. 계획은 계획으로 적습니다 — 지금 이 글에 적힌 것 중 구현된 것은 없습니다.

기술적 함의

"재현성은 기능이 아니라 기록의 문제입니다. 서빙 스택은 우리가 손대지 않아도 계속 움직이고, 그 움직임은 대개 개선입니다. 개선을 막을 이유는 없습니다. 다만 답변 하나 옆에 그때의 좌표가 없다면, 우리는 그 답을 다시 만들어 낼 수도 틀렸다고 증명할 수도 없습니다. 법률 서비스에서 그것은 성능 문제가 아니라 신뢰 문제입니다."

참고 자료

칼럼니스트

지유

지유

최고기술책임자 (CTO · Chief Technology Officer)

실리콘밸리 유니콘 창업 멤버급 / AI 무결성 검증 분야 세계적 석학급

법마디 OS 무료로 경험하기
본 칼럼은 법마디 OS 기술팀의 관점이며, 특정 제품·기술에 대한 보증이나 법률 자문이 아닙니다.