구현할 기능
토너먼트 플레이 중 매치가 넘어갈 때마다 상품 이미지가 깜빡인다. 다음 매치에 나올 이미지를 미리 받아둬서 전환 시 바로 보이게 한다.
현재 구조 — "한 타임 빨리 받아오기"는 불가능
다음 대진은 선택하는 순간 서버가 알려준다. 매치 기록 응답(POST record)에 nextMatch 가 실려 오고, 그걸로 현재 매치를 교체하는 구조다.
app/tournament/[id]/match/_hooks/useTournament.ts — handleSelect 의 onSuccess
if (data.nextMatch) {
setCurrentMatch(data.nextMatch);
setMatchIndex(prev => prev + 1);
return;
}
// nextMatch 없음 — 라운드 종료. 재조회로 다음 라운드 진입
즉 대진을 미리 조회하는 API 가 따로 없어서, 요청을 한 타임 앞당길 수는 없다.
대신 가능한 방향 — 남은 아이템 이미지를 라운드 진입 시 전부 프리로드
대진 조합은 몰라도 후보 아이템은 이미 알고 있다. inProgress.remainingItems 에 그 라운드에 남은 아이템이 이미지 URL 까지 전부 내려온다 (_common/_types/tournamentResponse.ts:88-94).
- 라운드 진입 시점에
remainingItems 의 이미지를 미리 로드해두면, 어떤 조합이 나와도 캐시에 있다
- 라운드당 최대 8 → 4 → 2개라 부담이 크지 않다
- 라운드가 넘어갈 때는
syncWithServer() 의 조회 응답에 새 remainingItems 가 오므로 같은 방식으로 처리 가능
참고 / 주의
- 이미지는
next/image 를 거치므로(components/base-image/index.tsx), 프리로드도 최적화 URL(/_next/image?url=...&w=...) 기준으로 맞춰야 캐시가 재사용된다. 원본 URL 로 new Image() 를 때리면 실제 렌더 요청과 다른 URL 이라 효과가 없다
ProductCard 의 sizes="(max-width: 480px) 45vw, 200px" 와 동일 조건이어야 한다
ProductCard 는 이미 preload 로 렌더되고 있다 (app/tournament/[id]/match/_components/ProductCard.tsx:37)
- 기록 요청 대기 중에는 스켈레톤이 뜨므로(
isRecordingMatch), 프리로드가 걸려 있으면 스켈레톤이 걷힐 때 이미지가 이미 준비된 상태가 된다
확인 필요
- 프리로드로 충분히 해소되는지, 아니면 대진 조회 API 분리(서버 작업)가 필요한 수준인지는 실제 적용 후 판단
구현할 기능
토너먼트 플레이 중 매치가 넘어갈 때마다 상품 이미지가 깜빡인다. 다음 매치에 나올 이미지를 미리 받아둬서 전환 시 바로 보이게 한다.
현재 구조 — "한 타임 빨리 받아오기"는 불가능
다음 대진은 선택하는 순간 서버가 알려준다. 매치 기록 응답(
POST record)에nextMatch가 실려 오고, 그걸로 현재 매치를 교체하는 구조다.app/tournament/[id]/match/_hooks/useTournament.ts—handleSelect의onSuccess즉 대진을 미리 조회하는 API 가 따로 없어서, 요청을 한 타임 앞당길 수는 없다.
대신 가능한 방향 — 남은 아이템 이미지를 라운드 진입 시 전부 프리로드
대진 조합은 몰라도 후보 아이템은 이미 알고 있다.
inProgress.remainingItems에 그 라운드에 남은 아이템이 이미지 URL 까지 전부 내려온다 (_common/_types/tournamentResponse.ts:88-94).remainingItems의 이미지를 미리 로드해두면, 어떤 조합이 나와도 캐시에 있다syncWithServer()의 조회 응답에 새remainingItems가 오므로 같은 방식으로 처리 가능참고 / 주의
next/image를 거치므로(components/base-image/index.tsx), 프리로드도 최적화 URL(/_next/image?url=...&w=...) 기준으로 맞춰야 캐시가 재사용된다. 원본 URL 로new Image()를 때리면 실제 렌더 요청과 다른 URL 이라 효과가 없다ProductCard의sizes="(max-width: 480px) 45vw, 200px"와 동일 조건이어야 한다ProductCard는 이미preload로 렌더되고 있다 (app/tournament/[id]/match/_components/ProductCard.tsx:37)isRecordingMatch), 프리로드가 걸려 있으면 스켈레톤이 걷힐 때 이미지가 이미 준비된 상태가 된다확인 필요