Skip to content

[Perf] 이미지 최적화 및 슬라이더에 이미지 블러 LQIP 적용#112

Merged
DreamPaste merged 8 commits intodevfrom
perf/web-image-optimization
Jan 17, 2026
Merged

[Perf] 이미지 최적화 및 슬라이더에 이미지 블러 LQIP 적용#112
DreamPaste merged 8 commits intodevfrom
perf/web-image-optimization

Conversation

@youdaeng2
Copy link
Member

📌 개요

  • Next.js Image 최적화에서 WebP 우선 적용 및 SoSo 레이아웃에 맞게 deviceSizes/imageSizes 튜닝
  • 상세페이지 이미지에 SSR blurDataURL 생성(Sharp) 추가 + 슬라이더 전체 이미지 placeholder blur 적용
  • 슬라이더 UX 개선(중복 스타일 정리, 첫 이미지 priority, draggable=false)

🗒 상세 설명

1. Next/Image 최적화 설정(WebP + sizes 튜닝)

핵심 기술 및 구현사항

  • apps/web/next.config.js

    • images.formats: ['image/webp']로 WebP 우선 적용
    • deviceSizes, imageSizes를 SoSo 레이아웃 기준으로 조정해서 불필요한 리사이즈/다운로드를 줄임
    • domains/remotePatterns 유지 및 확장

2. SSR blurDataURL 생성 유틸 추가 + 상세 슬라이더 전체 이미지 적용

핵심 기술 및 구현사항

  • apps/web/src/utils/getBlurDataURL.ts 신규 추가

    • server-only + sharp 기반으로
    • 원본 이미지 fetch → resize/blur → data:image/webp;base64,... 형태로 반환
  • apps/web/src/app/main/community/freeboard/[freeboardId]/page.tsx

    • 게시글 prefetch 후 post.images 전체를 대상으로 Promise.all로 blurDataURL 배열 생성
    • 생성한 blurImageUrlsClientPage로 prop 전달
  • ClientPage → FreeboardDetail → ImageSliderblurDataUrls prop drilling

  • apps/web/src/components/ImageSlider.tsx

    • placeholder={blurDataUrls?.[idx] ? 'blur' : 'empty'}
    • blurDataURL={blurDataUrls?.[idx]}
      슬라이드 전체 이미지에 블러 placeholder 적용

사용 예시

<Image
  src={imgUrl}
  fill
  placeholder={blurDataUrls?.[idx] ? 'blur' : 'empty'}
  blurDataURL={blurDataUrls?.[idx]}
/>

3. 깨진 이미지도 최대한 블러 생성되도록 보강

핵심 기술 및 구현사항

  • sharp(input, { failOn: 'none' }) 적용

    • 일부 손상/비정상 이미지에서 sharp가 throw하는 케이스를 줄이고
    • 실패 시에는 undefined 반환으로 placeholder만 스킵되도록 처리

4. 슬라이더 UX 개선

핵심 기술 및 구현사항

  • 중복 스타일 정리
  • 첫 이미지 priority 적용 (초기 로딩 개선)
  • draggable={false} 적용으로 슬라이더 조작 중 이미지 드래그 UX 이슈 방지 -> 확인 부탁드립니다
  • 스켈레톤 색상/전환 스타일 소폭 조정

5. pnpm 10 적용 및 락파일 재생성(+ 소규모 설정)

핵심 기술 및 구현사항

  • chore: pnpm 10 적용 및 lockfile 재생성
  • apps/web/.eslintrc.cjs에서 src/generated/** ignore 추가

📸 스크린샷 (추가예정)

AS-IS

  • 블러 미적용/일부만 적용 상태
  • 기존 이미지 로드 확장자 스크린샷

TO-BE

  • 이미지 blur placeholder
  • 이미지 webp 확장자로 로드되는 지 스크린샷

🔗 이슈

closes #


✅ 체크리스트

  • 코드가 스타일 가이드를 따릅니다
  • 자체 코드 리뷰를 완료했습니다
  • 복잡/핵심 로직에 주석을 추가했습니다
  • 관심사 분리를 확인했습니다
  • 잠재적 사이드이펙트를 점검했습니다
  • Vercel Preview로 테스트를 완료했습니다

🧪 테스트 방법

  • /main/community/freeboard/[id] 진입 시 슬라이더 이미지 placeholder blur 적용 확인
  • 이미지 여러 장에서 index 매칭(blurDataUrls[idx]) 정상 동작 확인
  • 손상 이미지 케이스에서 에러 없이 placeholder가 스킵되는지 확인
  • DevTools Network에서 /_next/image 응답 포맷(WebP/JPEG fallback) 확인
  • pnpm 10 환경에서 pnpm i 및 dev 실행 확인

📝 추가 노트

  • apps/web/next.config.js
  • apps/web/src/utils/getBlurDataURL.ts
  • apps/web/src/app/main/community/freeboard/[freeboardId]/page.tsx
  • apps/web/src/components/ImageSlider.tsx

후속 작업

  • 슬라이더에만 적용하지 않고 전체적으로 도입할 수 있을지 고민
  • keen-slider 초기화 시점(새로고침) 레이아웃 겹침 문제 재현 시, 초기 렌더/스켈레톤 전략 추가 검토

@youdaeng2 youdaeng2 requested a review from DreamPaste January 4, 2026 10:55
@youdaeng2 youdaeng2 self-assigned this Jan 4, 2026
@youdaeng2 youdaeng2 added Refactor 🫧 기존 내용을 개선하거나 최적화합니다! 유진 labels Jan 4, 2026
@github-actions
Copy link

github-actions bot commented Jan 4, 2026

@github-actions
Copy link

github-actions bot commented Jan 4, 2026

📦 번들 분석 결과

📊 번들 크기 요약

항목
📦 전체 번들 크기 3.8M
📄 JavaScript 크기 1.7M
🗂️ JavaScript 파일 수 64개

🔍 주요 청크 파일 (크기순)

075d628c-a737cab5ec06bda6.js - 169K
1157-62218139c4b10a75.js - 150K
framework-69e0f7d37422957b.js - 137K
main-088ae1876c5673c4.js - 130K
9524-7e0ed19159ca1cf4.js - 122K
9247-478a2d2a1658e375.js - 122K
polyfills-42372ed130431b0a.js - 110K
6279-3ef5a6e2abd3398f.js - 73K
page-7ec90837d2c5a6d0.js - 30K
740-8bf84951cd03170e.js - 28K

🤖 자동 생성된 번들 분석 리포트

@github-actions
Copy link

github-actions bot commented Jan 4, 2026

⚡ Lighthouse 성능 분석 결과

📊 전체 평균 점수

지표 점수
🚀 Performance 73점
♿ Accessibility 86점
✅ Best Practices 99점
🔍 SEO 100점

📈 측정 현황

  • 측정 성공: 15/16 페이지
  • 상태: success

📄 페이지별 상세 분석

🏠 커뮤니티 페이지: /main/community

지표 점수
🚀 Performance 67점
♿ Accessibility 78점
✅ Best Practices 96점
🔍 SEO 100점

📊 상세 분석 보기

👥 창업자 페이지: /main/founder

지표 점수
🚀 Performance 75점
♿ Accessibility 87점
✅ Best Practices 100점
🔍 SEO 100점

📊 상세 분석 보기

🏡 홈 페이지: /main/home

지표 점수
🚀 Performance 75점
♿ Accessibility 91점
✅ Best Practices 100점
🔍 SEO 100점

📊 상세 분석 보기

🗺️ 지도 페이지: /main/maps

지표 점수
🚀 Performance 75점
♿ Accessibility 87점
✅ Best Practices 100점
🔍 SEO 100점

📊 상세 분석 보기

👤 프로필 페이지: /main/profile

지표 점수
🚀 Performance 75점
♿ Accessibility 88점
✅ Best Practices 100점
🔍 SEO 100점

📊 상세 분석 보기

🔗 전체 상세 분석 결과

📊 전체 상세 Lighthouse 분석 결과 보기

📄 측정된 페이지

  • /main/community
  • /main/founder
  • /main/home
  • /main/maps
  • /main/profile

모든 페이지에서 성능 측정이 완료되었습니다.


🤖 자동 생성된 Lighthouse 성능 리포트

Copy link
Member

@DreamPaste DreamPaste left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생했어요

Comment on lines +46 to +50
return getBlurDataURL(img.imageUrl, {
size: 10,
blur: 2,
quality: 40,
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여러 값을 비교해보면서 속도와 UX 사이의 균형점을 생각해보면 좋을 것 같아요

@DreamPaste DreamPaste merged commit 07a5a01 into dev Jan 17, 2026
3 of 4 checks passed
@DreamPaste DreamPaste deleted the perf/web-image-optimization branch January 17, 2026 08:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Refactor 🫧 기존 내용을 개선하거나 최적화합니다! 유진

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants