버그 내용
next/image는 sizes와 기기 DPR로 srcset 후보 중 하나를 골라 /_next/image?url=...&w=<폭>&q=75 를 요청하는데, sizes 를 안 주면 100vw 로 간주해 화면 전체 폭짜리 이미지를 받습니다.
fill 을 쓰면서 sizes 를 빠뜨렸거나, sizes 값이 실제 렌더 폭과 어긋난 곳이 4군데 있습니다.
기준: iPhone 14 (뷰포트 390px, DPR 3). 매치 화면의 w=640 은 e2e 실측값이고, 나머지는 같은 방식으로 계산한 값
1. sizes 누락 — fill 인데 값이 없음
product-image/index.tsx (담기 화면 장바구니 썸네일)
BaseImage 에 sizes 를 전달하지 않습니다. 컴포넌트가 자기 크기를 이미 알고 있는데도 (SIZE_STYLE.sm.dimension = 68, lg = 200) 그 값이 sizes 로 이어지지 않습니다.
|
값 |
| 실제 렌더 폭 |
약 75px (장바구니 그리드 w-[45%] 2열) |
| 필요한 요청 폭 |
256 |
| 실제 요청 폭 |
1200 |
TournamentBasketItem.tsx:53 (친구 프로필 뱃지)
<Image src={friendImageUrl} fill className="object-cover" /> — sizes 없음.
컨테이너가 부모의 35%라 가장 작은 이미지인데 가장 큰 걸 받습니다.
|
값 |
| 실제 렌더 폭 |
약 26px |
| 필요한 요청 폭 |
96 |
| 실제 요청 폭 |
1200 |
2. sizes 값이 실제 렌더 폭과 어긋남
components/common/wish-card/index.tsx (위시 카드)
sizes="(max-width: 480px) calc(100vw - 40px - 8px), 216px" 인데,
wish-grid/index.tsx:31 이 grid grid-cols-2 입니다. 즉 calc(...) 는 한 줄 전체 폭이고
카드 하나는 그 절반입니다.
|
값 |
| 실제 렌더 폭 |
약 171px |
| 필요한 요청 폭 |
640 |
| 실제 요청 폭 |
1080 |
item-info-screen/ItemDetailView.tsx, ItemImagePicker.tsx
둘 다 sizes="440px" 인데 컨테이너가 w-full 이고 부모(item-info-screen/index.tsx:60)에
px-5 가 걸려 있어 실제로는 약 350px 입니다.
|
값 |
| 실제 렌더 폭 |
약 350px |
| 필요한 요청 폭 |
1080 |
| 실제 요청 폭 |
1920 |
왜 고쳐야 하나
- 모바일 데이터: 20~30대 모바일 쇼핑 사용자가 타겟인데, 68px 자리에 1200px 이미지를 받으면 픽셀 면적 기준 20배 이상을 낭비합니다
- LCP: 담기 화면과 위시 목록은 이미지가 곧 첫 화면입니다
/_next/image 최적화 비용: 큰 폭일수록 서버 리사이즈가 오래 걸리고 캐시도 더 씁니다
- 캐시 키 분산: 같은 상품 이미지를 화면마다 다른
w 로 받으면 서로 캐시를 재사용하지 못합니다. 실제로 담기 화면(w=1200)과 매치 화면(w=640)이 그렇습니다
버그 수정
ProductImage — size variant(sm: 68, lg: 200)에서 sizes 를 유도해 BaseImage 로
넘기고, fill 일 때는 호출부가 sizes 를 넘기도록 prop 을 열어둡니다
- 친구 프로필 뱃지 —
sizes 추가
- 위시 카드 — 2열 그리드 기준으로
calc((100vw - 40px - 8px) / 2) 로 정정
- item-info-screen —
440px → calc(100vw - 40px) 계열로 정정
- 재발 방지로
fill 사용 시 sizes 를 강제하는 린트 규칙 검토 (@next/next 룰셋 확인 필요)
버그 내용
next/image는sizes와 기기 DPR로srcset후보 중 하나를 골라/_next/image?url=...&w=<폭>&q=75를 요청하는데,sizes를 안 주면100vw로 간주해 화면 전체 폭짜리 이미지를 받습니다.fill을 쓰면서sizes를 빠뜨렸거나,sizes값이 실제 렌더 폭과 어긋난 곳이 4군데 있습니다.1.
sizes누락 —fill인데 값이 없음product-image/index.tsx(담기 화면 장바구니 썸네일)BaseImage에sizes를 전달하지 않습니다. 컴포넌트가 자기 크기를 이미 알고 있는데도 (SIZE_STYLE.sm.dimension = 68,lg = 200) 그 값이sizes로 이어지지 않습니다.w-[45%]2열)TournamentBasketItem.tsx:53(친구 프로필 뱃지)<Image src={friendImageUrl} fill className="object-cover" />—sizes없음.컨테이너가 부모의 35%라 가장 작은 이미지인데 가장 큰 걸 받습니다.
2.
sizes값이 실제 렌더 폭과 어긋남components/common/wish-card/index.tsx(위시 카드)sizes="(max-width: 480px) calc(100vw - 40px - 8px), 216px"인데,wish-grid/index.tsx:31이grid grid-cols-2입니다. 즉calc(...)는 한 줄 전체 폭이고카드 하나는 그 절반입니다.
item-info-screen/ItemDetailView.tsx,ItemImagePicker.tsx둘 다
sizes="440px"인데 컨테이너가w-full이고 부모(item-info-screen/index.tsx:60)에px-5가 걸려 있어 실제로는 약 350px 입니다.왜 고쳐야 하나
/_next/image최적화 비용: 큰 폭일수록 서버 리사이즈가 오래 걸리고 캐시도 더 씁니다w로 받으면 서로 캐시를 재사용하지 못합니다. 실제로 담기 화면(w=1200)과 매치 화면(w=640)이 그렇습니다버그 수정
ProductImage—sizevariant(sm: 68,lg: 200)에서sizes를 유도해BaseImage로넘기고,
fill일 때는 호출부가sizes를 넘기도록 prop 을 열어둡니다sizes추가calc((100vw - 40px - 8px) / 2)로 정정440px→calc(100vw - 40px)계열로 정정fill사용 시sizes를 강제하는 린트 규칙 검토 (@next/next룰셋 확인 필요)