최근 회사에서 백엔드 api는 Graphql
로, 프론트엔드는 Vue
로 작업하고 있다.
나는 프론트엔드에서 vue-apollo라는걸 사용해서 Graphql
을 연동해서 사용한다.
이걸 사용하면서 새롭게 알게된 Apollo
의 fetchPolicy
에 대해 간략히 설명하고자 한다.
Apollo client
에서 graphql
을 사용해서 서버에서 데이터를 받아온다. 이 데이터를 메모리 캐시에 저장해뒀다가 같은 쿼리를 요청하면 캐시에 저장된걸 받아오거나 캐시를 무시하거나 할 수 있다. 이를 정해주는 옵션이 fetchPolicy
이다. 이를 적절히 사용하면 HTTP 요청을 최적화하고 캐시 데이터 공유를 쉽게 할 수 있다.
이 옵션이 기본값이고 다음 단계로 동작하는데, 2단계에서 멈출 수도 있다.
캐시 데이터를 먼저 확인하니, 불필요한 HTTP 요청을 줄여준다. 서버에서 최초 받아오고, 그 이후엔 변경될 여지가 적은 데이터에 유용하다. 예를 들면 시, 도, 군, 구
등의 주소 데이터는 쉽게 변경되지 않으니 이에 사용하면 좋을 거 같다.
이 옵션은 다음 5단계가 무조건 실행된다.
이 옵션의 핵심은 캐시 데이터와 무관하게 HTTP 요청이 발생한다는 것이다. 단, 요청이 발생하기 전 캐시 데이터가 있으면 일단 반환한다. 실시간으로 변경이 잦은 데이터의 빠른 응답 속도를 위해 캐시 데이터를 먼저 반환하고 이후에 서버에서 받아온 데이터를 응답할 때 유용할 것 같다.
이 옵션은 다음 3단계로 동작한다.
cache-and-network
옵션의 경우 만료된(outdated) 캐시 데이터를 초기에 보여줄 수 있다는 단점이 있다. 이 옵션을 사용하면 캐시 데이터를 확인하지 않고 무조건 HTTP 요청을 실행한다.
이 옵션은 HTTP 요청이 발생하지 않는 2단계로 동작한다.
무조건 캐시 데이터만 반환한다. 캐시 데이터가 없으면 에러를 발생시키므로 주의해서 사용해야한다.
이 옵션도 간단하게 2단계로 동작한다.
network-only
옵션에서 캐시 데이터를 업데이트하는 동작을 하지 않는 것이다.
현재 nuxt-apollo
라는 vue-apollo
를 Nuxt
에서 쓸 수 있게 만든 오픈소스를 사용한다. 아직 서비스 개발 초기 단계인데, 아쉬움이 느껴진다.
첫번째로는 서버 사이드 렌더링 지원이 미흡하다는 것이다. vue-apollo에서 제공하는 스마트쿼리라는 것을 통해 Vue 컴포넌트 내에서 쿼리를 사용하는데, Nuxt의 The client-side rendered virtual DOM tree is not matching server-rendered content.
에러가 발생한다. 공식 문서대로 따라했지만, 내가 설정을 잘못한 것일 수 있다.
두번째로는 fetchPolicy
옵션이 예상대로 동작하지 않는다. 일단 서버 사이드 렌더링 시 스마트쿼리가 실행되면 설정한 옵션과는 무관하게 캐시 데이터가 무조건 저장되는 동작을 확인했다. 버그인지, 원래 동작인데 문서화가 안된 것인지 모르겠다. 공식 문서에서도 이와 관련된 내용은 찾지 못했다. 이참에 이슈 남기고 문서화 기여를 해볼까?
전술한 두가지가 아쉽지만 Graphql
은 확실히 좋다. 오히려 개발 속도가 빨라졌고, 상태 관리도 쉽게 된다. 가장 마음에 드는 점은 REST Api
처럼 Vue
, React
등 환경에 독립적인 기술이라는 것이다. 지금은 Vue
로 개발하고 있지만 나중에 Angular
, React
를 할 기회가 오더라도 Graphql
을 활용할 수 있다.