왜 웹사이트의 퍼포먼스 최적화가 중요한가?

우리가 서비스를 제공하는데 있어 항상 최고의 사용자 경험을 선사하기 위해 노력해야 하고 최고의 사용자 경험을 제공함에 있어 즉각적인 페이지 로드가 선행되어야 합니다.

이용자들은 페이지가 로드되는데 한참이 소요된다면 대부분 페이지가 모두 로드되기까지 기다리지 않고 바로 사이트를 이탈할 가능성이 높기 때문이죠.

또한 페이지를 로드하는 속도가 느리다는건 그만큼 많은 데이터를 로드하여 사용자의 한정된 데이터 자원을 크게 소모하게 만드는 것처럼 느껴지므로 이용자는 거부감을 느낄 수 있습니다. ( 특히 모바일 환경은 한정된 데이터를 초과해서 사용하면 별도의 요금이 부과됩니다. )

유명한 소셜 네트워크 서비스인 핀터레스트는 페이지 로드 시간을 개선시켜 전환율의 증가로 이어지는 긍정적인 효과를 얻었습니다.

핀터레스트는 페이지 로드 시간을 40% 감소시킴으로써 검색엔진을 통해 유입된 트래픽 및 가입자 전환율이 15% 증가하였습니다.

https://medium.com/pinterest-engineering/driving-user-growth-with-performance-improvements-cfc50dafadd7

그리고 BBC는 페이지 로드 속도가 느려짐으로 인해 부정적인 효과가 나타난 경우도 있습니다.

BBC는 사이트가 로딩하는 데 걸리는 매초마다 10%의 추가 사용자들이 감소했음을 발견했다.

https://www.creativebloq.com/features/how-the-bbc-builds-websites-that-scale

이런 사례들을 통해 알 수 있듯이 사이트의 퍼포먼스는 우리가 꼭 신경써야하는 부분임을 알 수 있습니다.

이제 본격적으로 사이트의 로드 속도를 최적화하는 방법들에 대해 알아보겠습니다.


서버단의 최적화

압축

간단히 웹서버의 압축 옵션을 활성화하는 것만으로도 HTTP 응답 크기를 획기적으로 줄여 큰 성능 향상 효과를 얻을 수 있으니 설정이 되어있지 않다면 필수로 활성화 하시기 바랍니다.

일부 정적인 에셋들(이미지,폰트,PDF 파일 등)은 처리가 되지 않는다는 점을 제외하고는 서버에서 전송되는 데이터가 압축되어 전송됩니다.

클라이언트와 서버의 압축 옵션 정보는 크롬의 개발자도구의 네트워크 탭에서 요청/응답 헤더를 보시면 확인할 수 있습니다.

  • 클라이언트가 지원하는 압축 방식은 요청 헤더의 accept-encoding 항목에서 확인 할 수 있습니다.
  • 서버가 클라이언트의 요청을 받아 처리한 압축 방식은 서버 응답 헤더의 content-encoding 항목에서 확인 가능합니다.

HTTP 요청 줄이기

압축 설정만으로도 데이터의 크기를 줄일 수 있지만, HTTP의 요청 수를 최소화하여 페이지의 로드 시간을 더욱 줄일 수 있습니다.

보편적으로 취할 수 있는 방법들:

  • 에셋(JS,CSS) 번들
    웹페이지에서 사용하는 JS, CSS 파일들을 번들로 합쳐서 HTTP의 요청 수가 줄어든다.
  • 이미지 스프라이트
    여러개의 이미지를 하나의 파일로 합쳐서 관리하면 개별 이미지를 사용할때 보다 HTTP 요청이 줄어든다.

CDN 서비스 사용

CDN(Content Delivery Network) 서비스는 여러 지역에 데이터를 저장해두고 사용자가 접속한 위치에서 가장 가까운 서버에서 데이터를 전송해주는 서비스입니다.

이렇게 사용자의 위치와 가까운 서버일수록 데이터의 전송속도가 빨라져 페이지의 로드 성능도 향상됩니다.

CDN 작동 예시 이미지
CDN 작동 예시 이미지

Cache-Control Header 사용

캐시는 동일한 처리를 여러번 반복하지 않도록 하여 성능을 향상시키는 방법입니다.

정적인 리소스(로고, 폰트, 외부 라이브러리 등)들은 내용이 변경되는 경우가 별로 없습니다.

이러한 리소스들은 캐시의 갱신 주기를 길게 설정해두면 리소스 로딩시 캐시로 우선 처리되어 페이지 로드 속도가 향상됩니다.

반대로 자주 변경되는 리소스들은 캐시 갱신 주기를 짧게 설정하여야 합니다.

클라이언트단의 최적화

HTML 최적화

  • 자바 스크립트는 하단에 작성하기
    웹 페이지 코드는 상단부터 한줄씩 처리되는데 자바스크립트 코드가 HTML 요소들보다 상단에 작성되어있다면 스크립트를 처리하는 동안 HTML 요소들이 화면에 보여지지 않게 됩니다.
    ( 스크립트를 하단에 작성하는 방법대신 async, defer 속성을 사용할 수도 있습니다. )
  • 리소스를 외부에 배치하여 사용하기
    리소스를 외부에 배치하여 사용하면 캐싱을 활용 할 수 있어 내부에 리소스를 배치하여 사용하는 것보다 페이지 로드 속도 향상 효과를 얻을 수 있다.
  • DOM 엘리먼트 수 줄이기
    DOM 엘리먼트가 많을 수록 HTML 파일의 데이터가 증가하여 다운로드 소요시간이 증가하고 자바스크립트의 DOM 요소를 처리하는 속도도 느려지게 됩니다.

    현재 HTML 파일에서 얼마나 많은 DOM 요소를 사용하는지는 아래의 코드로 확인해볼 수 있습니다.
document.querySelectorAll('*').length

CSS 최적화

  • 복잡한 셀렉터를 사용하지 않는다.
    일반적으로 프로젝트의 규모가 커질 수록 CSS 셀렉터도 복잡해지게됩니다. 그러나 셀렉터를 복잡하게 사용하는것보다 별도의 class 를 지정해주는게 속도 뿐만아니라 가독성에도 도움이 됩니다.
/* 변경 전 */
.class:nth-last-of-type(3n+0) { ... }

/* 변경 후 */
.class--special { ... }
  • 그리기 영역 감소
    그리기는 브라우저가 페이지를 화면에 보여주기 위한 중요한 단계 중 마지막 단계이고 레이아웃이나 엘리먼트의 형태가 변경되면 브라우저는 변경점들을 다시 그리게 되는데, 이때 실제 다시 그려야하는 범위보다 더 넓은 범위의 화면을 다시 그려야 할 수도 있습니다.

    따라서 불필요한 영역을 다시 그림으로인한 퍼포먼스의 감소를 줄이기 위해 필요한 부분만 다시 그려지도록 개선해야합니다.

    크롬의 개발자도구의 Rendering 탭을 열고 Paint flashing 옵션을 체크하면 어느 시점에 어떤 영역이 다시 그려지는지 확인이 가능하므로 불필요한 다시 그리기가 처리되지는 않는지 확인하고 개선시켜보세요.
크롬의 개발자도구의 Rendering - Paint flashing
크롬의 개발자도구의 Rendering – Paint flashing

자바스크립트 최적화

  • 복잡한 연산은 web worker 활용하기
    자바스크립트는 브라우저의 메인쓰레드에서 작동합니다. 그렇다는건 장시간 소요되는 작업을 처리하는 동안 페이지가 멈추거나 유저의 인터렉션이 처리되지 않게됩니다. 만약 무거운 연산이 필요한 작업을 해야한다면 web worker 사용을 고려하세요.

    web worker는 개별 쓰레드, 논블록킹으로 작동됩니다.
    ( 다만 web worker 사용시에는 DOM 요소에 접근할 수 없습니다. )
  • 크롬 개발자도구 – 커버리지 기능 사용
    커버리지 탭은 페이지가 로드되면서 작동하는 코드들을 확인할 수 있는 강력한 툴입니다.

    빨간줄로 표시된 부분은 페이지 로드시 실행되는 코드가 아니란 표시입니다.
    ( 추후 별도의 액션에 의해 실행될 수도 있지만 실행되지 않을 수도 있으므로 사용하지 않는다면 제거해야하는 코드가 되겠죠. )
  • 사소한 최적화 방지
    최적화라는 단어에 꽃혀서 무턱대고 모든 파일을 최적화하다보면 가독성까지 떨어뜨리면서 최적화를 하게 되는 경우가 발생할 수 있다.

    이러면 오히려 안하느니만 못한 ( 퍼포먼스에도 영향이 미미하고 가독성만 떨어뜨리니)게 될 수 있으니 꼭 필요한 부분인지 면밀히 검토한 후 최적화하시길 바랍니다.

이미지 최적화

  • 이미지 대신 CSS 사용하기
    이미지를 최적화하는 최고의 방법은 이미지를 사용하지 않는 방법이지만 우리는 복잡한 UI 요소들을 사소한 디자인적인 디테일까지 처리하면서 사용하고 있습니다.

    만약 쉐브론, 토글, 그림자, 패턴과 같은 디자인을 적용할 때 이미지대신 CSS 로 처리가 가능하다면 CSS로 처리하는 방법을 선택하는게 좋습니다.
  • 벡터 이미지 사용하기
    벡터 이미지는 해상도, 화면크기에 상관없이 자유롭게 사용할 수 있으므로 어떤 환경에서도 잘 어울리게 만들 수 있습니다. 또한 래스터 이미지와는 달리 크기가 작습니다.
  • 올바른 래스터 포맷 사용
    JPG, PNG, GIF 중 올바른 포맷을 사용하세요. 만약 애니메이션이 필요하면 GIF, 투명도처리가 필요하다면 PNG, 이외의 경우에는 JPG를 사용하세요.
  • 이미지 사이즈 조정
    이미지가 웹 페이지에 보여질때, 이미지는 웹페이지에 보여질 공간에 맞춰 리사이징 됩니다.
    만약 페이지에 보여지는 이미지 크기가 최대 600px 을 넘지 않는다면 600px 로 조정하세요.

폰트 최적화

  • 폰트 사용을 최소화
    퍼포먼스를 증가시키는 방법중 가장 간단하며 확실한 방법입니다.

    많은 웹사이트들 대부분은 5개 이하의 폰트를 사용하며, 폰트를 최소화 하는것은 성능 뿐만 아니라 일관성이 없는 사이트가 될 가능성이 있습니다.
  • 필요한 언어 폰트만 사용
    많은 폰트들이 다양한 언어를 지원하는데, 만약 사이트가 영어만 사용한다면 영어 이외의 폰트파일은 제거해야 합니다.
  • 폰트 사전로딩
    마지막으로 브라우저가 폰트를 가장 우선해서 로딩하도록 link 태그에 preload 옵션을 설정하세요.
<link rel="preload" href="font.woff2" as="font" />

마치며

여기까지 웹사이트의 성능을 향상시키는 방법들에 대해 알아보았는데요.

웹사이트의 성능을 향상시키기 위해서는 최적화 작업이 꾸준히 진행되어야 합니다.
웹사이트가 눈에 보이도록 느려질때는 이미 개선하기 어려울만큼 다양한 요소들이 복합적으로 작용하는 경우도 많기 때문이죠.

꼭 겉으로는 문제가 없어보여도 정기적으로 체크해서 사이트의 퍼포먼스를 최적화하시길 바랍니다.

감사합니다.