• 본 시리즈에서는 How to GraphQL의 Tutorial 문서들을 차례대로 번역합니다.
  • 이 글은 GraphQL Advanced - Clients을 번역한 글입니다.
  • 오역 또는 의역이 있을 수 있습니다. 양해 부탁드리며, 수정할 필요한 부분은 댓글로 요청해주세요.

심화 튜토리얼 - 클라이언트

프론트엔드에서 GraphQL API를 사용하는 것은 새로운 추상화를 개발하고 클라이언트 사이드에서 공통 기능을 구현하는 데에 도움이 될 수 있는 절호의 기회입니다. 어플리케이션에서 필요로 할 만한 "기반 인프라" 기능 몇 가지를 아래에서 생각해봅시다.

  • HTTP 요청을 구성하지 않고 쿼리 또는 뮤테이션을 직접 전송하기
  • 뷰 레이어 통합
  • 캐싱 (Caching)
  • 스키마에 기반한 쿼리의 유효성 검사 및 최적화

당연히, 늘 하던 것처럼 일반적인 HTTP를 사용하여 데이터를 불러 오고, 데이터를 UI 상에 직접 넣어줄 수도 있습니다. 하지만 GraphQL을 사용하면, 위와 같은 과정을 거쳐서 직접 해야만 했던 수많은 수동 작업들을 추상화하고, 당신은 어플리케이션의 실제 중요한 부분들에 오롯이 집중할 수 있게 됩니다! 아래에서는 앞서 언급한 "기반 인프라" 작업들에 대하여 자세히 알아보도록 하겠습니다.

주로 사용되는 GraphQL 클라이언트로는 두 가지가 있습니다. 첫번째는 Apollo Client로, 강력하면서도 유연한 GraphQL 클라이언트를 모든 주요 개발 플랫폼에서 사용할 수 있도록 하겠다는 방향성 아래 형성된 커뮤니티에 의하여 개발이 이루어지고 있습니다. 두번째는 Relay로, Facebook이 개발한 원조 GraphQL 클라이언트입니다. 성능 최적화가 상당히 이루어져있으며, 오직 웹에서만 사용 가능합니다.

쿼리와 뮤테이션을 직접 전송하기

GraphQL의 주요 장점 중 하나는 선언적인 방식으로 데이터를 불러오거나 갱신할 수 있다는 것입니다. 다시 말해 API 추상화를 한 단계 더 진행한 것으로, 더 이상 저수준의 네트워크 작업을 직접 수행할 필요가 없다는 것입니다.

기존에 API를 사용하여 데이터를 불러오고자 단순 HTTP 요청(Javascript의 fetch 또는 iOS의 NSURLSession과 같은 것)을 사용했다면, GraphQL을 사용할 때에는 단지 필요한 데이터 요구 사항을 선언하는 쿼리를 작성하기만 하면 요청을 전송하고 응답을 받는 일련의 작업들을 시스템이 알아서 대신 처리해줍니다. 이것이 바로 GraphQL 클라이언트가 하는 일입니다.

뷰 레이어 통합 & UI 갱신

서버로부터 응답이 와서 GraphQL 클라이언트가 이를 처리하고 나면, 요청한 데이터는 어떻게든 결국 UI에 나타나야만 합니다. UI 갱신이 처리되는 방식은 개발 플랫폼과 프레임워크가 무엇인지에 따라 저마다 다를 것입니다.

React를 예로 들면, GraphQL은 고차 컴포넌트의 개념을 사용하여 필요한 데이터를 가져온 뒤 컴포넌트에 props 형태로 제공하는 일련의 방식을 보이지 않게 처리합니다. GraphQL의 선언적인 특성은 일반적으로 함수형 반응형 프로그래밍 기법과 특히 잘 어울립니다. 이 둘을 함께 사용하면 뷰는 단지 데이터 의존성을 선언하기만 하고, UI는 당신이 선택한 FRP 레이어와 알아서 결합되는 식으로 강력한 조합을 형성하게 됩니다.

쿼리 결과의 캐싱: 개념과 전략

대부분의 어플리케이션의 경우, 서버에서 막 불러온 데이터라면 캐싱하여 보관하는 것이 바람직합니다. 정보의 로컬 캐싱은 풍부한 사용자 경험에 필수적이고, 이를 통하여 사용자의 통신 부담을 경감시킬 수 있습니다.

데이터를 캐싱의 직관적인 형태는, 원격에서 불러온 정보를 나중에 다시 읽어들일 수 있는 로컬 스토어에 보관하는 것입니다. GraphQL을 사용하는 경우, 가장 단순한 방식은 GraphQL 쿼리 결과를 스토어에 넣고 동일한 쿼리가 발생할 때마다 직전에 보관된 데이터를 반환하는 것입니다. 대부분의 어플리케이션에서 이러한 접근 방식은 아주 비효율적입니다.

더 좋은 접근 방식은 데이터를 미리 정규화하는 것입니다. 즉, (잠재적으로 중첩될 수 있는) 쿼리 결과를 개별적인 요소로 정리(Flatten)하고, 전역적인 고유 ID로 참조될 수 있도록 만든 개별 데이터만을 스토어에 저장하는 것입니다. 이 주제에 대하여 더 자세하게 배우고 싶다면, Apollo 블로그에서 이를 다루는 좋은 글을 읽어보시길 추천합니다.

빌드 시간에 이루어지는 스키마 검사 & 최적화

스키마는 클라이언트가 GraphQL API를 사용하여 어떤 것을 할 수 있는지를 모두 담고 있습니다. 따라서 클라이언트가 전송할 쿼리를 검사하고 최적화하는 작업을 빌드 시간에 미리 수행할 수 있습니다.

빌드 환경이 스키마에 접근할 수 있다면, 프로젝트 내의 GraphQL 코드를 모두 파싱하여 스키마 상의 정보와 비교하는 것이 반드시 가능합니다. 이를 통하여 어플리케이션이 실제 사용자에게 전달되기에 앞서 오타를 바로잡거나 오류를 수정하고, 좋지 않은 사태를 사전에 예방할 수 있습니다.

뷰와 데이터 의존성을 함께 배치

GraphQL의 강력한 개념 중 하나는 UI 코드와 데이터 요구 사항을 나란히 두고서 다룰 수 있도록 해준다는 것입니다. 뷰와 데이터 의존성 간의 긴밀한 결합은 개발자 경험을 크게 향상시킵니다. 적절한 데이터가 UI에 적절하게 표시되도록 신경써야 하는 심리적 부담이 사라질 것입니다.

Quiz

GraphQL 클라이언트가 쿼리 결과를 캐싱하기 전에 주로 무엇을 수행하는가?

  • 쿼리 결과를 스키마와 비교하여 검사한다
  • 데이터를 정규화한다
  • 리졸버 함수를 호출한다
  • 데이터를 React 컴포넌트의 props로 제공한다