
→ retry_count ,last_retry_at ,last_error 은 질문 생성 재시도 로직에서만 사용
retry_count→ 지금까지 재시도된 횟수 카운트
- 재시도 횟수는 3회로 설정
last_retry_at→ 마지막으로 재시도 버튼을 누른 시각
- 사용자가 버튼을 연타할 때
last_retry_at기반으로 "1분 내 재시도 금지" 제약 구현 (쿨다운을 위해서)last_error→ 직전 실패 사유 (ML 응답 오류, 타임아웃, 예외 메시지 등)
→ CRUD 같은 일반 질문 등록·조회·좋아요·스크랩 같은 기능에는 전혀 관여하지 않음
(A) 진입 검증 단계 – “재시도 가능한지 판단”
status == FAILED 인지 체크 (아니면 409)last_error 접두로 판정ML_400, ML_401, ML_403, ML_404, VALIDATION 등 → 즉시 409 (“데이터/권한 문제로 재시도 불가”)retry_count >= retryMaxCount(기본 3) → 409now() < last_retry_at + cooldown(기본 60초) → 409(남은 초 안내)이 단계에서 읽는 컬럼: status, retry_count, last_retry_at, last_error
(B) 재시도 시작 단계 – “실행 전 상태 전환”
retry_count = retry_count + 1last_retry_at = now()last_error = null (새 시도이므로 직전 실패 사유 초기화)이 단계에서 쓰는 컬럼: retry_count, last_retry_at, last_error(null로 초기화), status
status = READY (세 메타는 그대로 둠)last_error = "ML_4xx: <요약메시지>" → 이후 재시도 진입 시 즉시 차단 근거last_error = "TIMEOUT: 3s exceeded" 또는 "ML_5xx: ..." → 재시도 허용(쿨다운·상한에만 걸림)status = FAILED 로 반영이 단계에서 쓰는 컬럼: last_error, status
READY → 새로 만들지 않음 → 409 ConflictGENERATING 진행 중 → 기존 진행 건 공유 → 200 OK + questionIdFAILED 존재 → 자동 재시도 안 함 → 200 OK + questionId (FAILED 상태 → 재시도 버튼 안내)GENERATING, userNickname='GPT') → 201 CreatedREADY 업데이트 후 201GENERATING 상태로 questionId 반환(201), 이후 백그라운드에서 계속 진행POST /api/books/{bookId}/generate-questionREADY → 이미 존재 → 409 ConflictGENERATING → 진행 중 → 200 OK (questionId 반환)FAILED → 자동 재시도 안 함 → 200 OK (FAILED 상태 반환)status=GENERATING으로 row 생성READY 저장, 201 CreatedGENERATING 반환, 201 Created@Async)로 ML 호출 이어서 진행READY 업데이트FAILED 업데이트FAILED인 경우 → UI에서 “재시도” 버튼 노출이렇게 로직을 작성하였다. 하지만 여기서 의문점이 들었다. 생성과 생성 재시도는 어떤 차이가 있을까?
우선 생성과 재시도 모두 authenticated() 설정을 통해서 보호 경로로 설정하였다.
하지만 생성은 GPT 시스템 사용자가 자동으로 실행하는 것이고, 재시도는 사용자가 직접 요청을 하는 방식이다.
하지만 나는 GPT 시스템 사용자는 로그인이 불가(토큰 발급 X)하도록 설정을 해놓았다. 그렇다면 둘다 보호경로이지만 Bearer 토큰은 필요없는걸까? 결론부터 말하면 재시도만 토큰이 필요하다. 정리하자면 다음과 같다.
QuestionGenerationService에서 gptUserId를 강제로 세팅해서 INSERT)FAILED 상태의 질문을 보고, “다시 시도해봐야겠다” 하고 프론트에서 API 호출이렇게 둘다 permitAll로 설정했다.
그리고 ML과 프엔 담당자에게 아래와 같이 전달하였다.
"저는 우선 질문 생성, 질문 생성 재시도 코드는 구현 완료했습니다!
아직 ML 서버는 키고 테스트 해보지 않아서 다음주에 테스트 예정입니다
질문 생성 재시도 로직은 아래 노션 링크 걸어두겠습니다.
그리고 다른 API와는 다르게 질문 생성/재시도 API는 GPT API를 사용하는 만큼 트래픽가 생길 경우를
대비해서 question 테이블 내에 retry_count ,last_retry_at ,last_error 칼럼들을 추가했습니다.
이 칼럼들은 재시도 기능의 안정성을 위해서 추가해놓은 겁니다.
해당 칼럼들을 이용해서 질문 생성이 실패했을 경우에 재시도 횟수(retry_count 이용)는 3번,
한번 재시도 했을 경우에는 쿨다운을 위해서 “1분 내 재시도 금지” 제도(last_retry_at 이용)를
걸어놓았습니다.
그리고 재시도 했을 경우에 4XX 에러가 나는 경우에는 “요청을 보낸 쪽(우리 서버 or 입력 데이터)에
문제가 있다는 뜻.”이기에 재시도 해도 같은 에러가 발생됩니다.
그래서 이 경우에는 바로 재시도 차단을 해놓았습니다.
5xx 케이스와 타임아웃 에러인 경우에는 일시적인 서버 장애 또는 외부 서비스의 지연이 원인이라
쿨다운 후 다시 시도하면 성공할 가능성이 있기 때문에 재시도 가능하게 구현해놓았습니다. "
그리고 현재 비관적 락을 사용하였지만, 추가적으로 필요할 경우에는 낙관적 락까지 구현해볼 예정이다. 아직 ML과의 연동을 본격적으로 테스트 해보지는 않았기에 걱정이 되지만 코드 초안은 모두 구현하였다. 그래도 졸업프로젝트를 하면서 정말 많은 걸 배워가서 뿌듯하다. 지난 학기에 수강한 '컴퓨터 아키텍처'라는 수업에서 배웠던 트래픽 관련 문제를 조금씩 다루게 되어서 신기하기도 하다.
다음주 연동테스트 홧팅...🫠