개발 이야기/프론트엔드 개발자

프론트엔드 성능 최적화

석구석구 2020. 8. 24. 17:30

자바스크립트가 발전하면서, FE의 덩치가 커지고 있다.

 

이전보다 성능 이슈가 발생하기 쉬워졌고,

 

발생하지 않도록 여러가지를 고려해가며 서비스개발을 해야 한다.

 

개인적으로 FE에서 서비스의 성능 향상을 위해 할 수 있는 것은 크게 다음과 같다고 생각한다.

 

  • 필요한 시점에 필요한 만큼만 요청하는, 좋은 자원 요청 방법.
  • 요청한 파일의 용량을 줄이자.
  • 괜찮은 랜더링 로직.

물론 위와 같은 방법들이 무조건 맞는 것은 아니며, 상황에 맞게 적절히 사용하는 것이 중요하다.

 

우선 브라우저가 하나의 자원을 요청하고 받기까지의 과정을 살펴보면 다음과 같다.

 

- Stalled

Request 전 대기 시간으로 cors, 캐시 할당등의 작업을 한다.

 

- DNS Lookup

도메인에 따라 IP를 찾는다. - 이후 동일 도메인으로 자원 요청시 해당 시간은 소요 되지 않는다.

 

- Initial Connection

서버와 브라우저와의 커넥션 설정을 한다.

 

- TTFB

서버에서 자원의 첫 바이트 정보를 보내기 위해 걸린 시간 - 서버에서 걸린 시간이다.

 

- Content Download

자원 다운 로드

 

(크롬의 네트워크 창의 타이밍탭을 보면 자원을 얻기 위한 과정을 볼 수 있다. )

 

자원 요청에 대한 순서를 알게 되었으니, 우리가 실제 개발에서 할 수 있는 일들을 알아보자.

 

1. 좋은 자원 요청 방법.

  • 자원 요청하는 도메인을 분산시켜라. (도메인 샤딩)
    • static.files.com 도메인으로 모든 스태틱 파일을 요청하게 되면, 크롬 기준, 동시에 6개의 파일밖에 다운 받지 못한다.
    • static-1.files.com, static-2.files.com 2개의 도메인으로 나누면, 동시에 12개의 파일을 다운 받게 된다.
    • 먼저 학습한 DNS시간이 하나 더 추가된다.
    • http 2.0에서는 유효한 방법이 아니다.
  • 요청 수를 줄이자.
    • util.js, popup.js, form.js 를 build.js 하나의 파일로 합친다면 한 번의 요청에 자원을 이용할 수 있다. (merge)
    • 사용자가 이미지 보기 버튼을 누른 상황에 이미지를 로딩하거나, 팝업 버튼을 누른 경우 팝업에 관련된 소스를 다운 받는다. (lazy)
    • 이미지 데이터를 base64로 encode하여 DataURI를 이용한다.
      • 요청수는 줄지만, 캐시가 되지 않으므로, 캐시가 필요없는 데이터에 사용한다.
    • css에서 사용되는 전반적인 이미지들은 스프라이트 기법을 사용한다.

2. 요청한 파일의 용량을 줄이자.

  • 일반적으로 로딩 데이터의 절반이 이미지 로드에 사용되므로, 이미지 크기를 줄인다.
    • 적합한 이미지 확장자 선택
    • 사용자 환경에 맞는 크기의 이미지를 사용하자.(srcset 속성 이용)
      • 브라우저는 이미지를 사용자에게 디스플레이 하기 위해 이미지 데이터를 RGB 데이터로 디코딩을 해야 한다.
      • 큰 이미지는 다운로드뿐만 아니라, 디코딩 시간도 늘어나게 된다.
    • 서비스에 맞는 크기의 이미지를 사용하자.
      • 썸네일에는 작은 이미지를 사용.
      • 이미지 압축 프로그램을 적극 이용하자.
    • 정적파일들 요청에 쓸데없는 cookie 데이터가 헤더에 포함되지 않도록 파일 서버 설정을 한다.
    • 필요한 시점에 필요한 코드를 요청하여 실행하자. (code split)

(구글의 css 스프라이트 이미지)
(구글의 DataURI 활용)
(스태틱 파일 요청 헤더에 쿠키 정보가 포함되어 있는 경우)

3. 좋은 랜더링 로직

  • SCRIPT 태그를 만나면 HTML 파싱을 멈추게 되므로 적절한 스크립트 태그 사용.
    • js파일 요청에 defer 속성을 추가하여 다운로드 시간동안 HTML파싱을 멈추지 않으며 스크립트 실행을 HTML 파싱 이후로 늦춘다.
    • js파일 요청에 async 속성을 추가하여 다운로드 시간동안 HTML파싱을 멈추지 않으며, 스크립트 실행을 다운로드 이후로 늦춘다.
  • 리플로우 발생을 줄인다.
    • 신규 dom 생성 시, 스타일 작업 후 dom tree에 추가한다.
    • display:none을 활용하여 dom tree에서 제거 후, 스타일 작업을 한다.
    • 스타일 변화에 따른, 리플로우 여부를 http://csstriggers.com 을 참고하자.
    • contain 속성을 이용하여 리플로우 범위를 좁힌다.

이러한 3가지 외에도

  • 사용자에게 중요한 정보를 먼저 보여줄 수 있는 페이지 설계. (비동기 설계로 FMP 시간을 조정해보자.)
  • 효율적인 DOM 핸들링 코드
    • dom cash 하기
    • innerHTML를 이용하여 한 번에 생성하기.
  • GPU 가속을 이용할 수 있는 적절한 레이어 구조.

물론 세상만사 코드사,

트레이드 오프가 있기에 정답은 없다. 자신의 서비스를 잘 이해하고, 그에 맞는 방법을 찾아내는 고민이 가장 중요하다.

'개발 이야기 > 프론트엔드 개발자' 카테고리의 다른 글

터미널을 이쁘게  (0) 2020.12.18
유용한 크롬 & VSCODE 확장 도구들  (1) 2020.09.02
VSync 이야기  (0) 2020.08.24
HTTP 2.0  (0) 2020.03.06
20분이면 충분한 셀레니움 UI 테스트.  (0) 2020.01.31