# API 안정화 / 인증 / 세션 인수인계서 > 작성일: 2026-05-06 (옵션 B 분리) > 대상: 후임 AI 엔지니어 또는 개발 관리자 > 작업 브랜치: `hotfix/dev_yscha` > **이 문서의 범위**: 백엔드 API 통신, 재시도, 인증/세션 추적, 로컬 개발 환경 트랙만 다룹니다. > 다른 트랙은 `HANDOVER_INDEX.md` 참조. --- ## 0. 한 줄 요약 API 통신이 **동시 호출로 데드락**나거나 **간헐적 실패**로 사용자 작업이 날아가는 일을 막기 위해, 클라이언트 측 직렬화 / 재시도 / 에러 저장 / stale closure 제거 / 인증 추적을 차례로 보강한 트랙입니다. --- ## 1. 동시 UPDATE 데드락 방어 (가장 중요) ### 1.1 무슨 일이 있었나 - 같은 데이터를 짧은 시간에 여러 번 저장하면 **백엔드에서 동시 UPDATE 가 부딪혀 데드락**이 났습니다. - 사용자 입장에서는 "저장 안 됨" / "타임아웃" / "데이터 깨짐" 으로 보였습니다. ### 1.2 어떻게 풀었나 (커밋 `3000de9c`) 세 단계로 구성: | 단계 | 무엇을 하나 | |------|------------| | **abort + latest** | 진행 중인 동일 요청은 즉시 abort 하고, **가장 최근 요청 1개만** 살림 | | **`X-Idempotency-Key` 헤더** | 같은 의도의 요청이 중복 도달해도 백엔드가 한 번만 처리하도록 멱등키 부여 | | **클라이언트 큐 직렬화** | 같은 리소스에 대한 호출은 클라이언트 단에서 줄을 세워 1개씩만 보냄 | ### 1.3 핵심 파일 - `src/hooks/useAxios.js` — 메인 구현 위치 - 호출부 여러 곳 ### 1.4 주의 - abort 가 너무 공격적이면 **사용자가 의도한 마지막 요청도 취소될 수 있습니다**. 새 호출 추가 시 abort 정책을 검토하세요. - 멱등키는 **요청 단위로 유니크** 해야 합니다. 같은 키로 다른 의미의 요청을 보내면 이전 결과가 캐시처럼 돌아옵니다. --- ## 2. 에러 저장 API (`errSave`) - 커밋 `bb775b28` - 클라이언트에서 발생한 예외/에러를 **백엔드로 자동 전송**해 추적할 수 있게 한 API. - 운영 중에 사용자가 못 알아채는 에러를 잡기 위함. ### 사용처 - 글로벌 에러 핸들러 - 주요 fetch 실패 catch 블록 --- ## 3. API 재시도 — `getRoofMaterialList` 10회 - 커밋 `910974f8` - `getRoofMaterialList` API 가 간헐적으로 실패하는 이슈에 대해 **최대 10회 재시도**. - 지붕재 목록은 화면 진입 시 반드시 필요한 데이터라 실패하면 사용자가 아무것도 못 함. ### 주의 - 10회 재시도는 **이 한 API 한정** 정책. 다른 API 에 그대로 적용하지 마세요. 일반화하면 백엔드 부하 증가. --- ## 4. `fetchBasicSettings` Stale Closure 수정 - 커밋 `63578276` - **문제**: `fetchBasicSettings` 가 `correntObjectNo` 를 Recoil 상태에서 직접 읽고 있어, 새 오브젝트가 생성될 때 **이전 값(stale)** 이 그대로 남아 있는 클로저 문제 발생. - **수정**: 호출 시점의 최신 값을 인자로 받아 처리하도록 변경. ### 일반화 가능한 교훈 - React + Recoil 환경에서 비동기 함수 안에서 atom 을 읽을 때 항상 stale closure 가능성을 의심하세요. --- ## 5. 인증 / 세션 추적 자동 로그인 / 로그아웃 동작이 의도대로 안 되는 케이스가 보고돼 단계적으로 추적 로그를 넣었습니다. | 단계 | 커밋 | |------|------| | 로그인·로그아웃 추적 (1차) | `138bdbdd` | | 추적 강화 (반복) | `ccf60ee7`, `c6da437a` | | 자동 로그인·로그아웃 추적 1 | `c6da437a` | | 자동 로그인·로그아웃 추적 2 | `afe0a377` | | 로그아웃 결과 없이 (이슈 케이스) | `b021b7be` | ### 추적 로그의 목적 - 어디서 토큰이 사라지는지 - 어디서 자동 로그인 트리거가 안 잡히는지 - 어디서 로그아웃 결과가 누락되는지 --- ## 6. 로컬 개발 환경 — dev 스크립트 - 커밋 `27ee53c3` - `package.json` 에 다음 추가: - `dev:local-api` — 로컬 백엔드(`localhost:8080`) 에 붙여서 실행 - `dev:log:local-api` — 위와 동일 + 로그 강화 모드 - `.env.localhost` 와 페어로 사용. 환경변수에서 API base URL 분기. ### 사용 시나리오 - 백엔드 개발자와 동시 디버깅 시 - API 응답 형태가 stage / production 과 다른 경우 --- ## 7. 미해결 / 추적 중 - 동시 UPDATE 데드락의 **완전 재발 방지**는 여전히 모니터링 필요. abort 정책이 새로운 호출 패턴에서 깨질 수 있음. - 인증 추적 로그는 **운영에서 떼어낼지** 결정 필요. 현재는 디버깅 목적 유지. --- ## 8. 핵심 파일 | 파일 | 역할 | |------|------| | `src/hooks/useAxios.js` | API 호출 hook + abort/멱등키/직렬화 | | `package.json` | dev 스크립트 | | `.env.localhost` | 로컬 환경 변수 | | `src/...` (Recoil atoms 의 fetch wrapper) | stale closure 회피 패턴 적용 | --- ## 9. 인수 직후 권장 절차 1. 이 문서 통독. 2. `useAxios.js` 의 abort/직렬화 흐름 코드 한 번 따라가 보기. 3. `npm run dev:local-api` 로 로컬 백엔드와 붙어 동작 확인. 4. 인증 추적 로그를 운영에서 유지/제거 여부 사용자에게 확인. 끝.