따로 잰 건 같이 잰 게 아니다, 그리고 가동률 3%

띵킹을 오프라인 세트로 재고 효과 없음이라 결론 냈다가 다단계 세트에서 역전. 그 사이 측정한 적 없는 조합이 프로덕션에 들어갔다. max_tokens 상한은 예산이 아니라 차단기였고, 넉 달 튜닝한 장비의 가동률은 3%였다

집에 둔 GPU 장비에 로컬 모델을 직접 서빙하고 있고, 이날은 그 서버의 최종 설정을 확정하는 날이었다. 남은 변수는 띵킹이었는데, 항상 켜져 있고 추론 텍스트가 길어 지연의 큰 몫을 차지하면서도 그 값어치를 잰 적이 없었다. 오프라인 세트로 재서 효과 없음이라 결론 내고 프로덕션에 넣었고, 그 조합을 정말 잰 게 맞느냐는 질문이 남아 있었다.

하려던 것

실험이 끝났으니 최종 설정을 확정할 차례였다. 남은 질문 하나가 띵킹이었다. 항상 켜져 있고 추론 텍스트가 중앙값 2,490자다. 지연의 큰 몫인데 품질에 값어치가 있는지 잰 적이 없었다.

어떻게 시켰나

오프라인 시나리오 세트로 띵킹 ON과 OFF를 비교했다. 35/40 대 35/40 동점. “효과 없음”으로 결론 내고, 띵킹을 끄고 실험에서 이긴 새 시스템 프롬프트를 얹어 프로덕션에 넣었다.

미검증 조합 테스트한 거야? 그래서 띵킹은 어떻게 할 건데?

어디서 막혔나

Claude Code의 답이 자백이었다. 시스템 프롬프트 실험은 띵킹 ON에서 돌았고, 띵킹 실험은 새 프롬프트 없이 돌았다. 새 프롬프트에 띵킹 OFF 조합은 한 번도 측정된 적이 없었다. 그 미검증 조합이 방금 프로덕션에 들어간 것이다. 재 보니 상식 이탈 지적이 4/5에서 0/5로 떨어졌다. 즉시 되돌렸다.

띵킹 결론 자체도 틀려 있었다. 오프라인 세트는 띵킹이 개입할 자리가 없는 문제들이었다. 잴 수 없는 세트로 재고 효과 없음이라고 한 것이다. 다단계 추론 세트를 새로 만들어 다시 쟀다. 현금흐름 부호가 마이너스 400억인 문제, 지배주주 순이익에 지분율을 곱해야 하는 문제, 사이클 산업의 PER 함정. OFF 56/60 대 ON 60/60. 틀린 세 문제가 전부 함정 문제였다. 띵킹은 유지로 확정했다. 지연은 12초에서 28초로 늘지만 그 값어치가 있었다.

다음 날 max_tokens에서 같은 실수를 한 번 더 했다. 용도별 프리셋 네 개를 만들면서 실측 생성 길이의 두 배로 상한을 조였다. 그러면서 종합 프리셋이 4,000에서 잘리고 있었다는 걸 발견했다. 여유가 0%였다. 잘린 답은 오답으로 안 보이고 짧아 보인다.

그래도 적은 거 아니야? 왜 그렇게 제한하는 거야?

어떻게 풀었나

상한이 정말 비용인지 쟀다. 상한 200과 32,000에서 같은 요청을 던지니 지연 중앙값이 1.04초와 1.00초로 같았다. vLLM v1은 KV 캐시를 생성하면서 할당하므로 상한은 예약이 아니다. 생성 길이는 입력이 아니라 과제가 정하고, 입력을 14배 늘려도 생성은 평평했다. 상한은 예산이 아니라 차단기였다. 조일 이유가 없어서 실측의 네 배로 풀었다. 진짜 위험은 상한이 아예 없던 분석 프리셋이었다. 폭주하면 한 요청이 26만 토큰까지 GPU를 붙잡는다.

여기까지가 설정이다. 마지막으로 이 장비가 실제로 얼마나 일하는지 봤다.

값
GPU 평균 사용률30.4%
평균 전력21W (유휴 12.5W)
실효 생성9.3t/s
장비 능력339t/s
가동률약 3%

4월에 이미 답이 나와 있었다. 배치 클라이언트에 대해 “트래픽은 여기에 맞춰서 3개만 일단 해둔 거”라고 내가 적었다. 공시 요약 서비스가 요청을 순차로 보내고 있어 평균 지연이 53.1초다. 동시 16으로 보내면 같은 일이 훨씬 빨리 끝난다. 넉 달 동안 성능을 튜닝했는데 병목은 성능이 아니라 일감이었다.

배운 점