트랜잭션 분리 설계
LLM 호출 트랜잭션 분리로 DB 커넥션 고갈 장애 해결
문제
채점 시 LLM 응답 대기 시간은 수 초에서 수십 초에 이릅니다. 이 시간 동안 트랜잭션이 열려 있으면 HikariCP 커넥션(풀 크기 15개)을 장기 점유하게 됩니다.
문제는 채점이 몰리는 시점에 발생했습니다. 30명의 학생이 동시에 답안을 제출하면, 15개의 커넥션이 모두 LLM 응답을 기다리며 점유됩니다. 이 상태에서 학생 앱의 일반 API(로그인, 마이페이지 조회 등)도 커넥션을 할당받지 못해 응답성이 전체적으로 저하되는 운영 장애 위험이 존재했습니다.
해결
핵심 아이디어는 '외부 API 대기 중에는 DB 커넥션을 점유하지 않는다'입니다. 전체 채점 과정을 세 단계로 분리했습니다.
첫 번째 단계에서 채점 대기 행을 REQUIRES_NEW 트랜잭션으로 선커밋합니다. 이 시점에서 DB에 '채점 진행 중' 상태가 기록되고 커넥션은 즉시 반환됩니다.
두 번째 단계에서 LLM을 호출합니다. 이 호출은 트랜잭션 밖에서 수행되므로, 수 초에서 수십 초가 걸리더라도 DB 커넥션을 점유하지 않습니다.
세 번째 단계에서 LLM 응답 결과를 다시 REQUIRES_NEW 트랜잭션으로 반영합니다. 또한 문항 단위로 실패를 격리하여, 한 문항의 채점 실패가 챕터 전체 채점을 막지 않도록 설계했습니다.
성과
LLM 대기 중 DB 커넥션 점유가 0건으로 줄어 장애 재발을 완전히 차단했습니다.
문항 단위 실패 격리를 통해, 특정 문항에서 LLM 호출이 실패하더라도 나머지 문항의 채점은 정상적으로 완료됩니다. 실패한 문항은 FAILED 상태로 기록되어 관리자 화면에서 확인하고 재처리할 수 있습니다.
회고
MySQL REPEATABLE READ 스냅샷 특성상 큰 트랜잭션 안에서는 선커밋된 행이 보이지 않아 중복키 롤백이 발생할 수 있다는 것을 장애를 통해 학습했습니다.
이 경험을 통해 외부 API 호출이 포함된 트랜잭션은 반드시 분리해야 한다는 원칙을 세웠습니다. DB 커넥션은 유한한 자원이고, 외부 시스템의 응답 시간은 통제할 수 없기 때문입니다.
Other Topics
LLM 자동 채점 파이프라인
Gemini, OpenAI, Claude 3사 12종 모델을 추상화한 논서술형 답변 자동 채점 시스템
동시성 제어 및 폴백 설계
채점 전용 스레드풀 격리 및 LLM 3단 폴백 재시도 구조
LLM 안전성 설계
환각, 형식 이탈, 프롬프트 인젝션 방어 체계 구축
AI 1인 개발 체계
Claude 스킬 기반 역할별 에이전트 하네스로 1인 풀스택 개발 체계 구축
AWS 인프라 및 CI/CD
ALB, private EC2, RDS, ElastiCache Redis 3노드 구성 및 월 비용 37% 절감
논서술형 풀이 활동 로그
문항별 진입/이탈/답변 변경 이력을 기록하여 학생의 풀이 과정을 추적하는 시스템
보안 설계
JWT 이중 인증, Rate Limiting, 요청 로깅 마스킹, 비밀번호 강제 변경 등 서비스 보안 체계 구축