You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
⇒ 그래서 빌드 후 첫 유저가 아닌 상황인데도 다른 컴퓨터로 접속하면 긴 n초 로딩시간을 경험하는 것이었다.
🤸♂️ Next.js는 자동으로 해당 디바이스에 적합한 크기로 이미지를 리사이즈하고 최적화하여 제공하기 때문에 첫번째 유저만 해당 상황을 겪는것이 아니고 **각 이미지 사이즈별 첫 요청을 하는 유저에게**는 동일한 문제가 발생한다.
Next/Image의 특징이나, 해당이유로 특정 이미지만 미리 캐싱을 할 수 있는 것도 아니고 그렇다고 포기하기에는 첫번째 페이지에서 너무 긴 로딩시간이 문제였다.
🛠️ 해결 방법
sharp 의존성 설치
나와 같은 현상을 겪는 사람들을 찾을 수 있었다. Next/Image 구성 요소의 기본 로더는 이미지 크기 조정 및 최적화를 위해 ‘squoosh’라이브러리를 사용하는데, 배포환경에서는 ‘sharp’ 라이브러리를 선택하는 것이 좋다는 것이다. 또한 Next 공식 문서에서 배포 환경에서의 ‘sharp’ 라이브러리 설치를 적극 권장하고 있다.
npm install sharp
추가로 설정해줄 건 없다. 패키지만 다운받으면 알아서 최적화된다.
sharp 설치전
sharp 설치후
이미지 초기 로딩 속도 (X-Nextjs-Cache : MISS)
최대 8.21초에서 511 밀리초로 93.77% 개선
4._.11.webm
코드
return(<divclassName='relative w-full h-screen flex justify-center items-center px-2.5'><Imagesrc={`/intro/${currentImage===6 ? 1 : currentImage}.png`}alt={`Intro ${currentImage}`}fillstyle={{objectFit: 'cover',zIndex: 31}}// 이미지 비율 유지하며 컨테이너에 맞춤priority={true}// 이미지 로딩 우선순위 설정loading='eager'// 이미지 로딩 방식 설정/>
생략 ..
이미지 파일(Png말고 webp로 최적화하여)을 s3에 넣고 cloud front로 저장
🤸♂️ Next/Image의 캐싱이 아닌, AWS cloud front 캐싱을 사용하고,
기존 Image 태그는 div 태그의 background image 속성으로 변경하여 화면 크기마다 이미지가 가득 차도록 코드 변경
Next/Image 컴포넌트의 기본 로더는 배포 환경에서 최적화 성능이 떨어질 수 있으므로, Sharp 라이브러리를 설치하여 이미지 최적화 성능을 향상시킬 수 있음.
AWS S3와 CloudFront를 활용한 캐싱을 통해 성능을 극대화할 수 있음.
첫 유저의 유입에 있어 빠른 응답성을 최우선으로 하기 위해, 동일한 이미지 크기를 미리 캐싱하여 제공하는 방식을 선택하였습니다.
→ 이 방식은 유저의 화면 크기에 따른 최적화보다 빠른 로딩이 중요한 상황에서 더 나은 선택이었으며, 첫 유입 시 사용자 경험을 크게 개선했습니다.
최종 해결 방법
Next/Image는 화면 크기별로 이미지를 자동으로 최적화하고 제공하는 강력한 기능을 가지고 있지만, 첫 화면에서는 유저가 이미지 로딩에 기다리지 않도록 빠른 로딩이 더 중요합니다. 특히, 첫 유입 시 사용자가 보게 되는 이미지들은 초기 로딩 속도가 중요한데, Next/Image는 유저의 화면 크기에 따라 다른 크기의 이미지를 동적으로 제공하기 때문에 이미지 최적화는 뛰어나지만 첫 요청 시 로딩 시간이 길어지는 문제가 있었습니다.
따라서, 첫 화면에서의 빠른 이미지 로딩을 위해 **CDN(AWS CloudFront)**를 통해 고정된 크기의 이미지를 제공하는 방식으로 변경했습니다.
이 방식은 모든 사용자가 동일한 크기의 최적화된 이미지를 캐싱된 상태로 빠르게 받을 수 있어, 첫 유입 시 로딩 속도가 크게 개선되었습니다. 이는 첫 화면에서의 유저 경험을 최적화하는 데 더 중요한 선택이었고, 실제로 로딩 시간이 8.21초에서 78ms로 단축되어 99.05%의 성능 개선을 이루었습니다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
인트로 페이지 이미지 로딩 속도 문제 개선
🔗 커넥트립 : https://connectrip.travel/
이전 상황
: 로그인 필수서비스인 커넥트립의 첫 화면에는 카카오로그인 버튼만 존재하고, 우리 서비스에 대한 소개가 없어 유저의 유입에 있어 더 많은 정보가 필요하다는 판단.개선 상황
: 인트로 페이지에Next/Image
컴포넌트를 사용하여 여러 개의 PNG 파일로 이루어진 이미지를 추가하고, 버튼을 통해 페이지를 넘길 수 있는 구조로 첫페이지를 변경함.문제 상황
: prod에 배포했을때, 처음 이미지를 불러오는 순간 각 평균 4~5초(최대 10초 이상)의 시간이 걸리는 것을 확인하였다.이후 캐싱처리가 되어 새로고침을 하면 밀리초의 로딩속도를 보여주었다.
영상에서는 이미지 한번 로딩에 8.21초의 시간이 소요된것을 확인할 수 있다.
___._._._._.5.webm
→ 알고보니 얘도 처음엔 오래걸리는게 맞았다.
우선 이 문제를 개선하기 위해 다음과 같은 시도를 해봤다.
Next/Image
의priority
,eager
속성 추가:이미지 로딩 우선순위를 설정했지만 로딩 속도에 유의미한 개선이 없었음.
PNG 이미지를 SVG로 대체:
SVG 파일로 변경하니 로딩 속도가 줄어들었지만, 파일 크기가 너무 커져서 용량이 1.2MB까지 늘어남. 이 방법은 용량 문제로 적절하지 않음.
Next/Image
대신 일반<img>
태그 사용:초기 로딩 속도는 다소 개선되었지만 여전히 2초 이상 소요되고, 재로딩 시 성능은 크게 떨어짐. 용량 또한 크다는 문제가 있음.
시도 1. Next/Image prioriy, eager 속성 추가하기
priority, eager 속성은 이미지 로드의 우선순위를 지정해줄 수 있다. 이미지 로딩 우선순위를 설정했지만 로딩 속도에 유의미한 개선이 없었다.
시도 2. 각 이미지의 아이콘을 svg파일로 저장하여 컴포넌트 내에서 위치 재배치
통이미지 파일을 svg로 저장하지 않은 이유는, svg파일이 로고단위로 작으면 파일크기가 매우 작지만, 이미지가 복잡해질수록 mb단위의 이미지 크기로 커지기 때문에 요소별로 나누어 저장해보았다.
로딩속도가 각 페이지 별 140밀리초까지 줄일 수 있었다. 하지만 이미지를 나눠 저장했음에도 불구하고, svg 파일의 크기가 1.2mb까지 늘어나서 기존의 500kb 미만의 이미지 파일들에 비해 용량이 너무 커지는 문제가 있다.
결론 : SVG 파일로 변경하니 로딩 속도가 줄어들었지만, 파일 크기가 너무 커져서 용량이 1.2MB까지 늘어남. 이 방법은 용량 문제로 적절하지 않음.
좋은 해결법이 아닌 듯 하니 다음 시도로 넘어가 보자.
2._.7.webm
시도 3. Next/Image 태그 대신 일반 태그로 불러와보기
Next/Image 최적화에 시간이 오래걸리는 걸 수도 있겠다는 생각이 들었다.
일반 img 태그로 시간이 얼마나 소요되는지 확인.
이전 이미지 로딩속도 개선경험때, svg가 전체 이미지로 저장하게 되면 용량이 너무 커져서 png로 저장해야한다 이해했었다.
Next/Image 태그로 최적화가 되지않은 png파일은 svg와 다를바없이 큰 용량을 차지하고 있었다.
Next/Image가 이미지파일을 webp로 변경하여 최적화된 상태로 불러올수있게 하여서 이미지 파일이 kb의 작은형태로 올 수 있었던 것이다. 근데 왜 초기로딩속도가 그럴까?
이번 3번 방법은 Next/Image의 초기 로딩속도만큼은 아니지만 초기 로딩 속도 2초대로 시간은 줄었다. 하지만 용량이 너무 크다. 재로딩시점에 있어서는 이미지당 500ms 정도로 감소하기는 한다. 재로딩기준으로는 기존의 Next/Image 성능에 한참 못미친다.
로드 1.81초
결론 : 초기 로딩 속도는 다소 개선되었지만 여전히 n초 이상 소요되고, 재로딩 시 성능은 크게 떨어짐. 용량 또한 크다는 문제가 있음.
이것도 적절한 해결법은 아닌 것 같다. 다른 방법을 찾아보자.
🧚 원인발견
브라우저 캐시 문제가 아닌 서버 캐싱 문제:
Next/Image에서 캐싱, 최적화하는 시간이 오래걸리는 것 같은데, 이 현상이 어느 조건일때 발생하는지 알 수 없었다.
참고 : 멘토링 이미지
ssh 접속 후 캐시 삭제 과정
front dev 서버 ssh 접속 script
현재 떠있는 컨테이너 목록 확인
docker container 접속 ( docker ps로 현재 컨테이너가 블루인지 그린인지 확인하고 컨테이너 이름에 맞게 넣기 )
docker exec -it front-blue /bin/sh
캐시 폴더 삭제
캐시 관리:
.next/cache/images
에서 이미지 캐시 파일을 삭제하고 다시 사이트에 접속하면 처음 경험했던 n초이상의 로딩 상황이 재현된다.추가적으로, 유저가 한번 페이지를 요청한 이후부터는 이미지가 이미 캐싱되어 있기 때문에 동일한 이미지에 대한 다음 모든 요청에서는 Next/Image 캐싱을 활용하여 빠르게 로딩이 된다.
노란색 테두리처럼 캐싱된 images 폴더를 지운 뒤, curl 명령어로 이미지를 미리 요청하면 images 폴더에 해당 이미지가 캐싱된다.
그래서 임시로 캐싱된 이미지를 넣어 테스트를 해봤는데, 유저의 화면 사이즈별로 다르게 링크가 계속 생성됨을 알게 되었다.
다음은 본인 화면에서의 캐싱된 이미지 링크이다.
하지만, Next.js의
next/image
컴포넌트는 유저의 화면 크기에 따라 이미지의 크기를 자동으로 최적화하여 제공하는 기능을 가지고 있다. 따라서, 사용자의 화면 크기와 디바이스에 따라 요청하는 이미지의 크기(w
값)가 달라질 수 있다는 것이다.⇒
&w=1200
이 값이 유저별로 다르게 캐싱될 수 있어 [내가 생각한 방식](https://www.notion.so/10-2-113e51f85ff580739ab0e600d7f0b0f7?pvs=21)으로는 해결해줄 수는 없는 것이다. ( 모든 사진에 대해 사이즈별로 미리 요청을 날릴 수는 없으니.. )⇒ 그래서 빌드 후 첫 유저가 아닌 상황인데도 다른 컴퓨터로 접속하면 긴 n초 로딩시간을 경험하는 것이었다.
Next/Image의 특징이나, 해당이유로 특정 이미지만 미리 캐싱을 할 수 있는 것도 아니고 그렇다고 포기하기에는 첫번째 페이지에서 너무 긴 로딩시간이 문제였다.
🛠️ 해결 방법
나와 같은 현상을 겪는 사람들을 찾을 수 있었다. Next/Image 구성 요소의 기본 로더는 이미지 크기 조정 및 최적화를 위해 ‘squoosh’라이브러리를 사용하는데, 배포환경에서는 ‘sharp’ 라이브러리를 선택하는 것이 좋다는 것이다. 또한 Next 공식 문서에서 배포 환경에서의 ‘sharp’ 라이브러리 설치를 적극 권장하고 있다.
추가로 설정해줄 건 없다. 패키지만 다운받으면 알아서 최적화된다.
이미지 초기 로딩 속도 (X-Nextjs-Cache : MISS)
최대 8.21초에서 511 밀리초로 93.77% 개선
4._.11.webm
코드
이미지 초기 로딩 속도 최대 8.21초에서 78밀리초로 99.05% 개선
https://drive.google.com/file/d/1-4R6cxUCItVMYINnnxL86Qku0Ejo7dgJ/view?usp=sharing
코드
결론
Next/Image
컴포넌트의 기본 로더는 배포 환경에서 최적화 성능이 떨어질 수 있으므로, Sharp 라이브러리를 설치하여 이미지 최적화 성능을 향상시킬 수 있음.→ 이 방식은 유저의 화면 크기에 따른 최적화보다 빠른 로딩이 중요한 상황에서 더 나은 선택이었으며, 첫 유입 시 사용자 경험을 크게 개선했습니다.
최종 해결 방법
Next/Image
는 화면 크기별로 이미지를 자동으로 최적화하고 제공하는 강력한 기능을 가지고 있지만, 첫 화면에서는 유저가 이미지 로딩에 기다리지 않도록 빠른 로딩이 더 중요합니다. 특히, 첫 유입 시 사용자가 보게 되는 이미지들은 초기 로딩 속도가 중요한데,Next/Image
는 유저의 화면 크기에 따라 다른 크기의 이미지를 동적으로 제공하기 때문에 이미지 최적화는 뛰어나지만 첫 요청 시 로딩 시간이 길어지는 문제가 있었습니다.따라서, 첫 화면에서의 빠른 이미지 로딩을 위해 **CDN(AWS CloudFront)**를 통해 고정된 크기의 이미지를 제공하는 방식으로 변경했습니다.
이 방식은 모든 사용자가 동일한 크기의 최적화된 이미지를 캐싱된 상태로 빠르게 받을 수 있어, 첫 유입 시 로딩 속도가 크게 개선되었습니다. 이는 첫 화면에서의 유저 경험을 최적화하는 데 더 중요한 선택이었고, 실제로 로딩 시간이 8.21초에서 78ms로 단축되어 99.05%의 성능 개선을 이루었습니다.
참고
https://nextjs.org/docs/messages/sharp-missing-in-production
https://oliveyoung.tech/blog/2023-06-09/nextjs-image-optimization/
https://stackoverflow.com/questions/66637391/next-images-components-are-too-slow-to-appear
웨슬리 멘토링 https://www.notion.so/Next-Image-15ae51f85ff5807097c3caa6792c1b3f?pvs=4#db0687c1ac924948a6af4fd2ca506325
노션버전 원문 : https://sen2y-portfolio.notion.site/Next-Image-15ae51f85ff5807097c3caa6792c1b3f
Beta Was this translation helpful? Give feedback.
All reactions