GitHub Issues가 클라이언트 사이드를 재설계한 이유
웹 애플리케이션에서 네비게이션 성능은 사용자 경험의 핵심이다. GitHub는 Issues 페이지의 즉각적인 네비게이션(instant navigation) 비율이 고작 4%에 불과하다는 문제를 인식하고, 서버 사이드 최적화가 아닌 클라이언트 사이드 아키텍처 전면 재설계로 접근했다. 이 선택이 흥미로운 이유는, 많은 팀이 성능 문제를 서버나 인프라 레벨에서 해결하려는 경향이 있기 때문이다. GitHub는 네트워크 왕복 자체를 줄이는 것이 아니라, 사용자가 체감하는 레이턴시를 낮추는 방향으로 전략을 전환했다.
백엔드 개발자 입장에서도 이 접근은 중요한 시사점을 준다. API 응답 속도를 아무리 최적화해도, 매번 네트워크 요청이 발생한다면 한계가 있다. 클라이언트가 데이터를 얼마나 영리하게 재활용하느냐가 실질적인 사용자 경험을 결정한다.
핵심 기술 구성: 다층 캐싱과 Service Worker
GitHub가 선택한 아키텍처는 세 가지 레이어를 조합한다.
- 인메모리 캐시: 동일 세션 내 반복 접근에 가장 빠른 응답 제공
- IndexedDB 기반 영구 캐시: 브라우저를 닫았다가 재방문해도 이전 데이터를 즉시 렌더링
- Service Worker: 네트워크 요청을 가로채 캐시 우선 전략으로 응답, 백그라운드에서 최신 데이터를 동기화
이 구조는 백엔드의 Cache-Aside 패턴과 개념적으로 유사하다. 캐시에 데이터가 있으면 즉시 반환하고, 없거나 만료된 경우에만 원본 소스를 조회한다. 차이점은 이 모든 로직이 클라이언트에서 동작한다는 점이다.
// Service Worker의 캐시 우선 전략 개념
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request).then((cached) => {
const networkFetch = fetch(event.request).then((response) => {
// 백그라운드에서 캐시 갱신
caches.open('issues-cache').then((cache) => cache.put(event.request, response.clone()));
return response;
});
return cached || networkFetch;
})
);
});
백그라운드 동기화를 통해 사용자는 캐시된 데이터를 즉시 보고, 최신 데이터는 조용히 업데이트된다. 이 패턴은 Stale-While-Revalidate 전략과 맥락이 같다.
예측 기반 프리페칭의 실무적 의미
GitHub는 단순한 캐싱을 넘어 **예측 기반 프리페칭(predictive prefetching)**을 도입했다. 사용자가 어떤 이슈 목록을 보고 있을 때, 클릭 가능성이 높은 이슈의 데이터를 미리 가져오는 방식이다. 이를 통해 사용자가 실제로 링크를 클릭하는 시점에는 이미 데이터가 준비되어 있어 즉각적인 렌더링이 가능해진다.
이 전략은 백엔드 설계에도 영향을 준다. 프리페칭이 효과를 발휘하려면 API가 예측 가능하고 가벼운 응답을 제공해야 한다. 불필요한 데이터를 포함한 무거운 API 응답은 프리페칭 비용을 높이고, 오히려 네트워크 낭비로 이어질 수 있다. GraphQL의 필드 선택이나 REST API의 sparse fieldset 설계가 이런 맥락에서 더욱 중요해진다.
결과적으로 GitHub는 instant navigation 비율을 4%에서 22%로 약 5.5배 향상시켰고, 전반적인 네비게이션 레이턴시도 유의미하게 감소했다. 서버 응답을 바꾸지 않고도 이 수치를 달성했다는 점이 핵심이다.
정리
- 체감 레이턴시를 줄이려면 서버 최적화뿐 아니라, IndexedDB·Service Worker를 활용한 클라이언트 다층 캐싱 전략이 유효하다
- Stale-While-Revalidate 패턴으로 즉각적인 응답과 데이터 최신성을 동시에 달성할 수 있다
- 예측 기반 프리페칭의 효과를 극대화하려면 API 응답이 가볍고 예측 가능한 구조여야 하며, 백엔드 설계 단계부터 고려해야 한다