제품 화면: 일반 예약과 ‘어디든’ 예약
팀이 공개한 발표 자료의 화면입니다. 일반 예약·‘어디든’ 예약 생성과 포인트 사용 API를 연결한 본문 사례의 사용자 흐름을 보여줍니다.


출처: HASHI 공식 저장소 · Main Features · 팀 공개 자료. 현재 운영 화면의 실시간 실행 녹화는 아닙니다.
배경: 예약 생성은 포인트와 다음 화면도 바꾼다
HASHI는 한국인 여행객을 위한 일본 맛집 큐레이션·예약 요청 서비스입니다. 일반 예약과 ‘어디든’ 예약 생성, 포인트 사용 API를 연결하면서 성공 응답 이후의 데이터 흐름을 함께 다뤘습니다.
사용자는 예약을 만들고 상세 화면으로 이동합니다. 동시에 포인트 잔액도 달라질 수 있습니다. 예약 요청만 성공시키고 끝내면 화면마다 다른 시점의 데이터를 보여줄 수 있는 조건이었습니다.
문제 분석: 응답에 없는 최신 값을 채울 수는 없다
예약 생성 응답에는 예약 ID가 있지만, 완전한 예약 상세 객체나 최신 포인트 잔액이 보장되지 않았습니다. 응답을 그대로 상세 캐시에 넣으면 부족한 필드를 추측해야 하고, 기존 값을 복사하면 오래된 정보가 새 결과처럼 보일 수 있습니다.
| 데이터 | 생성 응답에서 확보 | 처리 |
|---|---|---|
| 예약 ID | 상세 이동에 사용할 ID | 해당 ID의 상세 경로로 이동 |
| 완전한 예약 상세 | 보장되지 않음 | 부분 응답으로 상세 캐시를 만들지 않음 |
| 최신 포인트 잔액 | 보장되지 않음 | 포인트 조회 캐시를 무효화해 재조회 |
선택 기준: 직접 갱신과 재조회는 조건이 다르다
이 흐름에서는 불완전한 상세 객체를 작성하지 않고, 현재 조회하는 포인트 잔액을 무효화해 서버의 최신 값을 다시 받도록 구현했습니다. 성공 후 다른 화면으로 이동한다는 조건도 함께 봤습니다.
| 조건 | 선택 | 판단 이유 |
|---|---|---|
| 같은 화면에서 완전한 최신 객체를 받음 | setQueryData | 응답이 화면에서 필요한 정보를 충족 |
| 부분 응답·화면 이동·집계 변화 | invalidateQueries | 서버의 최신 조회 결과가 필요 |
| 상세 즉시 반영 + 관련 목록·집계 갱신 | 두 방식 조합 | 상세와 목록이 요구하는 갱신 시점이 다름 |
재조회 방식은 추가 요청과 대기 상태를 수반합니다. 이 사례에서는 응답 계약이 충분하지 않으므로, 클라이언트가 상세를 구성하는 것보다 서버 조회를 기준으로 삼는 쪽이 맞았습니다. 모든 mutation에 같은 방법을 쓰도록 일반화하지 않았습니다.
데이터 흐름: 예약 성공 이후의 책임 분리
- 예약 요청입력과 사용할 포인트 전달
- 성공 응답예약 ID 수신
- 포인트 갱신관련 query 무효화
- 상세로 이동서버 조회를 기준으로 상세 표시
예약 ID는 다음 화면을 식별하는 데 사용하고, 포인트 잔액은 해당 조회가 최신 데이터를 가져오게 했습니다. 한 응답으로 해결할 수 없는 데이터까지 생성 결과에 억지로 합치지 않았습니다.
별도 발견: 버튼이 비활성화되기 전의 두 번 클릭
같은 작업의 회귀 테스트에서는 확인 버튼을 대기 없이 연속 클릭했을 때 생성 함수가 두 번 호출됐습니다. mutation.isPending은 재렌더 뒤에 반영되므로 두 handler가 모두 이전 false 값을 읽을 수 있었습니다.
- 첫 클릭isPending=false를 읽음
- 요청 시작재렌더는 아직 반영 전
- 두 번째 클릭이전 false를 읽고 다시 요청
handler 진입 즉시 useRef 잠금을 잡고 onSettled에서 해제하도록 수정했습니다. 버튼 비활성화는 진행 상태를 표현하고, 동기 잠금은 재렌더 이전의 진입을 막는 역할입니다.
예약 확인:
잠금이 이미 잡혀 있으면 종료
동기 잠금 설정
예약 mutation 실행
요청 종료(onSettled):
잠금 해제
실패한 경우 사용자가 다시 시도할 수 있음후속 작업: 발견한 기준을 문서와 리뷰에 남기기
캐시 선택표를 API 연동 스킬, 데이터 계층 문서, 작업 절차에 함께 반영했습니다. 다음 작업에서 완전한 응답인지, 화면이 이동하는지, 목록이나 집계가 함께 달라지는지를 확인할 수 있게 했습니다.
다른 PR 리뷰에서도 예약 취소의 재렌더 전 중복 요청과 리뷰 작성 후 식당 평점·개수 캐시 갱신 누락을 짚었습니다. 동료에게 재현 조건과 수정안을 제시한 범위이며, 후속 구현 전체를 제 기여로 포함하지 않습니다.
검증: 성공 경로보다 경계 조건을 함께 확인
| 조건 | 확인한 동작 | 검증 범위 |
|---|---|---|
| 같은 tick에서 연속 확인 | 예약 생성 호출 1회 | 수정 전 2회 호출 재현 후 비교 |
| 요청 실패 뒤 재시도 | 잠금 해제 후 다시 실행 가능 | 실패 복구 |
| 요청 진행 중 취소·Escape | 다이얼로그 닫기 제한 | 클라이언트 상호작용 |
| 예약 성공 | 포인트 캐시 갱신 처리 | 연동 코드·당시 PR 기록 |
위 결과는 당시 PR의 테스트·검증 보고입니다. 이번 포트폴리오 편집에서 운영 서버를 호출하거나 같은 테스트를 다시 실행한 것은 아닙니다.
이 사례의 기준: 서버가 준 정보만큼만 확정하기
예약 생성에서는 응답이 보장하는 정보의 범위를, 중복 요청에서는 React 상태가 반영되는 시점을 각각 확인했습니다. 데이터의 완전성과 상태의 반영 시점을 구체적으로 나누는 것이 두 문제를 해결한 공통 기준입니다.
문서와 스킬에 반영한 기준이 팀 전체의 시간 절감으로 이어졌는지는 별도 측정이 없습니다. 여기서 확인되는 결과는 동작 수정, 회귀 조건, 후속 작업에서 참조할 판단 기준입니다.