2020. 11. 21. 00:14ㆍ네트워크/HTTP
웹 캐시
캐시는 데이터나 값을 미리 복사해 놓은 저장소를 말한다. 값을 미리 복사해놓기 때문에 원본 데이터에 접근하는 시간과 재 계산 시간을 줄일 수 있다. 일상적인 예시로 냉장고에 사과가 있으면 언제든지 먹고 싶을 때마다 사과를 꺼내먹을 수 있다. 하지만 냉장고에 사과가 없다면 사과를 직접 사서 먹어야한다.
[그림 1]은 냉장고에 사과가 미리 저장되어 있는지 없는지에 따른 시간적 차이를 나타낸다. 사과를 직접 먹을 때까지 시간이 얼마나 걸리는지 적히지 않았지만, 우리는 냉장고에 미리 저장되어 있는 사과를 직접 꺼내서 먹는 시간이, 슈퍼에서 사과를 사와서 먹는 시간보다 더 빠르다는 것을 유추할 수 있다.
따라서 위 예시는 캐시의 존재가 데이터, 자원 접근 측면에 효율성을 높일 수 있다는 것을 보여주고 있다. 그렇다면 캐시는 어떻게 동작하길래 데이터 접근 측면에서 효율성을 높일 수 있는 걸까? 이 과정을 알기 위해 일반적으로 웹 클라이언트(브라우저)가 웹 서버로부터 자원을 어떻게 받는지를 알아야한다. 메커니즘은 다음과 같다.
-
브라우저(웹 클라이언트)가 서버로 자원을 요청한다.
-
서버는 브라우저에게 요청받은 자원을 제공한다.
간단한 과정이다. 하지만 이 과정은 중복에 취약하다. 즉, 내가 네이버 메인 사이트를 60번 들어간다고 가정한다면 [그림 2]를 구성하고 있는 하이퍼 텍스트(이미지, 글씨, 링크 등을 포함한 모든 구성요소)를 가져오는 과정을 60번을 반복해야한다.
일정 시간 텀으로 네이버 메인에 접속한다면, 로딩 에러는 덜 하겠지만, 짧은 시간안에 60번의 접속을 시도한다면 엄청난 로딩시간이 걸릴 것이다. 이러한 비 효율성을 줄이기 위해 브라우저는 서버로 자원을 요청하기 전에 브라우저 캐시를 탐색한다. 탐색 과정에서 찾으려는 데이터가 캐시 내에 있을 경우, 브라우저는 서버에 데이터를 요청하지 않고, 캐시 데이터를 사용한다. 즉, 아까 예시처럼, 냉장고에 사과가 있기 때문에 슈퍼마켓에서 사올 필요 없이 사과를 먹으면 된다는 것이다.
브라우저 캐시를 이용해서 중복 데이터를 가져오는 비 효율적인 과정을 없앴지만, 이 방법은 데이터가 업데이트 됐을 경우를 간과한다. 즉, 요청할 데이터가 브라우저 캐시 내에 있긴 하지만, 그 데이터가 구형 데이터인 경우를 말한다. 이 경우, 서버로부터 최신 데이터를 받아와야 하지만, 위 메커니즘([그림 3])은 브라우저 캐시 내에 똑같은 데이터가 있기 때문에 서버로부터 최신 데이터를 요청할 수가 없다. 이 상황을 해결하기 위해, 서버는 요청한 자원을 클라이언트로 응답할 때 만료시간을 같이 보내는 방법을 이용했다.
[그림 4]는 만료시간을 도입한 메커니즘을 나타낸다. 과정을 정리하면 다음과 같다.
-
브라우저가 서버로 자원을 요청한다.
-
서버는 브라우저에게 요청한 자원을 만료시간(60초)와 함께 응답한다.
-
브라우저 캐시 내에 만료시간을 포함한 요청 자원이 저장된다.
-
60초(만료 시간) 후에 브라우저 캐시 내에 있는 데이터가 없어지고, 서버로부터 최신 데이터를 요청한다.
[그림 4]의 메커니즘을 이용하여 최신 데이터를 업데이트할 수 있게 됐지만, 이 과정은 60초(만료시간)마다 데이터를 계속해서 서버로부터 받아와야한다는 비효율적인 예외를 야기한다. 즉, 받아온 자원이 업데이트된 자원이라면 목적에 부합하지만, 동일한 데이터라면 불 필요하게 같은 자원을 없애고 같은 자원을 서버로부터 받아와야한다. 이를 해결하기 위해 서버는 만료시간과 함께 Etag를 클라이언트로 보낸다. Etag를 추가한 메커니즘 동작은 다음과 같다.
- 웹 브라우저는 서버에게 사과라는 데이터를 요청한다.
- 웹 서버는 브라우저에게 사과라는 데이터, 사과의 해시 값(해싱 함수에 의해 변환)을 가지는 Etag, 만료시간 60초라는 속성이 담긴 객체 데이터를 보낸다.
- 60초 후, 웹 브라우저는 업데이트를 위해 헤더의 If-non-match 속성에 Etag 값을 넣어 서버로 요청 객체를 보낸다.
- 서버는 If-non-match의 값과 현재 자신이 가지고 있는 Etag값을 비교한다.
- 값이 같을 경우, 서버는 웹 브라우저에게 상태코드 304(변화된게 없다라는 뜻)을 보낸다[값이 같을 경우].
- 웹 브라우저는 상태코드를 확인한 후 캐시 값을 유지한다[값이 같을 경우].
- 하지만, 값이 다를 경우, 서버는 상태 코드 200과 함께 업데이트 된 객체 데이터(Etag: Tomato(업데이트 된 etag, Data: 토마토)를 웹 브라우저로 보낸다[값이 다를 경우].
- 웹 브라우저는 상태코드를 확인한 후 브라우저 캐시를 업데이트한다[값이 다를 경우].
따라서 Etag와 만료시간을 이용하면 효율적으로 자원을 업데이트할 수 있다. 하지만 이 방법이 효율적이기 위해서는 브라우저 캐시 내 자원이 만료되야한다는 조건이 성립해야한다. 즉 자원이 만료되지 않는다면, 업데이트를 할 수 없다.
CSS같은 정적 파일은 업데이트 횟수가 적기 때문에 만료 시간을 길게 잡는다. 만약 CSS 파일의 만료시간을 7일로 가정하면, 네이버 메인을 구성하고 있는 CSS 파일은 일주일 간 업데이트 되지 않는다. 그러면 문제가 발생하게 된다.
사용자 A, B가 있다. 그들은 자신이 가지고 있는 데스크탑으로 네이버에 접속했다. 그런데 사용자 A는 11월 20일에 네이버에 접속했고, B는 11월 21일에 네이버에 접속했다. 11월 21일은 국가에서 지정한 공휴일이기 때문에, 네이버는 그 날이 공휴일이라는 것을 사용자들에게 알려주기 위해 로고 색을 빨간색으로 바꿨다. 그런데 문제가 발생했다. 11월 21일에 네이버에 접속한 B의 웹 브라우저는 로고 색이 업데이트 됐지만, 사용자 A의 웹 브라우저는 만료시간이 남았기 때문에 로고 색이 업데이트 되지 않았다. 이 문제는 만료시간, Etag를 이용하여 업데이트하는 방식의 한계점을 그대로 보여준다.
이 문제의 해결 법은 리소스(자원) URL을 변경하는 것이다. 즉, CSS 파일이 업데이트 되면 styles.css가 아닌 styles.1.css, styles.2.css와 같이 디지털 지문이나 버전 번호를 파일 이름에 포함하는 방식으로 바꾸어서 URL을 변경해주면 된다. 개인적인 생각으로 이 방법은 styles.[버전번호 규칙].css와 같은 정규 표현식을 이용한 URL을 이용하는 것 같다. 그러면 일일히 URL을 변경하는 불편함을 거치지 않기 때문이다.
참고자료
'네트워크 > HTTP' 카테고리의 다른 글
영속적 연결과 비 영속적 연결 (0) | 2020.10.31 |
---|---|
하이퍼 텍스트 프로토콜(HTTP)이란? (0) | 2020.10.30 |