[개발] React 데이터 패치에 최적화된 Relay 사용하기

Eunho Lee
7 min readJun 5, 2020

--

React conf 2019에서 소개한 React Concurrent mode에서는 앱이 빠른 반응 속도를 유지하도록 하며, 네트워크 속도에 따라 랜더링 속도를 적절하게 맞추도록 돕는 기능들을 소개합니다.

이와 함께 데이터 패치에 대한 최적화된 프레임워크인 Relay를 강조했는데요. 여기에서는 우리에게 생소한 GraphQL 클라이언트인 Relay를 소개하고, 간단한 예제를 통해 어떤 방식으로 React가 데이터 패치를 최적화하고 있는지 알아보고자 합니다.

또한 Concurrent mode에서 제공하는 React.Suspense를 통해 React가 어떻게 데이터 패치에 대해 유연하게 랜더링 가능하게 하는지에 대해서도 알아보겠습니다.

Relay

여러분이 생각하는 React의 장점은 무엇인가요? 컴포넌트를 통해 복잡한 어플리케이션을 구성하기 때문에 서로 다른 컴포넌트 간의 간섭이 적습니다. 또한 선언적으로 UI를 작성하기 때문에 컴포넌트의 state에 따라 선택적으로 UI를 보여줄 수 있죠. 그렇기 때문에 개발자들은 어떤 위치에 어떤 명령으로 UI를 보여줘야할지 고민하지 않고, 컴포넌트 개발에만 집중할 수 있게 되었습니다.

데이터 패치는 이러한 React의 이점을 잘 살리고 있을까요?

데이터 패치를 위한 쿼리는 여전히 컴포넌트와 매우 밀접하게 결합되어있고 이러한 관계로 인해 컴포넌트에서 필요로 하는 데이터 셋이 변경될 경우, 쿼리도 그에 맞게 변경해야했습니다. 또한 컴포넌트를 랜더링하기 위한 데이터를 확인하기 위해선 일일히 쿼리를 확인해야하는 불편함이 있었습니다.

Colocation pattern

React와의 최상의 궁합을 위해 Relay에서는 colocation 패턴을 제안합니다. colocation이란 컴포넌트와 컴포넌트가 필요로 하는 데이터를 함께 선언함으로서 데이터 패치를 좀 더 유연하고 명료하게 처리 가능할 수 있는 개념입니다.

  • 일일히 어떤 쿼리를 통해 데이터가 패치되는지 찾을 필요 없이, 컴포넌트 자체에 선언된 Fragment를 통해 확인 가능하다.
  • 컴포넌트와 쿼리가 구분되어진다. 컴포넌트에 필요한 데이터가 변경되는 경우, 쿼리를 변경하는 것이 아니라 Fragment만 변경하면 되기 때문에 다른 컴포넌트와의 충돌을 걱정하지 않아도 된다.

FragmentGraphQL의 핵심 개념 중 하나입니다. Relay는 이러한 GraphQL의 개념을 클라이언트에 적용하면서, React와의 최적화된 패턴을 완성합니다.

친구 목록 불러오기

간단한 친구 목록을 구현했습니다. Friend 컴포넌트를 Friends 로 감싸고 있는 구조입니다. Friend 컴포넌트에서는 GraphQL 스키마에 정의된 User 타입의 idname, photoURL 이 필요합니다. 이것을 Fragment로 묶어서 선언하고 Friend_user 이라는 이름을 부여합니다.

Friend.tsx

이렇게 선언된 Friend_user 는 상위 Friends 컴포넌트에서 적절하게 조합하여 단일 쿼리를 만들 수 있습니다. 여기서 중요한 점은 Friends 에서는 하위 컴포넌트의 data dependency의 변경에 영향을 받지 않고 쿼리가 할 수 있고, 필요에 따라 다른 Fragment를 구성하여 단일 쿼리를 만들 수 있다는 점입니다.

Friends.tsx

React.Suspense

이제 어떻게 이러한 데이터 패치를 유연하게 만들 수 있는지 알아보겠습니다.

기존의 데이터 패치 로직을 작성할 때, 패치 시작 전 준비 상태로 전환하고 스피너가 빙글빙글 돌게 되죠. 패치를 완료하고 컴포넌트를 랜더할 준비가 되면 준비 상태를 해제하게 되면서 컴포넌트가 보여집니다. 만약 여기서 에러가 발생한다면 에러 상태를 업데이트하여 적절한 에러 컴포넌트를 보여줍니다.

모든 컴포넌트에서 이러한 패턴으로 데이터 패치를 한다면 여기에 사용되는 리소스는 얼마나 클까요?

Data Fetching With Suspense In Relay | Joe Savona 세션 중

Suspense를 사용하게 되면 컴포넌트가 랜더링 가능할 때까지 기다릴 수 있습니다. 그 사이에 예기치 못한 에러가 생기게 된다면 ErrorBoundary를 통해 컴포넌트의 오류를 잡아내고, 적절한 컴포넌트를 대신 랜더링 할 수 있습니다.

Suspense and ErrorBoundary

이러한 SuspenseRelay를 통합하여 강력한 데이터 패치 로직을 완성할 수 있습니다.

하위 컴포넌트들의 data dependencies를 통합하여 쿼리를 최적화하고, 최적화된 쿼리를 통해 패치를 진행하는 동안 Suspense를 통해 유연하게 컴포넌트를 랜더링 할 수 있게 됩니다.

더이상 isLoading은 필요 없다

관련 소스는 아래에 정리해두었습니다.

마치며

REST의 시대에서 GraphQL의 시대로 옮겨가고 있다는 것을 느낍니다. 보다 효율적인 방식을 택한다면 GraphQL을 쓰지 않을 이유가 없겠지요.

그에 맞게 클라이언트의 변화도 이미 시작되고 있습니다. React는 앞으로 Relay와 통합하여 그들의 UI와 더불어 데이터 패치에 최적화된 패턴으로 시장을 선도하게 될 것 같습니다.

이번 포스팅은 많은 제게 많은 의미가 있습니다.

정보 공유를 위해 포스팅하는 것과, 실험적인 요소들을 미리 적용해보는 것 모두 처음이기 때문입니다.

This documentation is aimed at early adopters and people who are curious
https://reactjs.org/docs/concurrent-mode-suspense.html 중에서

앞으로도 부단히 새로운 기술에 대해서 관심을 가지고 호기심을 가지는 사람이 되어 좋은 정보들을 공유하도록 하겠습니다.

부족한 글 읽어주셔서 감사합니다.

참고자료

--

--