2 minute read

이 글은 백엔드 크루 테오가 작성했습니다.

문제 상황

하루스터디 팀은 2차 스프린트까지 계획했던 기능 구현을 모두 마치고 첫 공식 배포를 진행하고 있었습니다. 그러나 처음으로 프론트엔드 서버와 백엔드 서버가 API 통신을 하다보니 몇 가지 문제가 드러나기 시작했습니다.

최신화되지 않은 API 명세에 대해 오해한 부분이 있다거나, 서로 데이터 형식이 통일되지 않은 경우가 종종 있었는데요. 따라서 몇몇 수정 작업을 거쳤고, 이렇게 수정된 파일을 다시 한 번 배포했습니다.

하지만 배포된 코드 자체에는 분명 이상이 없었음에도 웹 브라우저에서 하루스터디의 웹페이지를 접속했을 때 수정되기 이전의 현상이 그대로 발생했었습니다.

저희 팀은 고된 디버깅 작업 끝에 캐싱 문제가 아닐까 예상했지만 완전히 확신하지는 못했기에 이번 아티클을 통해 무엇이 문제였는지, 그리고 어떻게 해결하는지를 정리하고자 합니다.

Cache-Control 헤더

캐싱 문제가 짐작된 후, 개발자 도구의 네트워크 탭을 통해 페이로드와 헤더 등을 분석했습니다. 그리고 다음과 같은 내용을 확인할 수 있었는데요.

바로 Cache-Control 헤더에 max-age 가 14400s로 설정되어 있다는 것입니다. HTTP 응답에 이 Cache-Control 헤더를 지정하면 웹 브라우저 캐싱을 관리할 수 있습니다.

웹 브라우저 캐싱이란 웹 캐싱 기법 중의 하나로 리소스를 로컬 디스크에 캐싱하는 방식을 의미합니다.

사진 상에서는 Cache-Control 헤더에 max-age=14400 이라고 명시된 것을 확인할 수 있는데요. 이는 14400초, 즉 4시간을 디스크 상에 캐싱하겠다는 의미입니다.

이렇게 Cache-Control 헤더가 지정되어 있었기 때문에 클라이언트의 로컬 디스크에 정적 자원들이 캐시가 되고, 서버는 4시간 내에 아무리 새로운 파일을 배포하더라도 이전에 웹사이트에 들어온 적이 있던 사용자에게는 변경 영향을 미치지 못했던 것입니다.

그렇다면 이 Cache-Control 헤더는 어디서 생겨나는 것일까요? 백엔드 서버, 프론트엔드 서버, 그리고 Nginx에서는 따로 Cache-Control 헤더 지정을 해준 적이 없었기 때문에 예상되는 지점은 한 곳이었는데요. 바로 Cloudflare입니다.

Cloudflare 선택으로 인한 부수효과

저희 하루스터디팀은 HTTPS 프로토콜을 적용하기 위한 전략으로 비교적 설정이 간단한 Cloudflare를 선택했습니다. 그리고 Cloudflare 무료 플랜의 경우 다음과 같은 기능들이 제공됩니다.

하루스터디 팀은 SSL 암호화 통신을 위해 Cloudflare를 선택하긴 했지만, 이외에도 여러 기능을 제공하는 것을 볼 수 있습니다. 그리고 이 여러 기능들 중 CDN 서비스 때문에 앞서 언급했던 캐싱 문제 가 발생했던 것이었습니다.

CDN(Content Delivery Network)이란 여러 대의 물리적인 서버를 지리적으로 분산시켜 두고, 사용자와 가까운 서버에 Content(HTML, CSS, JavaScript 등)을 캐시하는 방식입니다.

Cloudflare의 경우에는 CDN 캐싱을 제공하면서 추가적으로 웹 브라우저 캐싱을 제공해줍니다. 즉, 리버스 프록시 역할을 수행하면서 들어오는 모든 응답에 대해 자동으로 Cache-Control 헤더를 지정한다는 의미입니다. 무료 플랜의 경우에는 기본적으로 4시간의 TTL을 지정해주고 있었습니다. 그리고 바로 이 기능 때문에 하루스터디의 서버가 보내는 모든 응답에 4시간(14400s)의 캐시 TTL이 적용되었던 것입니다.

따라서 아래처럼 Respect Existing Headers 옵션을 지정해 Cloudflare 서버에서 따로 Cache-Control 헤더를 다루지 않도록 설정했습니다.

하지만 이렇게 웹 브라우저 캐시를 제거했음에도 똑같은 문제가 발생했는데요, 이는 웹 브라우저 캐싱이 아닌 CDN 캐싱으로 인한 문제였습니다. 웹 브라우저에서 캐시를 하지 않더라도 CDN 서버에서 캐시를 하고 있으니 변경사항이 즉각 반영되지 않았습니다.

이는 Cloudflare에 접속해 직접 CDN 캐시 삭제(purge)를 하는 방식으로 해결했습니다. 이외에도 개발 모드 라는 기능을 제공해주는 것 같았는데, 트래픽 문제 때문에 Cloudflare에서도 권장하고 있는 기능은 아니기 때문에 하루스터디 팀은 손수 캐시 삭제(purge)를 하는 방식을 사용하고 있습니다.

물론 CDN 캐시 기능을 자체를 사용하지 않는다면 이러한 고민을 할 필요도 없어지지만, 어느정도 서비스가 안정적으로 자리잡는다면 짧은 주기의 배포를 할 일도 없을 뿐더러 CDN 캐시 기능이 매우 유용하게 작용하기 떄문에 완전히 배제하지는 않았습니다.

마치며

이번 아티클을 통해 웹 캐싱, CDN 캐싱이 어떻게 서비스 배포에 영향을 주는지 알아보았고 이를 통해 전체적인 네트워크 구조에 대한 이해도를 높일 수 있었습니다.

감사합니다.