4.3 KiB
4.3 KiB
ADR-004
- 제목: LLM Gateway의 비동기 추론 구조 개선: OCR 및 추론 파이프라인 요청 처리 방식 전환
- 날짜: 2025-06-23
- 상태: 채택됨 (Proposed)
- 작성자: [김용연 연구원]
1. 컨텍스트 (Context)
기존 LLM Gateway에서는 /ocr, /extract/*,
/general/* 요청 처리 시 다음과 같은 문제가 발생하였다:
- Gateway가 OCR 결과를 최대 85초간 polling하여 기다린 뒤, 후속 작업(LLM 추론 또는 최종 결과 응답)을 수행
- 이 구조는 Gateway가 해당 요청을 점유한 상태로 유지되므로, 동시에 여러 사용자의 요청을 처리하기 어려워짐
- 클라이언트는 장시간 대기해야 하며, 요청 실패 시 다시 처음부터 재시도해야 하는 구조였음
2. 결정 (Decision)
LLM Gateway는 모든 OCR 및 LLM 요청을 비동기 백그라운드 처리
방식으로 전환하여, Gateway가 요청을 즉시 반환하고 작업은
asyncio.create_task()를 통해 처리되도록 구조를
개선하였다.
📌 asyncio.create_task()를 사용한 이유:
asyncio.create_task()는 FastAPI와 잘 통합되는 간단한 백그라운드 실행 방식으로,- Gateway의 요청 핸들러를 차단하지 않으면서
- 요청 수신 즉시 응답을 반환하고
- 이후 파이프라인 작업을 비동기 이벤트 루프에서 독립적으로 처리할 수 있게 한다.
FastAPI의
BackgroundTasks는 요청 스코프에 종속되어 작업 진행 중 연결이 끊기면 실행되지 않을 수 있는 단점이 있음.create_task()를 사용하면 상태 추적, 결과 저장 등 복합 처리가 필요한 OCR + LLM 파이프라인에도 유연하게 대응 가능.
📌 주요 변경 사항:
- 클라이언트 요청 시
request_id와progress_url만 응답 - 전체 파이프라인(OCR → LLM → 후처리)은 백그라운드에서 실행
- 최종 결과는 Redis에 저장되며, 클라이언트는 /progress/{request_id}를 통해 상태 및 결과를 직접 조회
✅ /ocr에서
요청
변경 전
- Gateway가 OCR API에 요청한 후, 최대 85초간 polling
- 완료 여부에 따라 최종 응답을 직접 반환
변경 후
Gateway는 OCR API에 요청만 전송하고 다른 작업 요청 수행
클라이언트에는 다음 정보만 반환:
request_id: OCR 작업 식별자status: 작업 접수message: 사용자 안내 문구status_check_url:/ocr/progress/{request_id}
클라이언트는 해당 URL로 결과 조회
✅
/extract/*, /general/*에서 요청
변경 전
Gateway가 내부에서:
- OCR API 요청 → 결과 polling
- 결과 수신 후 LLM API 요청
- 최종 결과 응답
변경 후
전체 파이프라인(OCR → LLM → 후처리)을
asyncio.create_task()로 백그라운드 비동기 실행Gateway는 즉시 아래 정보 응답:
message: 작업이 백그라운드에서 실행 중request_id: 상태 추적용status_check_url:/extract/progress/{request_id}
최종 결과는 Redis에 저장되고,
/extract/progress/{result_id}로 확인 가능
Client
│
├── POST /extract/outer (input + prompt)
│ ↓
│ Gateway → OCR → LLM → Result
│ ↓
└── return: request_id + progress URL
백그라운드 작업
├── OCR API 호출
├── 추출 텍스트 Redis 저장
├── LLM API 호출
└── 최종 결과 Redis 저장
3. 고려된 대안
- FastAPI BackgroundTasks 사용: → 요청 스코프와 연결되어 있어 상태 추적 및 작업 흐름 관리에 제한적
- Celery를 통한 전체 파이프라인 비동기화 → 복잡성 증가, 구현 부담이 커서 1차 개선으로는 적절하지 않음
- 기존 polling 방식 유지 + 타임아웃 설정 개선 → 구조적 병목 문제 해결 불가
4. 결과
- Gateway가 작업을 점유하지 않고 완전한 비동기 구조 확보
- 클라이언트 응답 속도 향상 및 사용자 경험 개선
- Redis 기반 상태 추적 및 결과 조회 API 완비
- 확장성 및 고부하 처리 능력 증가