새로고침 후 사라지던 추출 진행 폴링 복구
목차
PDF 추출 시스템에서 결제 후 진행 상황을 폴링으로 추적하는 중에 사용자가 페이지를 새로고침하면 폴링이 멈추는 버그를 고쳤다. 특히 추출에 오래 걸리는 Opus 모델을 사용할 때 문제가 심각했다.
일어났던 일
결제 플랫폼과 연동된 PDF 추출 서비스에서 사용자가 PDF를 업로드하고 결제를 완료한 후, 백그라운드에서 추출이 진행되는 동안 클라이언트는 폴링으로 진행 상황을 계속 묻는다. 그런데 사용자가 이 과정에서 페이지를 새로고침하면, 폴링이 멈춰서 완료된 결과를 받지 못하는 상황이 발생했다.
사용자 입장에서 이건 매우 불편한 경험이다. 특히 추출에 5분, 10분이 걸리는 Opus 모델의 경우, 사용자는 "여전히 진행 중인가?" 싶어서 자연스럽게 새로고침을 해본다. 그런데 새로고침 후에 폴링이 사라지면, 완료될 때까지 기다려도 화면에 아무 일이 없는 것처럼 보인다.
근본 원인
클라이언트 컴포넌트(home-client.tsx)에서 폴링 로직을 관리하고 있었는데, 페이지 새로고침 후 컴포넌트가 리마운트되면서 이전의 폴링 상태가 사라진 거다.
비동기 작업의 상태는 여러 계층에 존재할 수 있다:
- 로컬 메모리 — React state, 전역 상태 (새로고침 시 사라짐)
- 세션 스토리지 — 브라우저 세션 동안만 유지
- 로컬 스토리지 — 브라우저 저장소 (만료 없이 유지)
- 서버 세션 — API 응답/쿠키
이 경우 폴링 중인 작업의 ID나 상태를 로컬 메모리에만 두었어서, 새로고침하면 즉시 사라진 것이다. 서버는 여전히 추출을 진행 중이었지만, 클라이언트는 "뭘 기다려야 하는지" 까먹은 거다.
어떻게 고쳤나
home-client.tsx의 초기화 로직을 개선해서 폴링 재개 메커니즘을 추가했다. 새로고침 직후 컴포넌트가 마운트될 때 다음 흐름을 따른다:
- 이전 세션의 진행 중인 작업이 있는지 확인 (스토리지에 저장된 작업 ID)
- 결제 상태가 완료된 상태인지 조회
- 추출이 아직 완료되지 않았는지 빠른 상태 체크
- 조건을 모두 만족하면 폴링 루프를 즉시 재개
이렇게 하면 사용자는 새로고침 후에도 자동으로 진행 상황 추적이 복구되고, "계속" 버튼을 누르거나 재시작할 필요가 없다.
| 시나리오 | 개선 전 | 개선 후 |
|---|---|---|
| 결제 완료 → 추출 중 → 새로고침 | 폴링 중단, 완료 상태 미감지 | 폴링 자동 복구, 진행 중 표시 |
| 느린 추출(Opus) 중 새로고침 | 특히 심각 (5~10분 대기) | 투명하게 폴링 계속 |
| 새로고침 후 즉시 완료 상태 조회 | 불가능 | 자동 감지 |
팀장으로서의 배운 점과 회고
이 건은 코드 한두 줄 고침처럼 보이지만, 실은 상태 관리와 사용자 경험의 관계를 보여준다.
첫째, 비동기 작업 특히 오래 걸리는 작업은 페이지 새로고침을 피할 수 없다. 사용자는 언제든 새로고침할 수 있고, 실제로 한다. 그래서 최소한의 상태라도 저장 가능한 곳에 둬야 한다. 로컬 메모리만으로는 부족하다.
둘째, Opus처럼 느린 모델을 사용하는 기능은 더욱 견고한 상태 관리가 필요하다. 빠르면 "순간적으로 폴링이 끊겨도 금방 끝나겠지" 하고 무시할 수 있지만, 느리면 UX 영향이 크다. 따라서 처리 시간이 길수록 상태 보존 로직은 더 철저해야 한다.
셋째, 컴포넌트를 설계할 때부터 다음을 습관처럼 고려해야 한다:
- 마운트 시 이전 작업 상태 체크 (useEffect 초기화 로직)
- 마운트 해제 시 폴링 정리 (클린업 함수)
- 상태 저장 위치 선택 (메모리 vs 스토리지 vs 서버)
넷째, 코드 리뷰 때 "이 폴링/작업이 새로고침을 견딜까?" "사용자가 중간에 탭을 닫았다 다시 열면?" 같은 질문을 습관처럼 던져야겠다는 깨달음도 얻었다. 디버깅하기 좋은 질문들이다.
마지막으로, 팀원이 이런 상황을 발견했을 때 "이건 엣지 케이스"라고 치부하지 말고, "느린 작업일수록 더 자주 일어나는 현실적인 사용 패턴"으로 봐야 한다는 걸 팀과도 나누고 싶다.
🛒 이 글과 어울리는 추천 상품
*위 링크는 쿠팡파트너스 활동의 일환이며, 일정액의 수수료를 제공받을 수 있습니다.
댓글 0
첫 댓글 달아줘.