렌더링 · 성능
이미지 뷰어 — 좌우로 넘길 때 2~5초 빈 화면 잡기
채팅 이미지 뷰어에서 좌우 화살표로 넘기면 2~5초간 빈 화면이 떴다. React가 아니라 브라우저의 Fetch·Decode·Paint를 이해하고서야 잡힌 문제다.
왜 느린가 — 브라우저의 3단계
이미지를 화면에 띄우려면 브라우저는 3단계를 거친다.
1. Fetch (네트워크) — CDN에서 바이트 다운로드
2. Decode (CPU) — 압축 이미지(JPEG/PNG)를 픽셀로 변환
3. Paint (GPU) — 픽셀을 화면에 그림채팅 목록은 324px 썸네일이라 빠르다. 뷰어는 원본 해상도(수천 px)라 Decode 시간이 폭증한다.
<img src> 변경은 React의 영역이 아니라 브라우저 네이티브 동작이라, React가 빨라도 소용없다.
시도와 함정
V2 — 스피너 + opacity: 두 가지 함정에 빠졌다.
key={url}함정: key가 바뀌면 React가 DOM을 파괴하고 새로 생성 → 캐시에 있어도 새<img>라 다시 decode. → key 제거(같은 요소 재사용,src만 변경)transition-opacity함정: 캐시된 이미지에도opacity전환 150ms가 붙어 느려 보임 → transition 제거
V3 — img.complete 캐시 체크: new Image().complete는 HTTP 캐시만 알려준다. 디코딩
여부는 모른다 → 썸네일로 본 이미지라도 원본은 다시 decode해야 한다.
해결 — 인접 이미지를 미리 decode
다음/이전 이미지를 미리 img.decode()로 디코딩까지 끝내 두고, 현재 이미지는 같은 <img> 요소를
재사용해 교체했다. 넘기는 순간엔 이미 디코딩된 픽셀이라 빈 화면이 사라졌다.
배운 점
keyprop은 리스트에서만. 단일 요소의 key를 바꾸면 불필요한 DOM 재생성 + 재디코딩이 생긴다- 캐시(
complete)와 디코딩 완료(decode())는 다르다. "느린 이미지"는 네트워크가 아니라 Decode가 범인인 경우가 많다 — 프레임워크가 아니라 브라우저 파이프라인을 봐야 잡힌다