본 글은 브라우저 캐시로 인해 사용자에게 이전 버전의 웹 리소스가 제공되어 장애가 발생한 이슈에 대해 스토리 느낌으로 기록해 놓고자 합니다.
먼저, 이슈에 대해 이야기하기 전에 이해를 돕기 위한 내용으로 시작하겠습니다.
저는 사내에서 ‘기업의 성장을 돕기위해 다양한 기능을 제공’하는 그룹웨어 솔루션의 웹 프론트엔드 개발을 하고 있습니다.
그룹웨어란, 협업을 위해 필요한 다양한 비즈니스 기능을 하나의 플랫폼에서 지원하는 업무용 소프트웨어를 말합니다. 비즈니스 기능이라고 하면 ‘전자결재’, ‘메일’, ‘게시판’, ‘인사관리’ 등을 지원합니다.
‘전자결재’ , ’메일’, ‘게시판’, ‘인사관리’ 를 각각 하나의 솔루션이라고 부르겠습니다.
각 솔루션의 코드베이스는 깃랩(gitlab)의 다른 저장소(repository)에 저장하고 있으며, 독립적으로 배포 가능한 MSA(Micro Service Architecture)로 구성되어 있습니다.
MSA로 구성되어 있음에 따라 전자결재 솔루션에서 수정 사항이 발생하면 다른 ‘메일’, ‘게시판’, ‘인사관리’ 서비스의 코드에 영향을 받지 않고 배포를 할 수 있습니다.
→ GNB란, Global Navigation Bar의 약자로, 보통 웹 사이트 최상단에 위치하며 메인 메뉴라고 생각하면 됩니다.
각 솔루션은 ‘공통 GNB’(이하 GNB)를 불러와 사용하고 있습니다.

GNB는 각 솔루션의 웹 페이지에 접근 시,
<script src=”https://gnb.company.com/main.js”></script>
태그를 읽어 들여 스크립트를 다운로드하고 로드하여 사전에 정의한 GNB 영역(<div id=”gnb영역” />)에 컨텐츠를 렌더링합니다. 이 방식은 각 솔루션에서 GNB 소스코드를 관리할 필요가 없다는 장점을 가지고 있습니다.
또한, GNB 수정사항이 생기면 한 곳에서 수정하면 되니 중복 코드와 중복 작업을 줄일 수 있다는 장점을 가지고 있습니다.
자 그러면 이제 문제에 대해 이야기해보겠습니다.
각 솔루션에서 수정 전 모습의 GNB를 렌더링 하는 이슈가 발견되었습니다.
그리고 일부 사용자에게만 해당 증상이 발생했습니다.
사용하는 곳이 많다보니 사용자 피드백(VOC)이 빨리 왔습니다.
이번 GNB 소스코드 수정 내용에는 API 스펙 변경이 있었고 호출 응답값이 달라져 잘못된 변수에 접근하다가
애플리케이션 전체적으로 동작하지 않는 현상, 데이터가 보이지 않는 현상 등이 발생했습니다.
사용자가 이전에 솔루션에 접근을 했었다면 GNB 리소스를 캐싱을 해둔 상태였고,
GNB 배포 후에도 이전에 캐싱해둔 GNB 리소스를 사용해서 발생한 문제입니다.
브라우저는 리소스를 디스크 또는 메모리 캐시에 저장해놓고 다음에 가져다가 쓰고 있습니다.


각 차이는 다음과 같습니다.
메모리 캐시
브라우저의 메모리에 직접 저장하는 방식
브라우저 닫으면 사라짐
매우 빠른 접근 속도
작은 크기의 리소스나 자주 사용되는 리소스에 적용
디스크 캐시
하드 디스크에 저장함
메모리 캐시보다 느림
브라우저를 닫아도 유지 됨
큰 크기의 리소스나 덜 자주 사용되는 리소스에 적용
브라우저가 캐시를 사용할 때는 서버에 요청을 보내지 않고 바로 메모리에서 리소스를 가져옵니다.
“사용자가 각 웹 솔루션에 접속하면 브라우저가 GNB 리소스를 다르게 식별하게 만들어 캐시를 못하게 만들자! 그러면 사용자들은 수정된 GNB를 볼 수 있겠지!”
다음처럼 GNB 리소스 호출 시에 쿼리스트링을 붙이는 방식으로 진행하기로 했습니다.
<script src=”https://gnb.company.com/main.js?v={특정 값}”></script>

그런데, GNB는 여러 솔루션에서 호출됨에 따라 많은 호출량을 가지고 있습니다.
또, 일부 솔루션은 MPA(Multi Page Application)으로 되어있어 페이지 이동마다 GNB를 호출 했습니다.
리소스 낭비를 줄이기 위해서는 캐시가 필요했습니다.
만약 ‘특정 값’(GNB URL 쿼리스트링)을 매번 웹에 접속할 때 새로운 값을 가지게 한다면?
예를 들어 ‘특정 값’이 (new Date()).getTime() 값이라고 한다면 매번 새로운 GNB 리소스를 호출하게 됩니다.
그래서 저희는 ‘특정 값’이 변경되는 시점을 각 솔루션에서 소스코드를 빌드하고 배포할 때, 만들어진 값으로 사용하기로 합니다. 값은 git-describe 라이브러리를 활용하여 output 값을 사용했습니다.
그럼 솔루션에서 빌드하고 난 뒤부터 사용자는 새로운 특정 값으로 웹에 접근하니 새로운 GNB 리소스를 불러오게 되고, 이후 호출은 동일한 ‘특정 값’을 가지고 있어 브라우저 캐시 효과를 누릴 수 있었습니다.
이 방법으로 우리는 브라우저 캐시 문제를 해결할 수 있었습니다.
하지만, 위 방법은 임시 방법이였습니다. 이 문제는 이후 우리를 번거롭게 한 계기가 됩니다.
글이 길어져 다음 글에서 이어서 이야기하도록하겠습니다.
상황측면으로 장애 소식은 생각 이상으로 당황스럽게 했습니다. 빠르게 이슈를 해결해야하는 상황이였습니다.
경험치에 비해 생각할 시간이 부족했었던 것 같습니다. 브라우저 캐시에 대한 지식 부족했고, 문제를 클라이언트 소스코드 내에서만 한정해서 해결하려고 했습니다.
공통 GNB가 브라우저 캐시로 인해서 일부 사용자에게 이전 버전의 GNB 가 보여지는 현상으로 인해서 장애가 발생합니다. 장애를 해결하기 위해서 브라우저 캐시를 무효화 시키는 작업을 시작합니다.
각 솔루션에서 GNB 리소스를 호출 시에 브라우저가 최소한으로 캐시하지 못하도록 작업했습니다.
하지만, 이 방법은 근본적인 해결방법은 아니였습니다. 더 좋은 방법을 찾게 됩니다. 이에 대한 내용은 다음 링크를 통해 이어집니다.