안녕하세요! 프론트엔드 성능 최적화의 세계로 오신 것을 환영합니다! 🎉
우리가 열심히 만든 웹사이트가 사용자에게 0.1초라도 더 빨리 뜨게 만들려면 '압축'은 선택이 아닌 필수랍니다. MDN 공식 문서를 통해 HTTP에서 압축이 어떻게 이루어지는지 하나씩 친절하게, 제 실무 꿀팁과 함께 설명해 드릴게요. 자, 시작해 볼까요?
압축(Compression)은 웹사이트의 성능을 높이는 정말 중요한 방법이에요. 파일의 크기를 최대 70%까지 줄여서 우리가 사용하는 대역폭(네트워크 용량)의 부담을 확 낮춰주거든요. 수년에 걸쳐 압축 알고리즘은 점점 더 효율적으로 발전해 왔고, 이제는 클라이언트(브라우저)와 서버 모두 새로운 알고리즘들을 든든하게 지원하고 있습니다.
사실 프론트엔드 개발자가 직접 복잡한 압축 알고리즘 메커니즘을 짤 필요는 없어요. 브라우저와 서버 안에 이미 똑똑하게 다 구현되어 있으니까요. 하지만, 우리 서버가 압축을 잘 하도록 설정되어 있는지 확인하는 것은 프론트엔드 개발자의 중요한 역할 중 하나입니다!
HTTP 통신에서 압축은 크게 세 가지 레벨에서 일어납니다:
1. 문서나 미디어 자체의 파일 포맷이 최적화된 방법으로 압축되는 경우
2. HTTP 레벨에서 일어나는 일반적인 압축 (엔드투엔드 압축) - 리소스가 처음부터 끝까지 압축된 상태로 전송됨
3. HTTP 커넥션의 두 노드 사이에서 일어나는 커넥션 레벨 압축 (홉-바이-홉 압축)
💡 강사의 실무 TIP!
"왜 내 사이트는 로딩이 느리지?" 할 때 가장 먼저 체크해야 할 것이 바로 이 텍스트 파일(HTML, CSS, JS)들의 압축 여부입니다. 압축만 켜져 있어도 초기 로딩 속도(FCP, LCP 등)가 드라마틱하게 개선된답니다!
모든 데이터 타입에는 어느 정도의 중복성, 즉 낭비되는 공간이 존재합니다. 일반 텍스트 파일이 대략 60% 정도의 중복성을 가진다면, 오디오나 비디오 같은 미디어 파일은 이 비율이 훨씬 높아요. 텍스트와 다르게 이런 미디어 파일들은 데이터를 저장하는 데 엄청난 공간을 차지하기 때문에, 엔지니어들은 아주 오래전부터 이런 특정 목적에 맞게 최적화된 파일 전용 압축 알고리즘을 만들어냈습니다.
파일에 사용되는 압축 알고리즘은 크게 두 가지 범주로 나눌 수 있어요:
gif나 png가 무손실 압축을 사용해요.jpeg 이미지 포맷 역시 손실 압축입니다.webp 포맷처럼 무손실과 손실 압축을 모두 지원하는 녀석들도 있어요. 보통 손실 알고리즘은 압축률을 조절할 수 있는데, 압축을 빡세게 할수록 용량은 줄어들지만 퀄리티는 떨어지게 되죠.
웹사이트 성능을 최고로 끌어올리려면, 사용자가 보기에 괜찮은 퀄리티를 유지하는 선에서 무자비하게 최대한 압축하는 것이 이상적입니다! 디자인 툴에서 뽑아낸 이미지가 웹용으로 완벽히 최적화되어있지 않을 수 있기 때문에, 이미지 압축 전용 도구들을 써서 한 번 더 꽉꽉 눌러 담는 것을 추천합니다.
당연히 손실 압축 알고리즘이 무손실 압축보다 훨씬 더 효율적으로 용량을 줄여줍니다.
🚨 강사의 주의사항 (매우 중요!)
이미 압축된 파일 포맷(jpeg,png,mp4등)을 HTTP 레벨에서 또 압축하려고 시도하지 마세요! 압축 알고리즘은 작동할 때 '딕셔너리(사전)'라는 걸 추가로 끼워 넣기 때문에, 이미 꽉꽉 눌러진 파일을 또 압축하려고 하면 오히려 파일 용량이 원본보다 더 커지는(오버헤드) 대참사가 발생할 수 있습니다. 이미지는 이미지대로, HTTP 압축은 텍스트(HTML/JS/CSS)에만 양보하세요!
웹사이트 성능을 획기적으로 향상시키는 진짜 주인공, 바로 엔드투엔드(End-to-end, 종단 간) 압축입니다.
이 방식은 서버가 메시지의 본문(Body)을 압축해서 보내면, 중간에 어떤 프록시나 노드를 거치든 아무도 그 본문을 건드리지 않고 클라이언트(브라우저)까지 그대로 안전하게 배달되는 것을 말해요.
모든 최신 브라우저와 서버는 이 엔드투엔드 압축을 지원합니다. 둘 사이에 서로 "우리 어떤 압축 방식 쓸까?" 하고 협상만 하면 되죠. 여기서 쓰이는 알고리즘들은 텍스트를 압축하는 데 아주 특화되어 있어요.
1990년대부터 수많은 압축 알고리즘들이 쏟아져 나왔지만, 오늘날 실무에서 살아남은 건 딱 두 가지뿐입니다. 가장 대중적인 gzip, 그리고 압축계의 강력한 신흥 강자 br (Brotli, 브로틀리) 입니다!
사용할 알고리즘을 결정하기 위해 브라우저와 서버는 사전 콘텐츠 협상(proactive content negotiation)이라는 과정을 거칩니다.
1. 브라우저가 먼저 서버에 요청을 보낼 때, Accept-Encoding 헤더에 "나 gzip이랑 br 풀 수 있어! 순위는 이거야!"라고 적어서 보냅니다.
2. 서버는 그걸 보고 하나를 고른 뒤, 메시지 본문을 꾹꾹 압축합니다.
3. 그리고 응답할 때 Content-Encoding 헤더에 "내가 br(브로틀리)로 압축해서 보냈어!"라고 적어서 줍니다.
4. 이때 서버는 캐시 서버들이 헷갈리지 않게 Vary: Accept-Encoding 헤더를 같이 보내줍니다. "이 파일은 압축 방식에 따라 다르게 캐싱해야 해!"라고 알려주는 거죠.
텍스트 기반 파일(HTML, CSS, JavaScript)은 이 압축을 활성화하면 성능이 눈에 띄게 좋아지므로 무조건 켜두는 것을 강력히 권장합니다. (단, 앞서 말했듯 이미 압축된 이미지, 오디오, 비디오 파일은 제외하고요!)
서버 단에서 설정하는 법도 간단해요. Apache는 mod_deflate를, Nginx는 ngx_http_gzip_module을, IIS는 <httpCompression> 요소를 사용하면 됩니다.
💡 강사의 실무 TIP!
요즘 웬만한 CDN(Cloudflare, AWS CloudFront 등)은 클릭 한 번으로Brotli압축을 켜고 끌 수 있게 되어있어요.Brotli는 구글이 만든 알고리즘인데, 기존gzip보다 압축률이 15~20%가량 더 좋아서 무조건 활성화해 두시는 걸 추천합니다!
Brotli나 Zstandard (zstd) 같은 현대적인 압축 포맷들은 자주 쓰이는 데이터들의 모음집인 '딕셔너리(Dictionary)'를 사용해서 압축률을 미친 듯이 끌어올립니다. 기본적으로는 포맷 자체에 내장된 정적 딕셔너리(예: Brotli 소스 코드에 있는 정적 사전)를 사용하게 되죠.
하지만 최근 떠오르는 압축 딕셔너리 전송 (Compression Dictionary Transport) 기술을 사용하면, 개발자가 앞으로의 요청을 위해 사용할 딕셔너리 리소스를 직접 커스텀해서 지정할 수 있습니다!
특정 딕셔너리 파일을 따로 만들 수도 있고, 심지어 이미 존재하는 리소스를 딕셔너리처럼 재활용할 수도 있어요. (예를 들어, 새로 배포된 app.v2.js를 다운받을 때, 유저의 브라우저에 이미 다운로드되어 있는 app.v1.js를 딕셔너리로 사용하는 겁니다!)
이렇게 하면 압축률이 폭발적으로 좋아져서 로딩 시간이 엄청나게 단축됩니다. 방금 든 예시처럼 두 버전 간의 차이점(Delta)만 다운로드하면 되고, 공통적인 부분은 이미 가지고 있는 app.v1.js에서 참조해서 조립하면 되니까요.
홉-바이-홉 압축은 방금 배운 엔드투엔드 압축과 비슷해 보이지만, 아주 근본적인 차이가 하나 있습니다.
엔드투엔드 압축이 서버에서 한 번 압축해서 클라이언트까지 쭉~ 보내는 방식이라면, 홉-바이-홉 압축은 클라이언트와 서버 사이를 거쳐가는 개별 노드(프록시 등)들 사이에서 각각 다르게 일어나는 압축을 말합니다. A 노드와 B 노드가 연결될 땐 gzip을 쓰고, B 노드와 C 노드가 연결될 땐 또 다른 압축을 쓸 수 있다는 얘기죠.
이 방식을 쓰기 위해 HTTP는 엔드투엔드의 콘텐츠 협상과 비슷한 메커니즘을 사용합니다. 요청을 전달하는 노드가 TE 헤더를 사용해 "나 이런 압축 지원해"라고 알리면, 다른 노드가 적절한 방식을 골라 압축을 적용한 뒤 Transfer-Encoding 헤더로 "나 이렇게 압축했어"라고 알려줍니다.
하지만 실무에서 이 홉-바이-홉 압축은 클라이언트와 서버 모르게 은밀하게(투명하게) 진행되며, 거의 사용되지 않는 방식입니다.
사실 TE와 Transfer-Encoding 헤더는 압축보다는 전체 파일 길이를 모를 때 데이터를 청크(Chunk, 조각) 단위로 나눠서 스트리밍하듯 보낼 때 훨씬 더 자주 쓰입니다.
실제로 이 홉-바이-홉 레벨의 압축은 너무 안 쓰이다 보니 Apache, Nginx, IIS 같은 웹 서버들조차 이를 쉽게 설정할 방법이 없어요. 굳이 설정한다면 프록시(Proxy) 서버 레벨에서나 가능하죠. 그러니 프론트엔드 개발자라면 "아, 이런 개념도 있구나!" 하고 쿨하게 넘어가셔도 좋습니다!
더 깊게 공부하고 싶은 열정적인 분들을 위해 MDN의 다른 문서를 추천해 드릴게요! (링크를 클릭하면 해당 문서로 이동합니다.)
이 페이지는 MDN 기여자들에 의해 2025년 7월 4일에 마지막으로 수정되었습니다.
오늘의 수업은 여기까지입니다! 이제 여러분은 브라우저의 Network 탭에서 Content-Encoding: gzip이나 br을 보게 되면 "아하! 우리 서버가 열일하고 있구나!" 하고 흐뭇하게 바라보실 수 있을 거예요.