React SPA 뒤로가기 API Cache 적용

Single Page App(SPA) 방식으로 많이 개발되는 추세인데, 반대로 MPA가 주는 좋은 경험을 세심하게 살려서 개발하는 앱은 찾기 힘든 것 같습니다. SPA가 더 빠른 반응성을 제공하는 것은 좋지만 링크를 새탭으로 열기, 뒤로가기 등 브라우저의 기본기능이 주는 경험을 살리는 것에는 상대적으로 관심이 부족한 것 같아서 안타깝습니다.

특히 뒤로가기를 했을 때 페이지를 다시 불러오는 동작으로 불필요한 로딩이 있고, 심한 경우 스크롤까지 상단으로 초기화되는 곳도 볼 수 있습니다. 스크롤의 경우 페이지별 스크롤 위치를 기억하는 헬퍼를 만들어서 뒤로가기 시 스크롤을 보전해주는 방법이 일반적인 것 같습니다. 하지만 뒤로가기 했을 때에도 발생하는 ajax 요청으로 페이지를 다시 로딩하는 동작은 반응성이 매우 떨어지는 경험입니다.

이를 해결하는 방안으로 라우터 내용을 그대로 캐시하도록 Vue.js에서 제공하는 keep-alive 기능이 있고, React에도 유사하게 react-router-cache-route,
react-keeper 가 있습니다. 그러나 사이드이펙트에 대한 우려는 있습니다. Redux State를 조사해서 API 요청 여부를 결정할 수도 있을 것 같고, GraphQL의 경우 캐시를 콘트롤하는 방법도 있습니다.

여러가지를 검토하다가 가장 쉬운 방법으로 API 요청을 캐시하는 방법을 적용해봤습니다. 먼저 아래 GIF 녹화 이미지에서 적용된 결과를 보겠습니다.

페이지를 이동한 후 네트워크 패널에서 XHR 로그를 삭제했습니다. 그리고 뒤로가기를 여러번 하는 동안 API 요청 XHR이 발생하지 않습니다. 화면도 로딩없이 즉각적으로 렌더링됩니다.

브라우저에서 뒤로가기를 해도 API요청은 발생하지 않고, 화면도 빠르게 뜬다.

캐시에 사용한 모듈은 axios-extensions 입니다.
아래처럼 API를 담당하는 파일에만 적용했습니다.

import axios from 'axios'
import { cacheAdapterEnhancer } from 'axios-extensions'
import { history } from '~/index' // BrowserHistory
/// 생략

const http = axios.create({
  baseURL: 'https://conduit.productionready.io/api',
  // cacheAdapterEnhancer 적용. 기본 캐시동작은 해제
  adapter: cacheAdapterEnhancer(axios.defaults.adapter, { enabledByDefault: false })
})

const historyPopCache = config => ({
  forceUpdate: history.action === 'PUSH',
  ...config,
  cache: true,

  // 뒤로가기, 앞으로가기 : forceUpdate: false
  // 링크 클릭 이동 : forceUpdate: true
})

// 필요한 요청의 config 객체와 historyPopCache()를 merge하여 뒤로가기 캐시 적용
const Articles = {
  all: ({ page, config } = {}) => {
    return http.get(`/articles?${limit(10, page)}`, historyPopCache(config))
  },
  feed: ({ page, config } = {}) => {
    return http.get(`/articles/feed?${limit(10, page)}`, historyPopCache(config))
  },
  get: ({ slug, config } = {}) => {
    return http.get(`/articles/${slug}`, historyPopCache(config))
  },
}

목록과 상세페이지, 프로필 등.. 캐시가 유용한 API에만 적용했습니다.
history의 action이 PUSH일 때만 forceUpdate를 하면 ‘뒤로가기’, ‘앞으로가기’ 이동에는 캐시된 데이터가 응답되고, 링크를 눌러서 이동할 때만 새로고침됩니다.

캐시가 적용되어도 fetch action 자체는 호출되지만 이미 준비된 데이터를 응답하기 때문에 화면에는 로딩표시 없이 바로 렌더링됩니다.

간단한 방법으로 사용성과 성능을 개선하는 방법이었습니다.
이상입니다.

“React SPA 뒤로가기 API Cache 적용”에 한개의 의견

  1. 글 잘 읽었습니다! ㅎㅎ 궁금한점이 있는데요 혹시 리액트 기반 SPA 페이지가 아닌 MPA 체이지에서도 axios api 캐시를 하면 다른 페이지를 갔다가 뒤로가기를 해도 최상단으로 올라갔다가 다시 이전 위치로 오는 부분이 해결이 가능할까요?… 테스트 중인데 API 부분쪽에 사용이 미숙해서 ㅠㅠ 많이 막혀서요!

답글 남기기

이메일 주소는 공개되지 않습니다.

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.