최적화란?

걸음걸음·2023년 3월 30일
0

최적화(Optimization)

주어진 조건으로 최대 효율을 내는 것
가능한 적은 리소스를 소모하면서 가능한 한 빠르게 원하는 결과를 얻을 수 있도록 하는 것
주어진 조건 아래에서 최대한 빠르게 화면을 표시하도록 만드는 것

최적화의 필요성 및 효과

이탈률 감소

웹 사이트의 성능 최적화를 통해 페이지 로딩 속도를 줄이면, 사용자의 이탈률을 효과적으로 줄일 수 있음

전환율 증가

수익 증대

사용자 경험(UX) 향상

최적화 기법

HTML, CSS 코드 최적화

DOM 트리 가볍게 만들기

DOM 트리는 깊을 수록, 자식 요소가 많을 수록 복잡도가 커지고 DOM 트리가 변경되었을 때 계산해야 하는 것이 많아짐

  • 불필요하게 깊이를 증가시키는 요소는 삭제

인라인 스타일 사용하지 않기

인라인 스타일로 코드를 작성하면 스타일 속성을 중복으로 작성하게 되는 경우가 발생, 불필요한 코드 중복은 가독성을 떨어트리고 파일 크기를 증가
CSS 파일을 따로 작성했을 땐 단 한 번의 리플로우만 발생시키는 것과 달리 인라인 스타일은 리플로우를 계속해서 발생, 렌더링 완료 시점이 늦어짐.

사용하지 않는 CSS 제거

간결한 셀레겉 사용

// 복잡한 셀렉터 예
.main .container .box { ... }
// 가능한 한 갈결하게 작성
.box { ... }

리소스 로딩 최적화

JavaScript 파일을 불러오는 <script>, CSS 파일을 불러오는 <link> 등의 요소를 사용할 때, 파일을 불러오는 위치가 어디인가에 따라 렌더링 완료 시점이 달라짐

CSS 파일 불러오기

CSSOM 트리는 CSS 코드를 모두 해석해야 구성할 수 있으므로 CSSOM 트리는 HTML 문서의 최상단에 배치

JavaScript 파일 불러오기

HTML 코드 파싱 중 <script> 요소를 만나면 해당 스크립트가 실행, 스크리븥 요소 이전까지 생성된 DOM 까지만 접근 가능.
스크리트 실행이 완료되기 전까지 DOM 트리 생성이 중단.
따라서 JavaScript 파일은 DOM 트리 생성이 완료되는 시점인 HTML 문서 최하단에 배치하는 것이 좋음

브라우저 이미지 최적화

이미지 스프라이트

여러 개의 이미지를 모아 하나의 스프라이트 이미지를 만들고 CSS의 background-positon 속성을 사용, 이미지의 일정 부분만 클래스 등으로 구분하여 사용하는 방법
해당 방법을 사용하면 네트워크 로딩 시간을 줄일 수 있으며 관리가 용이함

아이콘 폰트 사용

아이콘 사용이 많을 때는 아이콘 폰트를 사용하여 용량을 줄일 수 있음

  • Font Awesome
    CDN으로 사용 : Font Awesome에서 발급한 키트를 HTML 파일의 <head> 요소에 넣어 사용
    모듈 설치 : 라이브러리처럼 설치해서 사용

WebP 또는 AVIF 이미지 포맷 사용

JPEG 또는 PNG 대신 WebP 또는 AVIF를 사용, 용량을 감소

  • 모든 브라우저에 호환되지 않는다는 단점이 있음
    HTML <picture> 태그를 사용해 보완 가능, 각 브라우저의 호환에 맞도록 분기 대체
<picture>
  <source srcset="logo.webp" type="image/webp">
  <img src="logo.png" alt="logo">
</picture>

CDN 사용

콘텐츠를 좀 더 빠르고 효율적으로 제공하기 위해 설계, 유저가 가까운 곳에 위치한 데이터 센터(서버)의 데이터를 가져오는 방식.

캐시 관리

캐시 : 다운로드 받은 데이터나 값을 복사해 두는 임시 장소

  • 브라우저 캐시를 활용하면
    캐시가 유효한 시간 동안 네트워크 리소스 절약 가능
    파일을 다시 받아올 필요가 없어 브라우저 로딩이 빨라짐
    빠른 사용자 경험 제공 가능

캐시 검증 헤더, 조건부 요청

  • 캐시 검증 헤더
    캐시에 저장된 데이터와 서버의 데이터가 동일한지 확인하기 위한 정보를 담은 응답 헤더
    Last-Modified : 데이터가 마지막으로 수정된 시점을 의미하는 응답 헤더. 조건부 요청 헤더인 If-Modified-Since 와 묶어 사용
    Etag : 데이터의 버전을 의미하는 응답 헤더. 조건부 요청 헤더인 If-None-Match 와 묶어 사용.

  • 조건부 요청 헤더
    캐시의 데이터와 서버의 데이터가 동일하다면 재사용하게 해달라는 의미의 요청 헤더
    If-Modified-Since : 캐시된 리소스의 Last-Modified 값 이후에 서버 리소스가 수정되었는지 확인, 수정되지 않았다면 캐시된 리소스를 사용
    If-None-Match : 캐시된 리소스의 ETag 값과 현재 서버 리소스의 ETag 값이 같은지 확인, 같으면 캐시된 리소스를 사용

Tree Shaking

불필요한 코드 제거를 의미

JavaScript 트리 쉐이킹

  • 필요한 모듈만 import
    필요한 모듈만 불러오면 번들링 과정에서 사용하는 부분의 코드만 포함, 트리쉐이킹이 가능해짐
  • Babelrc 파일 설정
    Babel은 자바스크립트 문법이 구형 브라우저에서도 호한 가능하도록 ES5 문법으로 변환하는 라이브러리. ES5 문법으로 바꾸면 import 되는 모든 모듈을 불러오기 때문에 Babelrc 파일에 다음과 같은 코드를 작성해 ES5 변환 방지
{
  “presets”: [ 
    [
      “@babel/preset-env”,
      {
	    "modules": false
      }
    ]
 ]
}
  • sideEffects 설정
    웹팩은 사이드 이펙트를 일으킬 수 있는 코드의 경우, 사용하지 않는 코드라도 트리쉐이킹 대상에서 제외
    package.json 파일에서 sideEffects 설정, 코드를 제외시켜도 됨을 웹팩에 전달 가능
{
  "name": "tree-shaking",
  "version": "1.0.0",
  "sideEffects": false
}
// 특정 파일에서는 발생하지 않을 것임을 알릴 때
{
  "name": "tree-shaking",
  "version": "1.0.0",
  "sideEffects": ["./src/components/NoSideEffect.js"]
}
  • ES6 문법 사용하는 모듈 사용

Lighthouse

사이트를 검사하여 성능 측정을 할 수 있는 도구
다양한 지표를 이용, 성능 검사 뿐 아니라 개선책도 제공

  • Chrome 에서 사용할 때
  1. 검사하고 싶은 페이지의 url 입력
  2. 개발자 도구
  3. lighthouse 탭 클릭
  4. Generate report 클릭(특정한 지표만 검사도 가능)
  5. 리포트가 해당 페이지의 개발자 도구 내에 생성됨
  • Node CLI 에서 실행
  1. Lighthouse 설치(전역모듈 설치 권장)
npm install -g lighthouse
  1. 검사 실행
lighthouse <url>

** 모든 옵션 보기 lighthouse --help

분석 결과 항목

  • Performance : 웹 성능 측정
  • Accessibility : 웹 접근성을 잘 갖추고 있는지 확인
  • Best Practices : 웹 표준 모범 사례를 잘 따르고 있는지 확인
  • SEO : 검색 엔진 최적화가 잘 되어있는지 확인
  • PWA(Progressive Web App) : 모바일 애플리케이션으로서도 잘 작동하는지

Performance 측정 메트릭

  • First Contentful Paint(FCP)
    일부 콘텐츠의 첫 번째 렌더링 시점 측정
  • Largest Contentful Paint(LCP)
    주요 콘텐츠 로딩 완료된 시점 측정
  • Speed Index
    페이지를 로드하는 동안 얼마나 빨리 컨텐츠가 시각적으로 표시되는지를 측정
  • Time to interactive(TTI)
    페이지가 로드되는 시점부터 사용자와의 상호작용이 가능한 시점까지의 시간 측정
  • Total Blocking Time(TBT)
    페이지가 유저와 상호작용하기까지의 막혀있는 시간 측정
  • Cumulative Layout Shift(CLS)
    사용자에게 컨텐츠가 화면에서 얼마나 많이 움직이는지(불안정한지)를 수치화한 지표

사용 예시(네이버)

  • Serve images in next-gen formats
    Image formats like WebP and AVIF often provide better compression than PNG or JPEG, which means faster downloads and less data consumption. Learn more.
    (WebP 및 AVIF와 같은 이미지 형식은 종종 PNG 또는 JPEG보다 더 나은 압축 기능을 제공하므로 다운로드 속도가 빨라지고 데이터 사용량이 줄어듭니다.)

  • Reduce unused JavaScript
    Reduce unused JavaScript and defer loading scripts until they are required to decrease bytes consumed by network activity.
    (사용되지 않는 JavaScript를 줄이고 네트워크 작업에 사용되는 바이트를 줄이기 위해 필요할 때까지 스크립트 로드를 연기합니다.)
    ** React의 경우 SPA이기 때문에, 최초 로딩 시간이 길어짐 > 당장 사용하지 않는 코드를 읽어옴. 코드 스플리트를 적용하면 해당 부분을 해결하고 성능을 향상할 수 있음.

  • Reduce unused CSS
    Reduce unused rules from stylesheets and defer CSS not used for above-the-fold content to decrease bytes consumed by network activity.
    (스타일시트에서 사용되지 않는 규칙을 줄이고 상위 내용에 사용되지 않는 CSS를 연기하여 네트워크 활동에 의해 소비되는 바이트를 줄입니다.)

  • Efficiently encode images
    Optimized images load faster and consume less cellular data.
    ( 최적화된 이미지는 더 빨리 로드되고 셀룰러 데이터를 덜 소비합니다. )

  • Eliminate render-blocking resources
    Resources are blocking the first paint of your page. Consider delivering critical JS/CSS inline and deferring all non-critical JS/styles.
    (리소스가 페이지의 첫 번째 그림판을 차단하고 있습니다. 중요한 JS/CSS를 인라인으로 제공하고 중요하지 않은 모든 JS/스타일을 연기하는 것을 고려합니다.)

  • Avoid an excessive DOM size
    A large DOM will increase memory usage, cause longer style calculations, and produce costly layout reflows.
    (DOM이 크면 메모리 사용량이 증가하고 스타일 계산이 길어지며 비용이 많이 드는 레이아웃 리플로우가 생성됩니다.)

profile
꾸준히 나아가는 개발자입니다.

0개의 댓글