더 줄게 공고 신청 취소 버그 분석 기록
트러블슈팅버그API교차검증
팀 프로젝트 ‘더 줄게’를 개발하던 중, 공고 신청 프로세스에서 치명적인 버그를 발견했다.
일반적인 "신청 → 취소" 흐름은 정상적이었으나, "신청 → 취소 → 재신청 → (다시) 취소"로 이어지는 엣지 케이스에서 문제가 발생했다.
서비스의 공고 상세 조회 API는 유저 토큰을 헤더에 담아 요청하면 currentUserApplication이라는 필드를 통해 현재 로그인한 유저의 지원 상태와 ID를 내려주는 구조였다.
문제 상황
공고를 취소한 뒤 다시 재신청했을 때, UI상으로는 신청이 완료된 것처럼 보였으나 이후 다시 취소를 시도하면 에러가 발생했다.
- 유저가 공고 재신청 후 상세 페이지에 진입한다.
- 서버가 내려준
currentUserApplication.status는 여전히CANCELED(취소 상태)로 유지된다. - 더 심각한 것은
currentUserApplication.id가 재신청 시 생성된 새로운 ID가 아니라, 이전(취소된) 지원 정보의 ID를 그대로 반환하고 있다는 점이다. - 이 상태에서 유저가 취소 버튼을 누르면, 이미 취소된 ID로 요청을 보내게 되어 서버로부터 "이미 처리된 지원 정보입니다"라는 400 에러를 응답받는다.
원인 추론 및 단서 발견
처음에는 서버 캐싱 문제, 서버 내부 로직 문제, 혹은 공고 상세 조회 API 로직 오류를 의심했다. 하지만 문제를 좁혀가기 위해 다른 API 응답과 교차 검증을 진행했다.
유저는 공고 상세 페이지 외에도 내 지원 목록 페이지에서 본인의 신청 내역을 확인할 수 있다. 그래서 두 API의 응답을 비교해 보았다.
- 공고 상세 API (
currentUserApplication)- 지원 ID: 101 (과거 취소된 내역)
- 상태:
CANCELED
- 내 지원 목록 API
- 지원 ID: 101 (과거 취소된 내역, createdAt: 10:00)
- 지원 ID: 105 (방금 재신청한 내역, createdAt: 10:05)
이를 통해 캐싱 문제가 아니라, 서버 로직 상에서 공고 상세 API가 최신 데이터를 보장하지 못하는 문제라는 것을 확인했다.
해결 방법
서버 수정이 어려운 상황이었기 때문에 프론트엔드에서 신뢰할 수 있는 데이터 소스를 명확히 분리하는 방식으로 우회하여 해결했다.
- 공고 취소 동작 시, 내 지원 목록 API를 호출한다.
- 현재 보고 있는 공고 ID와 일치하는 지원 내역들을 필터링한다.
- 필터링된 목록을
createdAt기준으로 내림차순 정렬하여 가장 최신 지원 정보를 선택한다. - 확보한 최신 ID를 사용하여 취소 요청을 전송한다.
이 로직을 적용한 후, 재신청 이후에도 공고 취소가 안정적으로 동작하는 것을 확인했다.
배운 점
- 서버 응답의 무결성을 맹신하지 않는다.