HTTP 요청 개수 줄이기

- 브라우저는 HTML 파일 응답을 받고 나서, HTML안에 있는 CSS, 자바스크립트, 이미지 등의 콘텐츠들을 전부 받아 올 때까지 호출함
- 콘텐츠의 수가 많을수록 로딩 완료 시간은 길어짐
- 성능을 위해서 HTTP 요청 수를 줄여야 함

 

HTTP 요청을 줄이는 방법

스크립트 파일 병합

- 자바스크립트나 CSS파일들을 기능별로 분리하여 각각의 파일로 저장하고 호출하는 방식을 사용하는데, 이 방법은 HTTP 요청 수를 증가시키는 요인임
- 모듈화 된 여러 파일들을 하나로 합치고, 이 하나의 파일을 브라우저가 실행하는 것이 여러 개의 파일들을 각각 호출하는 것과 동일한 결과를 만들 수 있다면 파일 병합으로 HTTP 요청 수를 줄일 수 있음
- 병합한 파일의 크기가 너무 크다면 그 파일을 로딩하는 시간이 너무 길어질 수 있어서 적절한 크기를 유지해야 함

인라인 이미지

CSS 스프라이트

- 여러 개의 이미지를 하나의 이미지 파일로 결합해서 필요한 이미지가 위치하는 픽셀 좌표 정보를 사용

 

콘텐츠 파일 크기 줄이기

스크립트 파일 압축 전달

- 웹 서버가 지원하는 방식으로 스크립트를 압축해 클라이언트에게 더 작은 크기로 전달하고, 클라이언트가 압축을 해제하여 원본 콘텐츠를 이용
- 서버(Content-Encoding)와 클라이언트(Accept-Encoding)가 서로가 지원하는 압축방식 중 하나를 골라서 정해야 함
- Accept-Encoding : 클라이언트가 자신이 지원하는 압축 알고리즘을 서버에 알려줌
- Content-Encoding : 서버는 클라이언트가 알려준 압축 알고리즘 중 서버가 지원하는 알고리즘 하나를 선택해서 클라이언트에게 알려줌

ex.
Accept-Encoding: gzip, defalte, sdch
Content-Encoding: gzip

 

스크립트 파일 최소화

- 스크립트 파일에 포함된 주석, 공백, 개행 문자들처럼 실제 로직에는 아무 영향을 주지 않는 부분들을 제거하여 파일의 크기를 줄이는 방법
- 개발서버에는 원본을 두고, 운영서버에는 스크립트를 최소화하여 배포
- 더 이상 변경이 일어나지 않은 것이라 예상되는 스크립트를 대상으로 최소화
- Minify

 

Minify JS and CSS online, or include the minifier in your project for on-the-fly compression.

Minify JS and CSS online, or include the minifier in your project for on-the-fly compression.

www.minifier.org

=> 스크립트 파일 최소화로 불필요한 부분을 제거하여 가볍게 만들고, 압축을 해서 클라이언트에 전달

이미지 파일 압축

- 이미지는 웹 사이트에서 가장 많은 용량을 차지하는 콘텐츠
- 이미지는 메타데이터를 많이 가지고 있는데, 이를 제거하여 크기를 줄일 수 있음
- tinypng

 

TinyPNG – Compress PNG images while preserving transparency

Make your website faster and save bandwidth. TinyPNG optimizes your PNG images by 50-80% while preserving full transparency!

tinypng.com

 

적절한 이미지 포맷 사용

- 이미지는 jpg, png, gif, bmp 등의 다양한 포맷을 사용

- 각 브라우저에 특화된 이미지를 사용
- WebP : 손실 압축, 구글 개발, 이미지 전달 용도로 많이 사용하던 jpeg를 대체하기 위해 웹 사이트 트래픽 감소, 로딩 속도 단축을 목적으로 개발
- JPEG XR : 마이크로소프트
- 크롬에는 WebP, IE에는 JPEG XR제공 / JPEG만 들고 있다가 요청 브라우저에 따라 각각으로 변환하여 전달

- PNG는 알파채널로 투명 기능을 사용하는데, 투명 기능이 필요 없으면 사이즈가 작은 JPEG를 사용

 

래스터 이미지 vs 벡터 이미지

- 레스터 이미지는 사각형 필셀에 색상 데이터를 입력해서 표현, 큰 사이즈와 고품질 이미지를 위해서는 그만큼 픽셀을 추가해야 하므로, 용량이 커짐

- 벡터 이미지는 수학적인 메타 정보를 가지고 있어서 화면 스케일에 관계없이 항상 선명한 이미지를 제공, 이미지의 그림이 복잡해지면, 이를 위한 정보가 계속 늘어나게 됨, SVG는 텍스트 기반이라 svgz로 만들어서 사용 가능

 

무손실 압축 vs 손실압축

- 무손실 압축은 각 이미지 유형들을 서로 다르게 처리해야 함, 대부분 라이브러리 스크립트로 압축 자동화가 가능

- GIF : ImageMagicK, Giflossy, Gifsicle, gif2webp converter

- PNG : PNG는 청크 형태로 저장, 이미지 표현 정보인 핵심 청크가 아닌 정보성 청크는 삭제해도 됨(Pngcrush, Pngquant, PngOptimizer)

- JPEG : 이미지 외에 많은 메타 데이터가 있음(주석, 공백, 편집 앱 정보, 카메라 정보, 촬영 날짜/위치 등) 제거해도 이미지 품질 손실 없음(MozJPEG, libJpeg, Guetzli)

 

- 손실 압축은 이미지의 정보를 누락, 사용자의 시각적 경험을 손실시키지 않으면서 이미지를 손실시키면 됨

- 사람이 품질 저하를 모르게 하면서 파일 크기를 줄일 수 있는 JPEG품질은 100~75% => 85~80% 권장(시각적 손실이 거의 없고, 사이즈는 70% 이하로 축소 가능)

 

반응형 웹과 이미지

문제점 : (아직) 필요하지 않은 리소스들도 과도하게 다운로드

- 반응형 웹에서는 이미지를 내려받아서 화면의 사이즈에 맞게 줄이는 유동형 이미지 방법을 사용, 이 방법에서 화면상의 이미지가 작아졌다고 실제 이미지의 크기가 작아진 것은 아니고, 브라우저에서 큰 이미지를 받아다가 축소하는 처리하는 추가 과정이 이루어지게 되는 낭비가 발생함

- PC와 모바일에서는 같은 화면이어도 화면에 나타나는 이미지의 개수가 다름(PC가 훨씬 많음), 모바일 화면을 구성하기 위해 미디어 쿼리에 display: none;을 줘서 숨기는데, 이렇다고 해서 이미지를 다운로드하지 않는 것은 아님

- 모바일 화면을 볼 때 아직 스크롤을 내려서 확인하지 않은 화면에 있는 이미지들도 전부 다운로드

 

해결방법 : 사용자의 환경에 따라 그 환경에 적합한 이미지를 제공

- 사용자의 화면 크기에 따라 여러 가지 사이즈(버전)의 이미지를 준비해서 알맞게 전송

- FE : 미디어 쿼리로 사용자의 환경을 파악하고 그 환경에 맞는 이미지를 호출, 과도하게 사용하는 경우 FE코드가 무거워짐

- BE : 서버에서 사용자의 환경에 맞는 이미지를 전송, 서버에서 사용자의 환경을 파악하기 위한 작업이 필요함, Client Hint

- Client Hint : 사용자의 환경은 서버에 전달하기 위함, HTTP 헤더에 넣어서 전송

- 지연 로딩 : 당장 화면에 보여주지 않은 리소스를 처음부터 전부 다운로드하는 것은 낭비임, 실제로 필요하거나 스크롤을 내려서 화면이 움직일 때 이미지를 다운받음(lazyload라이브러리)

- 모바일 우선 접근 : 웹을 구현할 때 모바일 화면부터 개발, PC 화면부터 구성하면 모바일 화면을 구성할 때 PC에서 사용한 것들을 모바일에 그대로 사용하는 일이 많음

 

큰 파일은 작게 나누어서 전송

- 크기를 알 수 없거나 대용량 파일의 일부분을 순서대로 다운로드하는 부분 요청 응답 방식
- Range
- Content-Range
- 클라이언트는 구간별로 부분 파일 요청을 반복해서, 콘텐츠가 끊김 없이 서비스될 수 있도록 함

ex.
Range: bytes=0~1023
Content-Range: bytes 0~1023 / 10000 => 전체 10000중에서 1001~2000만 전송
Content-Length: 1024

 

브라우저 렌더링 최적화

- DOM최적화 : 웹 페이지에 구문 오류가 많을수록 예외 처리를 위한 메모리, CPU를 소모하므로, 구문 오류 최소화하기, 과도하게 HTML 태그를 중첩시키지 않기 (15단계 넘지 않도록)
- JS와 CSS배치 : HTML구문분석은 JS를 만나면 JS를 처리할 때까지 DOM생성 작업 중단, JS는 CSSOM생성이 완료될 때까지 JS처리 중단 => JS와 CSS는 랜더링을 지연할 수 있는 요소 => CSS는 최대한 위쪽에 두어서 CSSOM을 빠르게 만들도록, JS는 최대한 하단에 두어서 DOM, CSSOM생성 완료 후에 JS 수행되도록
- JS최적화 : 타사 솔루션 JS를 배치하는 경우도 있어서 하단에 배치하기 어려운 경우도 많음, 꼭 필요한 JS그룹과 그렇지 않은 JS그룹을 구분해서 후자는 async, defer적용
(async : DOM생성과 동시에 JS처리 / defer : DOM생성 중 별도 스레드로 JS 다운로드한 후, 처리는 DOM생성 완료 후에)
- CSS최적화 : 모든 CSS가 첫 화면 구성에 쓰이지는 않음, CSS를 적절히 분리해서 필요한 페이지에 필요한 CSS만 적용
- 이미지 로딩 최적화 : background-image, 지연 로딩, Progressive JPG

 

도메인 분할

- 여러 도메인을 소유한 경우 웹 콘텐츠를 병렬적으로 동시에 다운로드
- 브라우저 만다 허용하는 최대 동시 연결 개수를 제한함 (대부분 6개)
- 사이트 전체의 쿠키 사이즈를 줄일 수 있음
- 각 도메인은 동일한 인증서를 사용해야 함, 인증서가 다르면 추가적인 TLS협상 과정이 생겨버림
- 적절한 도에인 숫자를 결정해야 함, 너무 많으면 도리어 CPU 과부하

 

캐시 최적화

HTTP캐시 목적
1) 원본 서버로의 요청 수를 최소화, 네트워크 왕복 수를 줄여서 사용자에 대한 응답 속도를 단축
2) 완전한 콘텐츠를 응답하지 않아도 됨, 네트워크 대역폭과 리소스 낭비를 줄임

- 캐시 저장소에 접근하는 시간이 원래 데이터 위치에 접근하는 시간보다 짧고, 시스템의 리소스를 아낄 수 있음
- 프록시 서버 : 인터넷상에서 주고받은 데이터를 캐시 하고 다음에 요청하는 사용자에게 이를 제공하는 방식을 사용하여, 사용자들은 좀 더 빠르게 콘텐츠를 받을 수 있음
- PUSH : 미리 캐시 서버에 데이터를 복사해둠 / PULL : 실제 요청이 있을 때 캐시에 저장
- 웹 브라우저에서도 이미지나, 자바스크립트, CSS파일 등을 사용자의 브라우저가 캐시 해서 저장함
- 브라우저 캐시에 대한 내용은 웹서버의 캐시 설정을 따름 => 참고
- Cache-Control 응답 헤더로 클라이언트에 캐시 설정 정보를 알려줌 (유효시간)
- Expire는 만료 시점, Expire는 Date헤더를 함께 보내야 함, Date헤더에는 요청에 대한 응답이 작성된 시점을 표시
- Cache-Control, Expire둘다 있으면 Cache-Control를 우선 사용

Cache-Control: max-age=3600 => 브라우저 캐시 저장 후 3600초 동안 유효
Cache-Control: no-store => 캐시 하면 안 되는 콘텐츠
Cache-Control: no-cache => 원본 서버의 콘텐츠 갱신 여부를 확인하고 변경이 없는 경우만 캐시 된 콘텐츠 사용
Cache-Control: no-cache, no-store, must-revalidate : 캐시 절대 불가능
Expire: Mon, 30 Nov 2021 08:00:00 GMT => 2021년 11월 30일 08시에 만료

- 콘텐츠에 따라 캐싱을 어떻게 할 것인지 판단해야 함

- 동일한 파일을 서버의 여러 곳에 분산시키면 안 됨, 캐시 서버는 URL을 키로 하여 동작하기 때문에, 동일한 내용이 캐시에도 또 생김
- 캐시 오염 제거 : 원본은 한 개인데, 캐시에는 많음 => 쿼리 스트링 값이 달라도 응답이 매번 같다면, 캐시 키는 쿼리 스트링을 무시하도록, 쿼리 스트링의 순서를 동일하게

 

- 캐시 서버는 캐시 키를 사용

- 캐시 서버가 원본의 복사본을 저장하고 빠르게 조회하기 위해서 사용하는 키 값

- 일반적인 웹 캐시는 클라이언트가 요청하는  URL을 캐시 키로 사용함 (호스트/패스?쿼리스트링)

- 캐시 방지를 위해서 'version=오늘날짜' 와 같은 쿼리 스트링을 추가해서 요청할 수도 있음

 

EX) 아래 3개의 캐시 키는 서로 다른 객체를 참조함

www.abc.com/ui/css/common.css

www.abc.com/ui/css/common.css?vesion=20210721

www.abc.com/ui/css/common.css?vesion=20210722

CDN

- CDN은 웹 콘텐츠를 사용자에 세 빠르게 전달하기 위해 캐시 서버나 에지 서버와 같은 대용량 인터넷 캐시 영역에 콘텐츠들을 저장해서 사용하는 방식
- 클라이언트와 서버 사이에 발생 가능한 네트워크 지연이나 패킷 손실이 줄어듦
- 사용자는 비교적 가까운 에지 서버에서 콘텐츠를 받기 때문에 RTT가 줄어들어 빠르게 받을 수 있음
- CDN 서버가 콘텐츠를 전달해 주므로, 원본 서버의 부하를 덜어 줄 수 있음
- 캐시 사용률이 높아짐
- 서버 유지보수 용이