대규모 다국어 사전 생성 작업을 수행할 때 가장 빈번히 발생하는 문제 중 하나는 언어 모델 API가 불안정하게 응답하거나 아예 에러를 반환하는 상황이다. 특히 Ollama와 같이 로컬 환경에서 모델을 직접 서비스할 때는, GPU 리소스 한계, 요청 과부하, 혹은 응답 포맷 불일치와 같은 다양한 문제가 동시에 나타날 수 있다. 이러한 문제를 단순히 재시도 로직만으로 해결하려 하면, 시스템이 멈추거나 무의미하게 자원을 소모하게 된다. 따라서 안정적이고 지속 가능한 사전 빌드를 위해서는 다층적인 방어 코드가 반드시 필요하다.
1. 세션 관리와 재시도 어댑터
기본적인 HTTP 요청을 매번 새로 열고 닫는 방식은 불필요한 비용을 발생시키고, 일시적인 네트워크 지연에도 민감하다. requests.Session을 사용하고, 여기에 Retry 어댑터를 붙여 429, 502, 503, 504 같은 상태 코드에 대해서는 자동으로 재시도를 수행하도록 설정하는 것이 안정성의 첫 걸음이다. 단, 이때 단순 반복이 아니라 **백오프(backoff)와 지터(jitter)**를 적용해야 한다. 이렇게 하면 동시 요청이 몰려도 응답률이 급격히 떨어지는 것을 완화할 수 있다.
2. 서킷 브레이커(circuit breaker) 패턴
연속적으로 실패가 발생하면, 계속 요청을 시도하는 것은 의미가 없다. 대신, 일정 횟수 이상 실패하면 일정 시간 동안 요청을 중단하는 서킷 브레이커 패턴을 적용할 필요가 있다. 예를 들어 8회 연속 실패 시 1분간 회로를 열어 두고, 그 이후에 다시 닫아서 시도하는 방식이다. 이렇게 하면 모델이 내부적으로 리셋되거나 GPU가 자원을 회수할 시간을 벌 수 있다.
3. JSON 파싱 방어
언어 모델은 종종 JSON 형식으로 답하지 않고, 코드블록이나 불필요한 텍스트를 포함한다. 따라서 첫 번째 중괄호만 추출하는 방식은 쉽게 깨진다. 대신, 응답 전체에서 가장 긴 JSON 블록을 찾아 파싱하거나, 코드블록을 제거한 뒤 파싱하는 전략을 적용해야 한다. 또한, 파싱 실패 시 단순히 무시하는 것이 아니라 “invalid_json” 같은 이유 코드를 남겨 후속 검토가 가능하도록 하는 것이 좋다.
4. 번역 및 폴백 전략
사전 생성 과정에서 모델이 번역을 실패하거나 빈 응답을 반환할 수도 있다. 이 경우 원문을 그대로 저장하고 [UNTRANSLATED:ko] 같은 태그를 남기는 방식이 권장된다. 이렇게 하면 전체 파이프라인이 끊기지 않고, 사전이 불완전하더라도 후처리 단계에서 문제 구간만 보완할 수 있다.
5. 실행 루프의 방어 코드
단어별·접두어별 반복 루프에서 모델 에러가 지속되면 전체 프로세스가 무한 대기에 빠질 수 있다. 이를 방지하기 위해, 브레이커가 열려 있는 동안에는 즉시 진행 상황을 저장하고 현재 반복을 중단하는 코드를 삽입해야 한다. 이렇게 하면 부분적으로라도 데이터가 저장되고, 이후 --resume 옵션으로 안정적으로 이어서 실행할 수 있다.
6. 운영적 고려사항
- 타임아웃 분리: 연결(connect) 타임아웃과 읽기(read) 타임아웃을 구분해 설정해야 한다. 예를 들어 연결은 5초, 응답은 40초로 나누면, 서버 응답이 느릴 때와 아예 접속 불가일 때를 구분해 대처할 수 있다.
- 프롬프트 최적화: 지나치게 긴 프롬프트는 모델 내부 처리 시간을 늘리고 실패 확률을 높인다. 불필요한 규칙을 줄이고 핵심만 남기는 것이 안정성을 높인다.
- 저장 주기 관리: 10개 접두어마다 진행 상황을 저장하도록 설정하면, 갑작스러운 중단에도 손실이 최소화된다.
결론
Ollama를 이용한 사전 생성은 단순히 모델을 호출하는 것 이상의 안정성 확보 전략을 요구한다. 세션 관리, 서킷 브레이커, 파싱 방어, 번역 폴백, 루프 제어를 체계적으로 적용하면 “어느 순간부터 계속 에러가 나는 상황”을 효과적으로 피할 수 있다. 결국 이러한 방어 코드는 단순한 예외 처리 차원을 넘어, 대규모 생성 파이프라인을 안정적으로 유지하는 핵심 아키텍처 요소라고 할 수 있다.