무색
기술블로그
에세이
연구
소개

무색

소프트웨어로 비즈니스의 가능성을 만듭니다. 웹·앱 개발, 음성 AI, 자동화 콘텐츠 제작까지 — 기술이 필요한 곳에 무색이 있습니다.

연락처

contact@museck.com

사업자 정보

상호: 무색

대표: 배성재

사업자등록번호: 577-58-00836

인천광역시 연수구 인천타워대로 323, 에이동 8층 801-802호 AB-132 (송도동, 송도 센트로드)

© 2026 무색. All rights reserved.
개인정보처리방침·이용약관·연락처
INCHEON, KR
100페이지 논문 번역이 40분 걸릴 때: LLM 동시성과 재시도 전략 — bauhaus key visual
논문 번역기
2026. 1. 10.

100페이지 논문 번역이 40분 걸릴 때: LLM 동시성과 재시도 전략

vLLMLLMBabelDOC번역성능튜닝

BabelDOC에 커스텀 번역 모델을 붙이고 나서 처음 돌린 논문이 267문단짜리 100페이지 PDF였다. 결과가 나올 때까지 40분. 번역 품질 이전에 속도부터 문제였다.

병목을 파보니 원인은 셋이었다. 기본 QPS가 4로 너무 낮았고, worker 수도 부족했으며, 빈 문단이나 수식 블록에서 번역이 실패하면 그냥 멈춰버렸다. 이걸 동시성 튜닝, 재시도 전략, 캐시 제어 세 방향으로 잡았다.

동시성 16배 올리기: QPS 4에서 64로

vLLM은 continuous batching을 지원한다. 요청이 들어올 때마다 배치에 끼워넣는 방식이라 동시 요청이 많아도 GPU 활용률이 높게 유지된다. 전통적인 웹 서버처럼 동시성을 조심스럽게 올릴 필요가 없다는 뜻이다.

그래서 과감하게 QPS를 4에서 64로, worker pool을 32개로 올렸다.

parser.add_argument("--qps", type=int, default=64)
parser.add_argument("--pool-max-workers", type=int, default=32)
parser.add_argument("--no-cache", action="store_true", help="Ignore translation cache")
parser.add_argument("--verbose", "-v", action="store_true")

다만 무턱대고 올리면 안 된다. QPS를 높이면 vLLM의 KV cache 사용량도 같이 뛴다. --gpu-memory-utilization 0.8과 --max-model-len 4096을 함께 조절하지 않으면 OOM이 난다. 처음에 이걸 몰라서 GPU 메모리가 터지는 바람에 한참 헤맸다.

Temperature Escalation: 재시도할 때 온도를 올려라

동시성을 올리고 나니 속도 문제는 해결됐는데 품질 문제가 남았다. 빈 문단이나 수식만 있는 블록을 번역하려다 실패하는 경우가 꽤 있었다. temperature 0.0에서 빈 응답이 나오면 같은 조건으로 재시도해봐야 또 빈 응답이다. deterministic한 생성이니까.

전통적인 API 재시도는 대기 시간을 늘리는 exponential backoff를 쓴다. 근데 LLM한테는 대기 시간이 문제가 아니라 생성 결과 자체가 문제다. 그래서 temperature를 재시도 변수로 쓰기로 했다.

재시도마다 temperature를 0.0 -> 0.2 -> 0.4 -> 0.6 -> 0.8로 올린다. 최대 5회까지. temperature가 올라가면 생성의 무작위성이 높아져서 이전과 다른 결과가 나올 확률이 올라간다. 빈 응답이 나왔던 문단도 temperature를 좀 올리면 정상적인 번역이 나오는 경우가 많았다.

이건 Exponential Backoff의 LLM 버전이라고 볼 수 있다. 대기 시간 대신 모델 파라미터를 조절하는 방식. Temperature Escalation이라고 부르기로 했다.

빈 콘텐츠 필터링과 캐시 분리

재시도 전에 아예 불필요한 번역 요청을 줄이는 게 먼저다. 공백만 있는 문단이나 수식 기호만 있는 블록은 번역 전에 걸러낸다. API 호출 자체를 안 하는 게 가장 빠른 최적화니까.

캐시도 손봤다. SQLite 기반 Cache-Aside 패턴으로 동일 문단의 재번역을 막는다. 캐시 키에 모델명, temperature, 프롬프트를 포함시켜서 조건이 바뀌면 자동으로 새로 번역한다.

원래 --debug 플래그 하나에 PDF 디버그 오버레이, 캐시 무시, 상세 로깅이 전부 묶여 있었다. 캐시만 끄고 싶은데 PDF에 오버레이가 덕지덕지 붙는 상황이 반복되니 결국 플래그를 분리했다. --no-cache와 --verbose를 독립 옵션으로 뺀 건 작지만 확실한 개선이었다.

if args.verbose:
    logging.basicConfig(
        level=logging.INFO,
        handlers=[
            logging.StreamHandler(),
            logging.FileHandler("glm_translate_debug.log", mode="w"),
        ],
    )
    logging.getLogger("babeldoc.translator").setLevel(logging.DEBUG)

LLM 애플리케이션 튜닝은 좀 다르다

이번 작업에서 느낀 건 LLM 기반 시스템의 성능 튜닝이 전통적인 웹 서비스와 꽤 다르다는 점이다.

웹 서비스에서는 동시성을 올리면 DB 커넥션이나 메모리가 병목이 된다. 하지만 vLLM 같은 추론 서버는 continuous batching 덕분에 동시성을 공격적으로 올려도 괜찮다. 대신 KV cache 메모리라는 전혀 다른 지점에서 병목이 온다.

재시도 전략도 마찬가지다. 전통적인 backoff는 서버 부하를 줄이려고 대기 시간을 늘리지만 LLM에서는 같은 입력에 같은 결과만 반복된다. temperature를 올려서 생성 자체를 바꿔야 한다.

정리하면 이렇다. 동시성과 모델 파라미터를 함께 고려해야 하고, 기존 패턴을 LLM 특성에 맞게 변형해야 한다. 40분 걸리던 번역이 수 분으로 줄었으니 방향은 맞았다고 본다.

자주 묻는 질문

vLLM continuous batching에서 QPS를 얼마나 올릴 수 있나요?
vLLM은 요청을 실시간으로 배치에 끼워넣는 continuous batching을 지원하므로 QPS를 공격적으로 올릴 수 있습니다. 다만 KV cache 메모리가 병목이 되므로 --gpu-memory-utilization과 --max-model-len을 함께 조절해야 OOM을 방지할 수 있습니다.
LLM 번역에서 빈 응답이 반복될 때 재시도 전략은?
Temperature Escalation 패턴을 사용합니다. 재시도마다 temperature를 0.0에서 0.2씩 올려 0.8까지 최대 5회 시도합니다. 같은 temperature에서는 deterministic하게 같은 결과가 나오므로 대기 시간이 아닌 모델 파라미터를 바꿔야 합니다.
LLM 번역 캐시를 어떻게 관리하면 효율적인가요?
SQLite 기반 Cache-Aside 패턴으로 캐시 키에 모델명, temperature, 프롬프트를 포함시킵니다. --no-cache와 --verbose를 독립 옵션으로 분리하면 캐시만 끄거나 로깅만 켜는 등 세밀한 제어가 가능합니다.
논문 번역기(2/8)
Prev

BabelDOC에 내 번역 모델 끼워넣기 (fork 없이)

Next

논문 번역에서 용어가 뒤죽박죽이라면: TranslateGemma + 마스터 용어 사전