프론트엔드 웹 성능 최적화 Part.1

이수빈·2023년 12월 27일
0

React

목록 보기
14/20
post-thumbnail

웹 성능의 주요 요소

  • 로딩성능과 렌더링 성능에 초점을 맞춰서 최적화

  • 어떻게 더 빠르게 리소스를 가져오는가? 어떻게 더 빠르게 화면에 가져온 리소스를 그리는가? 가 중요함.

NVM(Node Version Manager)

  • 노드 버전을 관리해주는 도구이다. => 여러개의 노드 버전 설치후 간단한 명령어를 통해 노드버전을 변경 할 수 있다.

  • 아래 링크에서 다운 가능하다.

https://github.com/coreybutler/nvm-windows/

  • 만약 nvm을 통해 설치된게 아니라, 이미 단일 node.js가 설치된 상태라면, 이를 지우고 nvm을 통해 node를 다시 재설치해야한다. (변경이 안될 수 있음)

  • 경로는 기본 program File이 들어있는 경로를 추천한다. (nvm use 했는데 버전이 변경되지 않을 수 있다.)

node -v // node version 확인
nvm -v // nvm version 확인
nvm list available // 사용가능한 node.js 버전 조회
nvm install {설치할 버전}
nvm list // 설치된 노드버전 확인방법
nvm use {사용할 버전} // Node.js 버전 변경

  • 만약 권한이 없다고 뜨면 => Cmd를 관리자권한으로 열어 실행한다.

성능 측정 도구

  • Chrome Network, Performance Tab, Audit Tab(Lighthouse임), Webpack-bundle-analyzer

Image Size 최적화

ref) https://developer.chrome.com/docs/lighthouse/performance/uses-responsive-images?utm_source=lighthouse&utm_medium=devtools&hl=ko

  • Light House에 Properly Sized Images 라는 항목이 존재함. LightHouse는 페이지의 각 이미지에서 렌더링된 이미지의 크기를 실제 이미지의 크기와 비교함 => 렌더링된 크기가 실제 크기보다 4KiB 이상 작으면 이미지가 감사를 통과하지 못함.

  • 예를들어, 원본사이즈가 1200x1200px인 이미지를 받아와서 120px x 120px 로 렌더링을 하려고 하면, 브라우저에서 resize를 계산하는 시간이 오래걸림

  • 애초에 1200x1200을 => 240x240정도로 보내는게 이상적임 ( 요즘 많이 쓰는 레니타 디스플레이는 같은 공간에 더 많은 픽셀을 그릴 수 있기 때문에 너비기준 2배정도 큰 이미지를 사용하는게 적절함.)

  • 반응형이미지나 이미지 CDN을 통해 적절한 크기의 이미지를 제공할 수 있다.

  • 이미지 cdn) : https://web.dev/articles/image-cdns?hl=ko

  • CDN : Content Delivery Network

  • ImgIX와 같은 CDN 솔루션을 사용 : https://imgix.com/

  • unsplash에서 제공하는 파라미터를 이용하면 동적으로 이미지 크기조정이 가능하다.

  • 해당 파라미터는 unsplash API를 사용하는 경우 사용이 가능하다

https://unsplash.com/documentation#supported-parameters

Performance Tab

  • 페이지가 로드되면서 실행되는 작업들을 타임라인과 차트형태로 보여줌 (Network Tab보다 상세하게, 렌더링방식 보는데 유용할듯)

  • 아래는 React 방식의 CSR이므로, 번들을 받아오고 받아온 번들을 바탕으로 Client Side에서 렌더링을 한 뒤, 데이터 Fetching이 일어나는 것을 확인할 수 있음.

  • 얇은 선이 이어지는 것은 콜백함수가 실행되고 있다는 의미임

  • 중간에 FCP 와 같이 구분선이 존재함.

텍스트 압축

  • 서버에서 보내는 리소스를 압축해서 보내는 방식임.(리소스 자체의 크기를 줄인다)

  • Response Header에 Content-Encoding이라는 속성으로 확인가능하다. (있으면 압축되어 받은 형태임)

  • 보통 텍스트 압축 알고리즘으로는 Gzip vs Deflate 을 많이 사용함. GZip은 deflate 상위호환버전임

  • 압축은 서버에서 해줘야함. => 압축을 적용하고 끌 수 있는 option이 존재함.

  • 라우터서버에 압축기능을 추가할수도 있음.

  • 서버에서 압축을 하면 클라이언트에서 압축을 해제해야함. => 모든 파일을 무분별하게 압축하는게 아님. 파일크기가 2kb이상이면 인코딩, 그 이하면 안하는게 나음

애니메이션 원리

  • 애니메이션은 여러장의 이미지가 연속적으로 바뀌면서 움직이는 것처럼 보이는 트릭임.

  • 일반적으로 디스플레이의 주사율은 => 초당 60프레임. 즉 1초에 60개의 화면을 연속적으로 빠르게 보여준다는 의미 (브라우저 또한 60프레임으로 화면을 렌더링하려고 함)

  • 브라우저에서 애니메이션 버벅거림이 발생했다면 ? => 60프레임으로 화면을 렌더링하지 못했다는 뜻

  • Critical Rendering Path

  • width, height와 같이 직접적으로 크기를 변경하는 작업에서는 Critical Rendering Path에 대한 과정이 한번에 모두 실행됨. (Reflow) => 모두 다시 Flow를 타는 것.

  • Color 나 background Color가 변경된 경우? => CSS가 변경됨으로 새로운 CSSOM을 만들고 RenderTree 생성 but Layout 은 변하지 않았음 => Layout 계산을 생략한 Repaint 과정 실행

  • transform, opacity와 같이 GPU가 관여할 수 있는 속성을 변경하면 Reflow, Repaint를 피할 수 있다.

  • trasnform => scaleX를 통해 움직이는 비율을 조절 할 수 있다.

  • transform origin 으로 변하는 기준 변경가능함.

컴포넌트 Preload

  • lazy Loading으로 번들사이즈를 줄일 수 있지만, 모달과 같이 interaction이 필요한 컴포넌트가 있다면 사용자가 버튼을 클릭했을 때 바로 모달을 볼 수 없다.

  • 이때 컴포넌트 Preload 기법을 적용한다. => 클릭하기 직전 버튼위에 마우스를 올려놨을 때 모달코드를 로드하는 방법과, 최초 페이지가 로드되고 모든 컴포넌트의 마운트가 끝났을 때 모달코드를 로드하는 방식존재

  • 마우스를 올렸을 때 => onMouseEnter 이벤트핸들러적용

 const handleMouseEnter = () => {
        const component = import('./components/ImageModal');
    }
  • 아니면 초기 컴포넌트 마운트 이후 (useEffect) 안에서 modal을 import 해오는 방식도 존재함.(화면에 layout이 그려졌기 때문에 성능에 영향을 주지 않음)
function lazyWithPreload(importFunction){
    const Component = React.lazy(importFunction);
    Component.preload = importFunction;
    return Component;
}

const LazyImageModal = lazyWithPreload(()=> import('./components/ImageModal'));

 useEffect(()=>{
        LazyImageModal.preload();
    },[])

이미지 Preload

  • html 태그는 사용하는 시점에 loading됨.

  • JS의 이미지 Object를 사용하는 방법 존재 (이 JS코드가 실행되는 시점에 이미지 로드됨) => 모달의 이미지를 preload 가능함.

  • useEffect와 사용 => 리렌더링될때매다 이미지를 새로 불러오기 때문, 사용하는 이미지에 캐시가 제대로 걸려있는지 확인해야함

const img = new Image()
img.src = '이미지주소' ~~ 
profile
응애 나 애기 개발자

0개의 댓글