동시성 제어 및 폴백 설계
채점 전용 스레드풀 격리 및 LLM 3단 폴백 재시도 구조
문제
채점 비동기 작업이 Spring의 기본 스레드풀(무제한 큐)을 사용하고 있었습니다. 동시 30명이 제출하면 스레드가 무한정 생성되어 메모리 초과(OOM) 위험이 존재했습니다.
또한 LLM 응답은 본질적으로 불안정합니다. 네트워크 타임아웃, JSON 파싱 실패, 모델 서비스 장애 등 다양한 실패 케이스가 있는데, 이런 실패가 그대로 사용자에게 노출되고 있었습니다. 채점 작업이 리포트 집계, 배지 발급 등 다른 비동기 작업과 같은 스레드풀을 공유하고 있어, 채점 폭증 시 다른 작업까지 영향을 받는 문제도 있었습니다.
해결
채점 전용 스레드풀(core 4, max 8, queue 64, AbortPolicy)을 분리했습니다. 자원 사용 상한을 설정하여 채점 작업이 아무리 많아도 시스템 전체 안정성에 영향을 주지 않도록 격리했습니다.
LLM 호출 실패에 대해서는 3단 복구 구조를 적용했습니다. 1단계로 지수 백오프 재시도를 수행합니다. 2단계로 JSON 파싱이 실패하면 보강 프롬프트로 재요청합니다. 3단계로 특정 모델이 계속 실패하면 기본 모델로 폴백합니다. 답안당 AI 호출 상한은 3회로 제한하여 무한 재시도를 방지했습니다.
성과
채점 작업이 리포트 집계, 배지 발급 등 다른 비동기 작업과 스레드를 경합하지 않도록 완전히 격리되었습니다.
LLM 단건 실패가 채점 실패로 이어지지 않는 복구 체계를 확보했습니다. 3단 폴백 구조 덕분에 일시적인 모델 서비스 장애 상황에서도 채점이 중단되지 않습니다.
회고
풀 설정을 yml 고정값으로 두어 조정할 때마다 배포가 필요한 점이 아쉬웠습니다. 프롬프트를 DB로 관리해 무배포 교체했던 것처럼, 운영 중 조정이 잦은 파라미터는 런타임 변경이 가능하게 설계해야 한다는 점을 배웠습니다.
Other Topics
LLM 자동 채점 파이프라인
Gemini, OpenAI, Claude 3사 12종 모델을 추상화한 논서술형 답변 자동 채점 시스템
트랜잭션 분리 설계
LLM 호출 트랜잭션 분리로 DB 커넥션 고갈 장애 해결
LLM 안전성 설계
환각, 형식 이탈, 프롬프트 인젝션 방어 체계 구축
AI 1인 개발 체계
Claude 스킬 기반 역할별 에이전트 하네스로 1인 풀스택 개발 체계 구축
AWS 인프라 및 CI/CD
ALB, private EC2, RDS, ElastiCache Redis 3노드 구성 및 월 비용 37% 절감
논서술형 풀이 활동 로그
문항별 진입/이탈/답변 변경 이력을 기록하여 학생의 풀이 과정을 추적하는 시스템
보안 설계
JWT 이중 인증, Rate Limiting, 요청 로깅 마스킹, 비밀번호 강제 변경 등 서비스 보안 체계 구축