본문 바로가기

SSAFY/SSAFYcial

프론트엔드 개발자가 알아야 할 캐싱(caching) 개념 정리

 

 

 프론트엔드 개발 경험이 쌓이다 보면 웹사이트 성능을 최적화하는 것에 관심이 자연스레 생기게 됩니다. 처음에는 그저눈에 보기 좋은 사이트를 개발하는 것(보다 제대로 동작하는 기능을 개발하는 게 먼저였지만)에 이끌려 프론트엔드에 본격적인 흥미를 얻다가 점차 웹사이트의 로딩 시간을 줄이고, 어색하거나 불편하지 않은 웹사이트를 개발하려다가 '웹 최적화'가 중요하다는 것을 느끼게 됩니다.

 

내가 만든 사이트는 언제쯤 light house 폭죽을 터뜨릴 수 있을까?

 

오늘은 웹을 최적화하는 방법 중 하나인 캐시(cache)에 대해 기본적인 개념을 정리해보려고 합니다.

 

1. 캐시가 뭐야? 캐시 기본 개념 정리

캐시(Cache)는 어떤 웹사이트나 서비스에서 데이터를 받아 온 이후 그 데이터를 원래 불러왔던 데이터 저장소보다 클라이언트(유저)에게 가까운 곳에 임시로 저장해 필요시(예를 들어 웹 사이트 재방문 등) 더 빠르게 불러와서 사용하기 위한 목적으로 저장하는 데이터를 의미합니다. 캐시를 불러오고 저장하는 프로세스를 캐싱(Caching)이라고 합니다. 

 

 

'오 그럼 캐싱을 많이 할 수록 좋은거네요?' 라고 생각할 수 있지만 사실은 그렇지 않습니다. 자세히 설명하기에는 복잡하니까 핵심만 설명하기 위해 간단히 컴퓨터의 메모리 저장에 대한 개념을 설명하자면 컴퓨터의 메모리 구조는 아래와 같습니다.

 

컴퓨터 메모리 계층구조(출처 = wikipedia)

 

복잡한 그림인데 간단히 설명하자면 컴퓨터에서 메모리에 저장된 데이터를 불러올 때 계층에 따라 불러오는 속도에 차이가 납니다. 위 사진에 따르면 메모리 계층 구조에서 캐시는 디스크나 메인 메모리보다 더 빠르게 데이터를 불러와서 사용해야 할 때 쓰이지만 단위 메모리당 저장 비용이 비쌉니다. 즉, 캐시는 빠르게 접근할 수 있도록 도와주지만 그만큼 저장할 공간이 적기 때문에 좋은 개발자가 되기 위해서 '재사용성'이 충분한 데이터만 선별적으로 캐싱해서 성능과 비용을 모두 아끼는 것이 필요합니다.

 


2. 웹 캐시(Web Cache)

어떤 웹 사이트에 접근하는 주체를 멋있는 말로 '클라이언트(Client)'라고 합니다. 클라이언트가 특정 웹 사이트에 접근할 때 서버로부터 HTTP 요청을 통해 필요한 데이터(HTML, CSS, JS, 이미지 등)를 불러옵니다. 기본적으로는 웹 사이트에서 무언가 실행될 때마다 클라이언트는 해당 웹 사이트를 그리기 위해 필요한 데이터를 전부 불러와야 합니다.

 

 

예를 들어 유튜브 인기 급상승 페이지에 접속한다고 가정해봅시다. 위 화면을 크게 두 부분으로 나눌 수 있습니다. 어떤 클라이언트가 유튜브의 어떤 피드를 접속하더라도 왼쪽의 메뉴바, 상단 네비게이션 바는 공통으로 나타납니다. 

 

유튜브 영화 탭의 화면

 

그렇다면 공통된 부분인 메뉴 바, 상단 네비게이션 바는 클라이언트가 어떤 페이지로 이동하더라도 공통적으로 있을텐데 매번 서버로부터 불러오는 게 최선의 방법일까요? 같은 부분이라면 클라이언트가 매번 불러올 필요 없이 어딘가에 저장해놓고 다양한 콘텐츠가 있는 영상 부분만 불러오면 더 효율적일 것 같네요!

 


3. 브라우저 캐시(Browser Cache)

이전에 한 번 불러왔고, 거의 바뀌지 않는 데이터라면(위 유튜브의 예시에서 좌측 메뉴 바 같은 것) 캐싱을 적용해 볼 수 있습니다. 여기에 적용하는 캐시를 브라우저 캐시(Browser Cache)라고 합니다. 브라우저 캐시는 브라우저나 HTTP요청을 하는 클라이언트 애플리케이션에 의해 내부 디스크에 이루어지는 캐시이며 HTTP 캐시라고 불리기도 합니다.

 

이럽 캐시는 단일 사용자를 대상으로 하는 사적 캐시(Private Cache)이며 해당 사용자의 정보만을 저장합니다. 브라우저에서 캐싱을 처리하는 속성은 여러 가지가 있는데 대표적으로 ETag, Cache-Control이 있습니다.

 

대표적인 브라우저 캐싱 속성: ETag, Cache-Control

(1) ETag

HTTP 헤더의 ETag는 특정 버전의 리소스를 식별합니다. 특정 버전의 리소스를 식별한다는 게 무슨 말일까요? 클라이언트가 어떤 사이트를 최초로 방문할 때 사이트를 보기 위한 모든 파일(HTML, CSS, JS 등)을 받게 되는데 그때 ETag도 포함되어 받게 됩니다. 그리고 재방문 시 웹 서버에서 ETag 내용을 확인하고 서버의 ETag와 동일하다면 웹 서버에 전체 요청을 보내지 않아 효율적으로 캐시를 관리할 수 있습니다.

 

만약 해당 요청의 리소스가 변경되었다면 새로운 ETag가 생성되고, 요구사항에 따라 서버에서 ETag가 무기한으로 지속되게끔 설정하는 것도 가능합니다. 

 

(2) Cache-Control

서버에 HTTP 요청을 보낼지 말지 여부를 판단할 때 HTTP 헤더의 Cache-Control 이라는 요소를 통해 캐싱을 제어할 수 있습니다. Cache-Control에 'no-cache'라는 속성이 있는데 이건 캐시를 쓰지 않는다는 뜻이 아닙니다. 캐시를 먼저 사용하기 이전에 서버에 해당 캐시를 사용해도 되는지에 관해 검증 요청을 보내는 속성입니다. no-cache 속성이 없는 경우 캐시가 있다면 바로 캐시를 쓰지만 no-cahe 속성이 있다면 캐시를 바로 쓰지 않고 클라이언트가 가지고 있는 캐시를 써도 되는지 서버에 허락을 맡고 사용하기 때문에 서버와 통신을 하는 시간이 소요될 수 있습니다. 


4. 프록시 캐시(Proxy Cache)

프록시 캐시란 이런 겁니다. (출처 = freeCodeCamp)

웹 캐시에는 브라우저 캐시뿐만 아니라 다른 캐시도 존재합니다. 대표적으로 프록시 캐시(Proxy Cache)가 있습니다. 프록시 캐시는 공유 캐시(Shared Cache)로 한 명 이상의 사용자에 의해 재사용되는 응답을 저장합니다. 대표적으로 ISP(Internet Service Provider)에서 많이 조회되는 리소스를 재사용하기 위해 웹 프록시를 설치했을 수 있습니다. 

 

무슨 말인지 쉽게 감이 오지 않을 수 있어서 예를 들어 설명을 해드리겠습니다. 예를 들어 우리가 유튜브에 접속할 때 매 접속 시마다 미국에 있는 유튜브 서버에서 웹 사이트 데이터를 불러온다면 상당한 시간이 걸릴 것 같습니다. 그런 방식이라면 전 세계 사람들이 사용하는 유튜브는 실시간 사용자만 해도 수 억 명 단위일테니까요. 그렇다면 이 방법을 해결하기 위해 프록시 캐시를 사용하면 유튜브 사이트 리소스를 한국 서버에 둘 수 있을 거니까 한국에서 유튜브로 보내는 요청은 한국 프록시 서버에서 처리할 수 있으니까 더 빠른 응답을 기대할 수 있습니다.

 


5. 네트워크 캐시

프록시 서버에서 캐시를 관리할 수 있으면 된 거 아니냐고 생각할 수 있지만 현실은 그렇지 않습니다. 위에서 본 프록시 서버 그림은 현실세계를 단순하게 모델링한 그림이고, 실제로는 하나의 서버에 여러 개의 프록시 서버가 붙어있고 또 서비스 대상에 따라 지역이 여러 군데일 수도 있기 때문입니다.

 

위에서는 유튜브를 예로 들었지만 세상의 모든 회사가 유튜브처럼 전 세계에 프록시 서버를 둘 수는 없기 때문에 전 세계의 클라이언트에게 빠르게 콘텐츠를 제공하기 위해 나온 개념이 아래에서 살펴볼 CDN입니다.

 


6. CDN(Content Delivery Network)

CDN은 분산 노드로 구성된 네트워크 입니다. CDN은 성능 향상을 위해 클라이언트의 요청이 같은 서버로 가는 것을 막습니다. CDN은 각 지역의 엔드 유저에 따라 요청을 오리진 서버가 아닌 다른 서버로 가도록 분산시키는 역할을 합니다. 이 과정에서 캐싱이 사용됩니다.

 

CDN을 통해 전 세계 클라이언트의 요청을 분산 처리하는 예시(출처: Microsoft)

 

만약 엔드 유저의 요청이 CDN 노드에서 가져올 수 있다면 그 요청을 처리하지만 그렇지 않다면 오리진 서버로 요청을 전송합니다. 최초 접속 시에는 오리진 서버로부터 데이터를 받아와야 하므로 느릴 수 있지만 그 다음부터는 CDN을 통해 빠르게 해당 콘텐츠를 내려받을 수 있다는 장점이 있습니다.

 

이러한 CDN을 서비스하는 대표적인 회사로 Cloudflare가 있습니다. Cloudflare는 추가적인 캐싱 레이어를 설정할 수 있게 해서, 사용자가 이전에 사이트를 방문했다면 그 정보를 브라우저에서 캐싱할 수도 있습니다. 그래서 Cloudflare를 ‘CDN 캐시’ 서비스라고 부르기도 합니다. 

CDN과 캐시를 분리하여 생각하기는 어렵습니다. 실제로 Cloudflare는 엣지 캐시를 사용하고 있습니다. 엣지 캐시란 네트워크의 엣지에서 정적 에셋 파일(이미지, CSS, JS 등)을 캐싱해서 엔드 유저에게 빠르게 도달하고, 콘텐츠 전송 시 서버 로드를 줄여주는 역할을 합니다.


여기까지 프론트엔드 개발자가 알아야 할 캐싱 기본 개념에 대해 알아보았습니다. 위에서 다룬 각각의 내용을 깊이 있게 다루지 않았기도 하고 다루지 않은 캐싱 개념도 많습니다. 또한 데이터 캐싱과 관련해서 Fetching 라이브러리인 swr, react-query 등을 통해 캐싱을 어떻게 처리하는지 학습하고 사용해보는 것도 캐싱에 대한 개념 이해를 도와줄 수 있다고 생각합니다.

 

사실 캐싱은 아는 것에서 그치는 것이 아니라 끊임없이 개발자의 판단이 들어가야 하는 영역(성능과 비용 측면에서 최적의 해를 찾는 과정)이므로 자신이 처한 환경과 비즈니스에 맞춰 적절하게 활용할 수 있는 최적의 지점을 발견해 나가는 것이 중요하다고 생각합니다.

 

참고 자료

1. How to Improve Your Site's Ranking using Lighthouse Chrome Extension, https://dev.to/frontend_jedi/how-to-improve-your-sites-ranking-using-lighthouse-chrome-extension-20bo 

2. Browser Cache, https://www.imperva.com/learn/performance/browser-caching/

3. HTTP 캐싱, https://developer.mozilla.org/ko/docs/Web/HTTP/Caching