TIL-2024/09/08

박상우·2024년 9월 8일
0

매일 면접 연습하기

웹 성능을 최적화하기 위한 핵심 지표(LCP, FID, CLS 등)에 대해 설명하고, 이러한 지표를 개선하기 위해 프로젝트에서 어떤 방법들을 사용했는지 구체적인 사례를 들어 설명해 주세요.

측정 척도

First Contentful Paint (FCP)

페이지가 로드될때 브라우저에 첫번째 DOM 컨텐츠(Text or Image)가 랜더링 되는데 까지 걸리는 시간. 사용자에게 얼마나 빠른 피드백을 주는지 측정하는 지표

CSS와 JS 파일의 불필요한 코드를 삭제하고 파일 크기를 최적화하여 랜더링 속도를 높여 FCP를 개선할 수 있다.

Largest Contentful Paint (LCP)

페이지가 로드될 때 화면에 있는 가장 큰 컨텐츠가 랜더링 될 떄까지 걸리는 시간을 나타내는 지표.

당장 필요한 요소만 로드(Lazy Loading)하고, 중요한 웹 폰트나 이미지의 경우 미리 로드(Preloading)하여 개선할 수 있다.

Total Blocking Time (TBT)

페이지가 클릭, 키보드 입력 등의 사용자 입력에 응답하지 않게 차단된 시간을 종합한 지표. FCP와 TTI 사이의 시간을 의미하고, 메인 스레드를 독점해서 다른 동작을 방해하는 작업에 걸린 시간의 총합.

→ 긴 작업은 Web Worker나 비동기 처리하여 메인 스레드를 차단하지 않도록하여 개선할 수 있다.

Cumulative Layout Shift (CLS)

페이지 로드 과정에서 발생하는 예기치 못한 레이아웃 이동을 측정한 값. 이미지, 동적 콘텐츠를 로드하는 경우 발생한다.

→ 로드 전/후 레이아웃이 깨지지 않도록 컨텐츠의 크기를 미리 고정하는 것으로 개선할 수 있다. 이미지의 크기를 명시적으로 지정하고, font-display: swap 을 통해서 폰트가 로드되기 전 기본 폰트를 보여주어 레이아웃이 깨지는 현상을 방지할 수 있다.

Speed Index (SI)

페이지 로드 중에 콘텐츠가 시각적으로 표시되는 속도를 나타내는 지표. Lighthouse는 먼저 브라우저에서 페이지 로드 동영상을 캡처하고 프레임 간의 시각적 진행을 계산한 값

→ 이미지, 동영상 컨텐츠를 최적화하고, Lazy Loading 기법을 사용한다.

Time To Interactive (TTI)

사용자가 페이지와 사용작용이 가능해지기 까지 걸리는 시간을 측정한 지표

→JS 파일을 async 키워드 또는 defer 키워드를 통해서 비동기적으로 로드하여 해당 수치를 개선할 수 있다.


이미지 최적화

적절한 이미지 사용

예제에 사용된 이미지는 1200px x 1200px 크기의 이미지를 사용하고 있었는데 실제 랜더링 되는 사이즈는 120px X 120px이어서 필요한 이미지의 크기보다 너무 큰 이미지를 사용하고 있기 떄문에 적절한 크기로 이미지를 조절해주는 것이 좋다. ( 책에서 제시한 적절한 사이즈는 요즘 디스플레이의 성능을 고려했을때 랜더링하고 싶은 이미지의 가로 2배, 세로 2배 정도로 사이즈를 조절하는 것이 적절하다 라고 명시해두었다. )

API를 통해 이미지를 받아오는 경우 이미지 CDN을 통해 이미지 사이즈를 임의로 조절하는 방식을 사용할 수 있다.

이미지 CDN

물리적 거리 한계를 극복하기 위해 사용하는 쪽에 가깝게 콘텐츠(이미지) 서버를 두는 기술을 말한다. 기본적인 서버의 위치를 임의로 바꾸는 것 외에 컨텐츠의 크기를 바꾸거나 포멧을 변경할 수 있다는 점도 있다.


병목 코드 최소화

Performance 탭에서 페이지가 로드 되는 과정 중 JS의 파일을 실행하는 시간을 살펴보면 이상하게 시간이 많이 걸리는 부분이 있다.

그 부분의 작업내용을 보고 실행시간이 많이 걸리는 부분이 존재한다면 코드를 개선해서 성능을 최적화 할 수 있다.

방법으로는 1. 효율적인 코드로 개선 / 2. 작업량을 줄여주기 등이 있을 수 있다.

코드분할/지연로딩

번들링 된 파일 중 불필요하게 큰 사이즈의 번들링 파일을 확인해서 분리할 수 있다.

리소스의 다운로드가 늦어지면 다운로드가 완료된 이후에 화면을 그릴 수 있기 떄문에 자연스럽게 화면이 늦게 뜬다.

cra-bundle-analyzer를 통해 번들 파일을 구성하는 파일들의 크기를 확인해보고, 비중이 높은 파일들이 어떤 컴포넌트에서 참조새허 사용하는지 추적한다. 한번에 모든 리소스를 다운받지 않고, 이후 필요한 시점에서 다운로드할 수 있도록(지연코드) 코드를 분할하는 과정을 통해 번들 파일일 크기를 조절한다.

// import문을 통한 동적(dynamic) import 해보기

// 일반 import
import { add } from './math';

console.log(`1 + 4 = ${add(1,4)}`);

// 이때 add 모듈은 빌드시 함께 번들링된다.

// 동적 import
import('add').then((module) => {
	const { add } = module;

	console.log(`1 + 4 = ${add(1,4)}`);	
});
// 동적 import를 활용하면 런타임에 해당 모듈을 로드한다.
// React에서 동적(dynamic) import 활용하기 => lazy 함수
import React, { Suspense, lazy } from "react";
import { Switch, Route } from "react-router-dom";
import "./App.css";

const ListPage = lazy(() => import("./pages/ListPage/index"));
const ViewPage = lazy(() => import("./pages/ViewPage/index"));

function App() {
  return (
    <div className="App">
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route path="/" component={ListPage} exact />
          <Route path="/view/:id" component={ViewPage} exact />
        </Switch>
      </Suspense>
    </div>
  );
}

export default App;

텍스트 압축

텍스트 압축도 앞서 했던 코드 분할과 같이 리소스의 사이즈를 줄여 리소스 다운로드 시간을 최적화하는 기법이다.

해당 리소스는 서버에서 텍스트를 압축해서 전달 할 수 있도록 수정한다.

profile
나도 잘하고 싶다..!

0개의 댓글

관련 채용 정보