상세 컨텐츠

본문 제목

CDN에서 웹 고속화 콘텐츠 압축의 설정과 주의점

프로그래밍/서버 네트워크

by 노을좋네 2020. 5. 18. 01:30

본문

웹 사이트를 고속화하고 오리진 서버의 부하도 줄일 목적으로 CDN을 도입하려는 케이스가 증가하고 있습니다. 웹 사이트의 고속화·오리진 서버의 부하 삭감을 할 수 있는 "CDN에서 실시하는 컨텐츠 압축"의 개요와 주의점에 대해 소개하겠습니다.

 

 

콘텐츠 압축이란?


콘텐츠 압축으로 유명한 것은 gzip에 의한 압축입니다. gzip은 "RFC 1952에 기술되어 있는 파일 압축 프로그램 gzip에서 생성된 인코딩 포맷"을 말하며, PC나 MAC에서도 ZIP으로 만들어 파일을 제공할 수 있지만, 웹 세계에서도 같은 방식으로 콘텐츠의 크기를 줄일 수 있습니다.

 

압축의 사양

gzip 압축은 텍스트 콘텐츠 내에서 비슷한 문자열을 찾고 그 문자열을 대체함으로써 전체 콘텐츠 크기를 줄입니다. HTML이나 CSS, JS는 비슷한 문자열의 반복을 많이 포함하고 있기 때문에 보통 파일보다 gzip압축 효과가 높다고 할 수 있습니다.

 

웹 세계에서의 콘텐츠 압축

PC나 MAC에서는 파일을 압축할 경우 압축 형식에 대응한 모종의 소프트를 이용하고 있다고 생각합니다. 웹 세계에서는 이 소프트웨어로 전환되는 것이 브라우저(해동 전용)와 웹 서버(압축 전용)입니다. 웹 서버의 전단에 CDN을 둔 경우는 웹 서버 대신 CDN이 콘텐츠를 압축하게 됩니다.

 

콘텐츠 압축 방식의 종류

콘텐츠 압축으로 유명한 것은 gzip형식이지만, gzip이외에도 다양한 종류의 방식이 존재하며 압축률과 CPU비용이 각각 다릅니다.

gzip
알고리즘: LZ77, 허프먼 부호
포맷: Gnuzip

deflate
알고리즘: LZ77, 허프먼부호
포맷: zlib

bzip2
특징: deflate나 gzip보다 압축률이 높지만 비표준
알고리즘: Burrows-Wheeler transform (BWT)
포맷: bzip2

brotli
특징: 구글이 개발한 알고리즘. deflate나 gzip보다 높은 압축률
알고리즘: LZ77, 해프먼 부호, 2ndorder context modeling
포맷: brotli

 

오리진 서버측에서의 압축대응 형식

주요 미들웨어는 콘텐츠 압축을 지원하고 있습니다. 여기에서는 자세히 언급하지 않지만 apache에 대해서는 mod_deflate에 의해 지원되며 nginx는 gzipon으로 설정함으로써 압축이 활성화됩니다. 예전에 일부 인기가 있었던 lighttpd는 특이하게 bzip2에도 대응하고 있습니다.

 

압축 대상이 되는 콘텐츠

Apache나 Nginx에서는 압축시킬 대상 콘텐츠를 설정할 수 있습니다. 때문에 어떠한 콘텐츠라도 지정하여 압축 설정이 가능하지만 그렇다고 해서 모든 콘텐츠를 압축해 버리는 것은 피해야 합니다.

 

서버측은 압축을 온더플라이로 실시할 경우 당연히 CPU 자원을 소비합니다. 그리고 사실 압축콘텐츠를 클라이언트 측에서 압축해동을 전개할 때에도 CPU 자원을 소비합니다. 서버 측에 대해서는 자원이 윤택한 케이스가 많기 때문에 그만큼 문제가 되지 않는다고 생각할 수 있지만, 클라이언트측은 어떠한 단말기로 접속하고 있는지 불명확하기 때문에 특히 스마트폰으로의 열람이 많은 사이트는 귀중한 스마트폰의 CPU 자원을 소비시켜 버릴 우려가 있습니다. 이것은 스마트 폰의 페이지 렌더링에 적지 않은 영향을 줄 수 있습니다.

그렇기 때문에 서버 측에도 클라이언트 측에도 부드러운 설계를 고려해야 하며 일반적으로는 비압축 파일인 HTML, CSS, 자바스크립트 등 압축효과가 높은 콘텐츠를 Mime Types의 압축대상으로 지정합니다. 그리고 반대로 압축해도 효과가 낮은 이미지나 동영상 같은 콘텐츠는 압축대상에서 생략해야 합니다.

 

 

압축 대응 형식을 통지하는 구조


CDN이나 서버 측에서 수행하는 압축형식에 클라이언트도 동일하게 대응하지 않으면 해동이 불가능합니다. 따라서 HTTP 헤더를 이용하여 클라이언트는 어떤 압축 형식의 파일을 해제할 수 있는지 서버에 알립니다.

Accept-Encoding으로 전달하기

클라이언트 측 브라우저가 HTTP 요청 내 Accept-Encoding 헤더를 이용해서 서버 측에 이런 압축된 형식의 파일을 압축해동할 수 있습니다 라고 알립니다. 복수 대응하고 있는 경우는 콤마 구분으로 기술됩니다.

 

Content-Encoding으로 답하기

서버 측은 전달받은 Accept-Encoding 헤더의 내용을 보고 자신이 압축 가능한 형식이 있는 경우 이러한 형식으로 압축했습니다 라는 정보를 HTTP 리스폰스 내의 Content-Encoding 헤더로 클라이언트 측에 알립니다.

이렇게 해서 먼저 클라이언트가 기점이 되어 대응한 형식을 통지하고 받은 서버 측에서 압축 형식을 지원하는 경우는 콘텐츠를 압축하고 동시에 압축 형식을 HTTP 헤더로 통지하는 방식으로 서로의 대응 형식을 판별하고 있습니다.

 

 

브라우저 지원상황


서버·CDN(압축하는 측)의 이야기를 했지만, 브라우저(해동하는 측)도 이러한 압축 형식에 대응하고 있지 않으면 아무런 의미가 없습니다. 그렇다고 해도 브라우저가 대응하고 있는 형식을 Accept-Encoding내에 격납해 요청 하기 때문에 의식해야 할 곳은 서버나 CDN의 압축하는 측이라고 할 수 있습니다.

 

Can I Use로 확인하면 모던 브라우저에서는 gzip압축을 지원한다는 것을 알 수 있습니다.

 

 

CDN으로 콘텐츠 압축


CDN서비스는 웹 서버처럼 콘텐츠 압축 기능이 표준으로 탑재되어 있는 케이스와 CDN에는 압축하지 않고 오리진 서버에 맡기는 두가지의 패턴이 있습니다. CDN측에서 콘텐츠 압축을 지원하고 있으면 오리진 서버측은 압축하는 CPU비용을 신경쓸 일이 없어지고 캐시할 수 없는 요청이 대량으로 왔을 경우에도 효력을 발휘하기 때문에 매우 유력하다고 할 수 있습니다.

 

 

CDN에서 콘텐츠 압축 시 전달 문제


CDN측에서 콘텐츠 압축을 어떻게 취급할 것인가 라는 것은 매우 중요합니다. 이것은 설정이나 부여하는 헤더를 잘못하면 아래와 같은 문제가 발생합니다. 여기에서는 각각의 패턴으로 압축 대응하고 있는 클라이언트와 그렇지 않은 클라이언트가 2개 있는 것을 전제로 합니다.

 

비압축 콘텐츠를 반환하고 리스폰스 저하

  1. 압축 비대응 클라이언트가 CDN에 액세스 합니다.
  2. CDN은 압축 비대응을 위해 오리진 서버에서 받은 비압축 파일을 CDN 내부에 캐시합니다.
  3. 압축 대응하고 있는 클라이언트가 CDN에 액세스 합니다.
  4. CDN은 이미 캐시가 완료된 비압축 파일을 클라이언트에 전송해 버립니다.

이 패턴은 압축 대응 클라이언트 측에 비압축인 큰 콘텐츠가 전달되는 것만으로 일반적으로 열람이 가능합니다. 하지만 다음과 같은 패턴은 더 비참해집니다.

 

클라이언트 측에서 인식오류

  1. 압축 대응하고 있는 클라이언트가 CDN에 액세스 합니다.
  2. CDN은 압축 대응으로 판단하여 오리진 서버에서 받은 비압축 파일을 압축하여 CDN 내부에 캐시합니다.
  3. 압축을 지원하지 않는 클라이언트가 CDN에 접속하면 CDN은 이미 있는 압축 완료 콘텐츠를 반환합니다.
  4. 클라이언트측은 압축된 콘텐츠를 해제할 수없어서 콘텐츠를 볼 수 없습니다.

이것은 이미 압축 완료된 콘텐츠를 캐시하고 있기 때문에 압축 비대응 클라이언트의 액세스는 모두 에러가 나 버립니다.

 

Vary 헤더로 문제 회피

이러한 두 가지 비참한 상황을 피하기 위해서는 몇 가지 방법이 있는데, 가장 간단한 방법은 오리진 서버에서 Vary 헤더를 리스폰스 하는 것입니다.

 

Vary 헤더의 개요

Vary 헤더는 CDN이 캐시 완료 여부를 판단하는 재료인 경로와 호스트 헤더 이외의 요청 헤더에서 어느 부분을 고려해야 하는지를 CDN에 전달할 수 있습니다. 압축 콘텐츠의 경우 Accept-Encoding이 지정되지만 기타 관련된 헤더의 이름을 여러 개 콤마 구분으로 리스트 지정이 가능합니다.

 

CDN에서 캐시 분리

이와 같이 CDN은 Vary 헤더에 의해서 같은 값의 Accept-Encoding을 보관 유지하고 있는 경우는 캐시를 이용하고, 그 외의 경우는 오리진 서버에 콘텐츠를 재취득하러 가게 됩니다. 따라서 비압축 캐시와 압축 완료 캐시 2개를 CDN이 유지하고 클라이언트에 맞춰 적절히 리스폰스 할 수 있습니다.

 

 

Vary 헤더의 덫을 회피하는 CDN의 정규화


Vary 헤더가 리스폰스 되면 CDN은 Vary 헤더의 내용별로 캐시를 유지하며 방금과 같은 문제를 회피합니다. 그러나 전세계의 브라우저나 앱에서는 Accept-Encoding의 내용만으로도 많은 종류나 기술 순서가 있기 때문에, 모든 종류별로 CDN이 캐시를 나누어 버리면 반대로 HIT율이 큰폭으로 저하하는 새로운 문제가 발생합니다.

 

 

정리


페이지의 읽기 속도를 향상시키기 위해 할 수 있는 대책은 자원 최적화와 합계 다운로드 크기를 최소화하는 것입니다.

그 때문에 CDN측의 콘텐츠 압축에 의해 전송량 삭감과 렌더링 스피드를 향상시키는 것은 머스트라고 해도 과언이 아닙니다. 그러나 그렇다고 압축·해동 비용을 무시하거나, CDN을 통한 경우의 문제를 경시하면 역효과가 납니다. 적절한 콘텐츠만 압축하여 CDN이나 프록시를 고려하기 위한 Vary 헤더로 문제를 회피할 필요가 있습니다.

관련글 더보기

댓글 영역