항해 플러스 프론트엔드 코스란?
1~4년 차 주니어 프론트엔드 개발자들이 모여 매주 토요일마다 오프라인 모임, 코드 리뷰를 진행하고
평일에 한 번씩 멘토링을 진행하면서 주니어 개발자들이 성장할 수 있는 환경을 제공해 주는 코스입니다.
이번 항해 플러스 프론트엔드 코스 9주 차에선 성능 최적화에 대해서 배웠습니다.
성능 최적화 방법에 대해서 처음 배워보고, 적용해 보아서 새롭게 배운 내용이 많은 주차였습니다.
어떤 내용들을 배웠고, 성급한 최적화는 왜 좋지 않은지 정리해 보겠습니다.
이번 9주 차 과제로는 성능이 안 좋은 프로젝트를 Lighthouse로 측정하며 성능을 개선하는 것이었습니다.
심화 과제로는 직접 개선 사후 보고서를 작성하는 것이었는데요, 제가 직접 제출한 보고서를 첨부하여 어떤 것을 배웠는지 다루어보겠습니다!
AS-IS | TO-BE |
First Contentful Paint(FCP): 1.9초 | 0.8초 |
Largest Contentful Paint(LCP): 1.9초 | 0.8초 |
Total Blocking Time(TBT): 910밀리초 | 0초 |
Cumulative Layout Shift(CLS): 0.516 | 0 |
Speed Index: 2.7초 | 2.0초 |
기존 서비스의 문제점은 이미지 로드 시간이 오래 걸려 FCP, LCP 수치가 좋지 않았습니다.
WebP 및 AVIF와 같은 이미지 형식은 PNG나 JPEG보다 압축률이 높기 때문에 다운로드가 빠르고 데이터 소비량도 적습니다.
개선 방식:
AS-IS | TO-BE |
LCP: 16.4초 | 8.3초 |
TBT: 910 밀리초 | 600 밀리초 |
이미지 리소스 1,400KiB | 140 KiB |
주의할 점으로는 webp나 avif는 IE나 오래된 버전의 브라우저는 지원이 안 될 수 있습니다.
브라우저마다 지원되는지 확인할 때 주로 Can I Use 사이트를 이용할 수 있습니다!
기존 코드의 문제점은 Desktop, Tablet, Mobile 사이즈에 맞는 배너 이미지가 각각 있었는데, Desktop 해상도에도 Tablet, Mobile 이미지를 로드하고 있었습니다.
중요한 리소스의 로드가 모두 완료된 후에는 오프스크린 및 숨겨진 이미지를 지연 로드함으로써 상호작용 시작 시간을 줄이는 것이 좋습니다.
개선 방식: source 태그의 media 속성을 선언하여 특정 화면에 맞는 이미지만 불러오도록 변경하였습니다.
<picture>
<source
width="576"
height="576"
media="(max-width: 575px)"
srcset="images/Hero_Mobile.webp"
/>
<source
width="960"
height="770"
media="(min-width: 576px) and (max-width: 960px)"
srcset="images/Hero_Tablet.webp"
/>
<img width="1920px" height="893px" src="images/Hero_Desktop.webp" />
</picture>
AS-IS | TO-BE |
LCP: 8.1초 | 3.5초 |
불필요하게 로드되었언 이미지 리소스 크기: 2,270KiB | 0 KiB |
기존 코드는 head에 있는 script 태그가 html 렌더링을 지연시키고 있었습니다.
리소스가 페이지의 첫 페인트를 차단하고 있습니다. 중요한 JS/CSS를 인라인으로 전달하고 중요하지 않은 모든 JS/Style을 지연하는 것이 좋습니다.
개선 방식:
async와 defer 속성은 스크립트는 다운로드 시 페이지 렌더링을 막지 않는다는 공통점이 있습니다.
HTML 콘텐츠에 영향을 주지 않는 script라면 상황에 따라 적절히 async, defer를 지정하여 렌더링이 차단되는 점을 개선할 수 있습니다. (참고자료)
AS-IS | TO-BE |
LCP: 8.1초 | 3.5초 |
불필요하게 로드되었언 이미지 리소스 크기: 2,270KiB | 0 KiB |
기존 코드의 문제점은 뷰포트에 상품 목록 화면이 보이지 않아도 API 요청과 이미지 로드를 하고 있었습니다.
사용자 입장에서 상품 목록을 요청하지 않아도 페이지에 접속하면 해당 리소스 만큼 로딩을 기다려야 하는 비효율이 발생합니다.
개선 방식: 특정 요소가 뷰포트 내에 노출된다면 그때 무거운 연산을 수행하도록 Intersection Observer를 사용하였습니다.
추가로 이미지가 로드될 때 레이아웃 시프팅 현상이 발생하지 않도록 스켈레톤 UI를 적용하였습니다.
AS-IS | TO-BE |
TBT: 1,670 밀리초 | 0 밀리초 |
자바스크립트 기본 스레드 작업: 2.4초 | 0.3초 |
주의해야할 점으로는 화면에서 바로 노출되어야 하는 이미지는 Lazy 로딩을 적용하면 안됩니다.
성능 최적화 과제에 대한 더 자세한 내용은 해당 깃허브 레포지토리에서 확인 가능합니다!
저는 이번에 새로운 최적화 기법을 배우면서 성급한 최적화가 좋지 않다는 것도 알게 되었습니다.
Lazy Loading 기법을 모든 이미지에 무작정 적용했을 때 첫 화면에 노출되는 배너 이미지의 로딩 속도가 오히려 느려지는 현상을 경험했습니다. 이로 인해 최적화가 항상 긍정적인 결과를 보장하지 않음을 깨닫게 되었습니다!
최적화 보다 더 중요한 것은 최적화가 필요한 부분을 신중하게 식별하고 그에 맞는 적절한 기법을 선택하는 것입니다.
이렇게 9주차에 배운 내용을 다루어 보았습니다!
다양한 성능 최적화 기법들을 배워 어떻게 적용할지 부터 급급하게 생각했는데, "성급한 최적화는 좋지 않다."라는 코치님의 조언이 가장 인상깊었습니다.
각 최적화 기법은 사용하는 상황이 있고, 무분별하게 사용하면 오히려 좋지 않기 때문에 이러한 의미에서 성능 최적화 경험이 많으면 좋을 것 같다고 뼈저리게 느꼈습니다. ㅠㅁㅠ
실습 기반의 발제 내용과 알찬 과제 구성으로 다양한 개념을 많이 배운 9주차 였습니다.
앞만 보고 달리니 벌써 마지막인 10주차가 다가오네요.
다음 주에는 전체적인 항해 플러스 프론트엔드 코스를 회고하며 마지막 후기 글로 찾아오겠습니다!
긴 글 읽어주셔서 감사합니다 :)
제가 현재 참여하고 있는 항해 플러스 프론트엔드 코스가 4기를 모집하고 있다고 하여 공유드립니다!
10월 24일까지 신청하시면 얼리버드 혜택으로 약 50% 할인을 받으실 수 있습니다.
또한 추천인 제도로 [추천인] 코드에 “zmK2OE”를 입력하시면 20만 원 추가 할인 혜택이 있으니
관심 있으신 분들은 항해 플러스 공식 홈페이지에서 신청하시면 됩니다 :)
저의 후기 글을 보시고 항해 플러스 프론트엔드 코스 관련해서 궁금한 사항이 있으시다면 링크드인 메시지 또는 이메일 yoosioff@gmail.com으로 편하게 연락주세요.
글 잘 읽었습니다 👍
그런데 첨부해주신 깃허브 레포 링크가 잘 못 연결된 것 같아요!