최적화(Optimization)란?
우리는 어떠한 일을 할 때 "효율적"으로 하길 원한다.
같은 노력을 들여도 덜 힘들고 더 좋은 결과를 얻길 바라는 모습은 어찌보면 당연한 것이 아닐까 싶다. 이러한 특징이 유독 눈에 띄는 것이 한국인이지만, 세계 어디에서도 효율적인 일처리 방식을 싫어하는 사람은 없다고 생각한다.
최적화(Optimization)란, 허용된 자원의 한계 내에서 주어진 요구사항을 만족시키면서 최선의 결과를 얻는 과정이다. 수익과 관련되는 분야에서는 이익을 최대로 내는 과정을 의미할 수 있고, 수학과 관련되서는 특정의 집합 위에서 정의된 실수값, 함수, 정수에 대해 그 값이 최대나 최소가 되는 상태를 해석하는 방법이 될 수 있다.
이렇듯 "최적화"라는 개념은 다양한 분야와 때에 따라 다르게 정의할 수 있는데, 근본적으로 주어진 조건으로 최대 효율을 내는 것을 말한다.
웹 개발에서의 최적화 기법
그렇다면 설계(Design)적 측면, 나아가 웹 개발에서의 최적화란 무엇일까?
웹 개발에서의 최적화란 "주어진 조건 아래에서 최대한 빠르게 화면을 표시하도록 만드는 것"을 의미한다.
웹 페이지를 빨리 띄우는 것은 언뜻 생각하기엔 쉬워보이지만, 우리가 자주 이용하는 웹 사이트들을 생각해보면 그렇지 않다는 것을 알 수 있다.
우리가 방문하는 대부분의 웹 사이트들은 하나의 웹 페이지로 구성되어 있지 않고 여러 개의 웹 페이지들이 서로 연결되어 있는 구조를 가지고 있다. 또한 하나의 웹 페이지에서도 단순히 정보를 나열해 놓는 것에 그치지 않고, 사용자가 사용하기 편안한 인터페이스 구성과 디자인을 가지고 있어 보다 최적의 사용자 경험(UX)을 제공하고자 한다.
하지만 유저 친화적인 디자인과 기능은 단순히 HTML 파일에 인터넷 구조를 적는 것에 그쳐서는 구현할 수 없다.
더 나은 디자인을 제공하기 위한 CSS, 기능을 구현하기 위한 자바스크립트 파일을 작성해야 하고, 웹 페이지와 연결시켜 적용시켜야 한다.
이러한 과정을 거치다보면 결국 "빠르게 화면을 표시하는 것"과는 멀어진다.
앞서 언급했듯 단순히 HTML 파일을 작성하는 것으로는 지금의 웹 사용자에게 매력적인 웹 사이트를 만들 수 없다.
결국 우리는 주어진 조건(좋은 디자인과 성능)에서 최대한 빠르게 화면이 표시될 수 있는 방법을 모색해야 하는데, 이를 "최적화 기법"이라고 한다.
Lighthouse를 활용한 최적화
웹 최적화를 위한 최적화 기법에는 코드 최적화, 캐시 관리, Tree shaking 등 다양한 기법이 있다.
하지만 이번 포스팅에서는 Lighthouse라는 자동화 툴의 사용 방식에 더 집중할 예정이다.
Lighthouse란, 구글에서 개발한 오픈소스 자동화 도구로, 웹 사이트를 검사해 성능 측정을 할 수 있다.
사용 방법도 간단한데, 크롬 개발자 도구에서 Lighthouse 탭을 들어가 해당 웹 페이지를 검사하는 방법과 Node CLI에서 실행하는 방법이 있다.
Node CLI에서 실행하는 방법은 다음과 같다.
// 설치
npm install -g lighthouse
// 명령어로 검사 실행
lighthouse <url>
Lighthouse를 사용하는 것은 근본적으로 같으므로 개발자 도구를 통해 분석해보도록 하자.
먼저 분석하고 개선하고자 하는 웹 사이트를 고른다.
페이지 분석이 완료되면 다음과 같이 각 분야의 점수가 전체 요약된 설명을 시작으로 세세한 분석 결과가 나온다.
분석 결과 항목에는 총 다섯 가지 항목이 있다.
- 웹 성능을 측정하는 Performance
- 웹 접근성을 확인하는 Accessibility
- 웹 표준을 잘 따르고 있는지 확인하는 Best Practices
- 검색 엔진 최적화를 측정하는 SEO(Search Engine Optimizer)
- 웹 사이트가 모바일 애플리케이션으로 잘 작동하는지 확인하는 PWA(Progressive Web App)
Lighthouse에서 각 평가 항목을 측정하기 위한 메트릭(측정기)으로는 여섯 가지 항목이 있으며, 위와 같이 결과를 통해 어떤 메트릭에서 낮은 평가를 받았는지 알 수 있다.
- First Contentful Paint (FCP): 사용자가 페이지에 접속했을 때 브라우저가 DOM 컨텐츠의 첫 번째 부분을 렌더링하는 데 걸리는 시간을 측정
- Largest Contentful Paint (LCP): 뷰포트를 차지하는 가장 큰 콘텐츠(이미지 또는 텍스트 블록)의 렌더 시간을 측정
- Speed Index: 성능(Performance) 지표를 추적
- Time to interactive (TTI): 페이지가 로드되는 시점부터 사용자와의 상호작용이 가능한 시점까지의 시간을 측정
- Total Blocking Time (TBT): 페이지가 유저와 상호작용하기까지의 막혀있는 시간을 측정 (Lighthouse에서는 FCP와 TTI 사이에 긴 시간이 걸리는 작업들을 모두 기록하여 TBT를 측정)
- Cumulative Layout Shift (CLS): 사용자에게 컨텐츠가 화면에서 얼마나 많이 움직이는지(불안정한 지)를 수치화한 지표
위의 결과를 통해 성능 개선이 시급한 부분은 뷰포트를 차지하는 가장 큰 콘텐츠가 렌더되는데 너무 많은 시간을 사용하고 있다고 한다.
현재 웹 페이지에서 뷰포트를 차지하는 가장 큰 콘텐츠는 상품 이미지와 텍스트를 포함하고 있다. 이를 위해서 현재 사용 중인 파일 형식인 .jpg를 .webp 형식으로 교체할 수 있다.
단, WebP 파일 형식은 감소된 용량에 비해 일부 브라우저에서 호환되지 않기 때문에 보다 적절한 고려가 필요하다. 따라서 srcset 속성을 통해 각 브라우저의 호환에 맞도록 분기를 대체한다.
<picture>
<source srcset="logo.webp" type="image/webp">
<img src="logo.png" alt="logo">
</picture>
Speed Index의 경우 페이지를 로드하는 동안 얼마나 빨리 컨텐츠가 시각적으로 표시되는지, 즉 성능 지표를 추적한다.
구글 Lighthouse에선 Speed Index를 통한 성능 향상 방안으로 다음과 같이 추천하고 있다.
자세히 읽어보면 랜더링 과정이 다소 오래 걸리기 때문에 자바스크립트 코드 경량화와 메인 스레드의 부담을 줄여줄 방법 등을 선택할 수 있다.
즉, 현재 사용 중인 자바스크립트 코드에서 사용되지 않고 있는 코드가 있는지, 시간이 오래 소요되는 기능의 최적화가 이루어져 있는지, 중복해서 사용하는 기능이 불필요하게 사용되고 있는지 등을 확인하고 수정할 수 있다.
또한, HTTP/2 버전을 활용한 PRPL(웹 페이지를 로드하고 대화식으로 더 빠르게 만드는 데 사용되는 패턴을 설명하는 약어) 패턴으로 즉시 로딩 적용을 시키는 방법도 있다.
연계해서 사용자에게 컨텐츠가 화면에서 얼마나 많이 움직이는지(불안정한 지), 즉 콘텐츠의 불안정성을 수치화한 지표인 CLS 역시 이미지 형식 변화, 크기가 정해지지 않은 이미지의 width/height 속성 지정, 애니메이션 최적화 및 축소화 등을 통해 개선할 수 있다.
또한, FOIT(브라우저가 폰트를 다운로드 하기전에 폰트가 보이지 않는 현상) / FOUT(브라우저가 폰트를 다운로드하기전에 폰트가 적용되지 않은 글자가 보이는 현상)을 유발하는 웹 글꼴을 개선하기 위해 핵심 웹 글꼴에 font-display, <link rel=preload> 속성 등을 활용할 수 있고, Font Loading API를 사용해 필요한 글꼴을 가져오는데 걸리는 시간을 줄일 수 있다.
또한, Lighthouse에서는 이를 위한 개선 방안도 제시해주기 때문에 이를 참고해 기존 코드를 개선시킬 수 있다.
물론 애플은 이미 각고의 노력을 들이고 있을 것이다...
참조
- MDN - font-diplsay 속성
- Chrome Developers - How to improve your Speed Index score
- web.dev - 빠른 로드 시간, CLS
- patterns.dev - PRPL Pattern
'Front-End > 자바스크립트 (JavaScript)' 카테고리의 다른 글
[자바스크립트] 프로토타입 (Prototype) (0) | 2022.09.26 |
---|---|
[자바스크립트] 객체 지향 프로그래밍(OOP): 클래스와 인스턴스 (2) | 2022.09.21 |
[자바스크립트] 스코프 (Scope) (0) | 2022.09.14 |
[자바스크립트] 원시(Primitive) 자료형과 참조(Reference) 자료형 (1) | 2022.09.13 |
[자바스크립트] 배열(Array)과 객체(Object) (2) | 2022.09.13 |
댓글