React Native
Relay (GraphQL)
리액트 네이티브에서 Relay 쿼리 렌더러 사용하기
29 분
back4app의 쿼리 렌더러 소개 이전 가이드 , 우리는 relay 환경을 준비하는 방법을 배웠습니다 이제 react native 앱 개발을 시작할 준비가 되었습니다 이 가이드에서는 back4app에서 첫 번째 쿼리를 만드는 방법을 배웁니다 relay 쿼리 렌더러에 대해 깊이 파고들고, 그 주요 원칙을 이해하며 back4app에서 첫 번째 데이터를 소비하는 데 사용할 것입니다 목표 relay 쿼리 렌더러에 대한 개요를 얻기; relay를 사용하여 react native 앱에서 back4app graphql api에 쿼리하기; 전제 조건 back4app 대시보드에서 생성된 애플리케이션 이전 문서에서 구성된 relay 환경을 가진 react native 애플리케이션 relay 노드 및 연결에 대해 읽기 쿼리 렌더러란 무엇인가? react가 컴포넌트의 트리를 구축하는 것처럼, relay는 데이터 컴포넌트의 트리를 구축합니다 이는 애플리케이션의 각 컴포넌트가 자신의 프래그먼트 데이터를 소유하게 됨을 의미합니다 프래그먼트는 화면에 렌더링하는 데 필요한 데이터 정보를 포함하며, relay는 컴포넌트를 렌더링하기 전에 이 데이터가 사용 가능하도록 보장합니다 이 전체 접근 방식을 처리하면서, 쿼리 렌더러는 이러한 프래그먼트를 구성하고 백엔드에서 가져올 쿼리를 준비하는 데 필요한 루트 컴포넌트입니다 쿼리 렌더러를 이해하는 이유는 무엇인가? 쿼리 렌더러의 사용을 이해하는 것은 애플리케이션을 다양한 방식으로 추상화하는 데 중요합니다 코드의 좋은 추상화는 작업 시간, 오류, 디버깅 시간 등을 줄일 수 있습니다 렌더러가 back4app api와 함께 작동하는 방식 지난 튜토리얼에서는 back4app 연결 정보를 지정하는 relay 환경 파일을 준비했습니다 이 구성을 사용하여 relay는 back4app api와의 통신을 처리합니다 연결에 대해 걱정할 필요가 없습니다 데이터 구성 요소를 구축하는 데 집중하세요 1 back4app 대시보드에서 클래스 만들기 back4app graphql 콘솔을 사용하여 첫 번째 클래스를 만들고 몇 개의 객체로 채워 보겠습니다 person 클래스에는 문자열인 name 필드와 정수인 salary 필드가 있습니다 대시보드 >코어 >graphql 콘솔로 이동하여 아래 코드를 사용하세요 1 mutation createclass { 2 createclass(input { 3 name "person" 4 schemafields { 5 addstrings \[{name "name"}] 6 addnumbers \[{name "salary"}] 7 } 8 }){ 9 class{ 10 schemafields{ 11 name 12 typename 13 } 14 } 15 } 16 } 아래에서 결과를 확인할 수 있습니다 클래스 생성 이 클래스 안에 객체를 생성해 보겠습니다 객체 생성 뮤테이션 가이드 https //www back4app com/docs/parse graphql/graphql mutation create object#mutation generic 를 확인하고 이 경우를 처리하는 방법을 알아보세요 back4app에서 사용할 수 있는 최신 graphql api 표기법을 사용하기 위해 최신 parse server 버전을 사용하고 있는지 확인하세요 1 mutation createobject{ 2 createhero(input {fields {name "allana foley", salary 1000}}){ 3 person { 4 id 5 name 6 salary 7 } 8 } 9 } 객체 생성 이제 person 클래스가 생성되었고 이름과 급여 필드가 있습니다 새 클래스를 생성한 후, back4app은 백엔드를 안전하게 사용하기 위해 필요한 모든 리소스를 자동으로 생성합니다 한 예는 객체 목록입니다 back4app은 이미 사람 목록을 쿼리하는 데 필요한 연결을 생성했습니다 people 더 잘 이해하려면, 플레이그라운드로 가서 새로 고침하고 문서 탭을 열어 people을 찾아보세요 back4app이 연결 필드를 생성했습니다 클래스 person을 목록으로 쿼리할 수도 있습니다 query people 필드는 personconnection임을 주의하세요 relay는 연결 필드를 사용하여 person 객체 목록을 렌더링합니다 person 필드 문서 그리고 people (person) 연결 필드 문서 2 스키마 업데이트 새로운 클래스가 애플리케이션에 추가되면, react native 애플리케이션의 루트 내에서 스키마를 업데이트해야 한다는 점을 기억하는 것이 중요합니다 필요하다면, 스키마 다운로드 문서로 가서 스키마를 업데이트하는 단계를 반복하세요 3 프래그먼트 컨테이너의 첫 번째 예 튜토리얼을 계속하기 전에, 프래그먼트 컨테이너를 소개하겠습니다 사람 정보를 소유할 컴포넌트를 생성해 보겠습니다 이 컴포넌트는 사람의 이름과 급여를 포함할 것입니다 여기에서 컴포넌트를 구축하기 위해 어떤 사람 필드든 요청할 수 있습니다 이제 이 두 필드로 진행하겠습니다 파일을 생성하고 이름을 personcard js personcard js 그 안에 간단한 함수형 컴포넌트를 생성합시다 1 import react from 'react'; 2	 3 const personcard = () => { 4 return ( 5 \<div> 6 7 \</div> 8 ); 9 }; 아래 코드로 export default 라인을 교체하세요 1 export default createfragmentcontainer(personcard, { 2 person graphql` 3 fragment personcard person on person { 4 id 5 name 6 salary 7 } 8 `, 9 }); 위 코드는 id, name, salary만 요청하는 person의 프래그먼트를 생성합니다 다음 코드로 나머지 컴포넌트를 업데이트하세요 1 const personcard = ({person}) => { 2 return ( 3 \<view> 4 \<text>name {person name}\</text> 5 \<text>salary {person salary}\</text> 6 \</view> 7 ); 8 }; 최종 결과는 다음과 같아야 합니다 1 import react from "react"; 2 import { createfragmentcontainer, graphql } from "react relay"; 3 import { view, text } from "react native"; 4	 5 const personcard = ({person}) => { 6 return ( 7 \<view> 8 \<text>name {person name}\</text> 9 \<text>salary {person salary}\</text> 10 \</view> 11 ); 12 }; 13	 14 export default createfragmentcontainer(personcard, { 15 person graphql` 16 fragment personcard person on person { 17 id 18 name 19 salary 20 } 21 `, 22 }); 4 쿼리 렌더러 만들기 다음 단계는 객체 목록을 위한 쿼리 렌더러를 만드는 것입니다 쿼리 렌더러는 데이터 구성 요소를 검색하고 백엔드에서 데이터를 가져오도록 준비하는 루트 구성 요소입니다 back4app에서 person 클래스의 데이터를 검색하는 방법을 배우게 됩니다 4 1 파일 만들기 새 파일을 만들고 이름을 personrenderer js personrenderer js 아래 코드를 복사하여 personrenderer 파일에 붙여넣습니다 1 const personrenderer = () => { 2 return ( 3 \<queryrenderer 4 environment={environment} 5 query={graphql``} 6 variables={null} 7 render={({error, props}) => { 8 if (error) { 9 return ( 10 \<view> 11 \<text>{error message}\</text> 12 \</view> 13 ); 14 } else if (props) { 15 // @todo here will be implement the person card for each item from result 16 } 17 return ( 18 \<view> 19 \<text>loading\</text> 20 \</view> 21 ); 22 }} 23 /> 24 ); 25 }; 26	 27 export default personrenderer; 4 2 queryrenderer의 props 이해하기 query renderer를 props가 비어 있는 상태로 시작해 보겠습니다 graphql, variables, render 단계별로 각 항목을 점진적으로 구현할 것입니다 우선, 애플리케이션은 query renderer에 대한 쿼리를 알려야 합니다 여기서 우리의 애플리케이션은 people 목록을 소비할 것입니다 쿼리 props에 다음 코드를 붙여넣으세요 1 graphql` 2 query personrendererquery { 3 people { 4 edges { 5 node { 6 personcard person 7 } 8 } 9 } 10 }` graphql은 react relay에서 가져오며 쿼리를 문자열로 구현합니다 edges와 node 연결을 이해하는 것이 중요합니다 위 쿼리는 back4app 서버에서 사람들의 node 연결을 소비하고 있습니다 새 클래스를 생성할 때마다 node 연결이 뒤따릅니다 변수 필요할 때 쿼리 렌더러는 변수를 소비합니다 좋은 예 애플리케이션이 id로 사람에 대한 쿼리를 요청할 때입니다 현재는 그런 경우가 아니므로 변수 props에 null을 전달합시다 person card 채우기 이 쿼리는 사람 목록을 반환합니다 쿼리 렌더러는 데이터를 렌더링할 수 있도록 보장합니다 그렇지 않으면 오류를 발생시킵니다 이를 담당하는 props는 render입니다 다음 코드를 사용하여 render props를 채우세요 1 render={({error, props}) => { 2 if (error) { 3 return ( 4 \<view> 5 \<text>{error message}\</text> 6 \</view> 7 ); 8 } else if (props) { 9 return props people edges map(({node}) => \<personcard person={node} />); 10 } 11 return ( 12 \<view> 13 \<text>loading\</text> 14 \</view> 15 ); 16 }} 주석 처리된 todo를 각 결과에 대한 사람 카드를 렌더링하기 위한 javascript map으로 교체하세요 앞서 말했듯이, 쿼리 렌더러는 데이터가 준비되었을 때만 사용할 수 있도록 책임을 집니다 그때까지는 로딩 메시지가 표시됩니다 오류가 발생하면 화면에 표시되어 예기치 않은 애플리케이션 충돌을 방지합니다 마지막으로, map을 새로운 함수로 대체하여 사람 렌더링을 개선합시다 쿼리 렌더러 앞에 두세요 1 const renderpersons = (people) => { 2 return people edges map(({node}) => \<personcard person={node} />); 3 }; 그리고 최종 결과는 다음과 같아야 합니다 1 import react from "react"; 2 import { queryrenderer } from "react relay"; 3 import environment from " /relay/environment"; 4 import personcard from " /personcard"; 5 import { view, text } from "react native"; 6	 7 const personrenderer = () => { 8 const renderpersons = (people) => { 9 return people edges map(({node}) => \<personcard person={node} />); 10 }; 11	 12 return ( 13 \<queryrenderer 14 environment={environment} 15 query={graphql` 16 query personrendererquery { 17 people { 18 edges { 19 node { 20 personcard person 21 } 22 } 23 } 24 } 25 `} 26 variables={null} 27 render={({error, props}) => { 28 if (error) { 29 return ( 30 \<view> 31 \<text>{error message}\</text> 32 \</view> 33 ); 34 } else if (props) { 35 return renderpersons(props people); 36 } 37 return ( 38 \<view> 39 \<text>loading\</text> 40 \</view> 41 ); 42 }} 43 /> 44 ); 45 }; 46	 47 export default personrenderer; 5 첫 번째 쿼리 만들기 이제 personrenderer를 사용하여 person을 가져올 시간입니다 모든 것이 괜찮다면, 귀하의 애플리케이션에는 이제 두 개의 새로운 구성 요소가 있습니다 personrenderer와 personcard 애플리케이션을 시작하기 전에, relay는 relay compiler가 실행되어 구성 요소 유형을 생성해야 합니다 이를 위해 터미널에 다음을 입력하세요 app js에 다음 코드를 추가하세요 1 import react from 'react'; 2 import { safeareaview, statusbar, view, text } from 'react native'; 3	 4 import providers from ' /providers'; 5 import personrenderer from ' /components/home/person/personrenderer'; 6	 7 const app = () => { 8 return ( 9 \<providers> 10 \<statusbar barstyle="dark content" /> 11 \<safeareaview> 12 \<view 13 style={ { 14 flexdirection 'column', 15 justifycontent 'center', 16 alignitems 'center', 17 margintop 100, 18 } }> 19 \<text style={ {fontweight "bold", textalign "center"} }> 20 back4app react native relay query renderer list example 21 \</text> 22 \<personrenderer /> 23 \</view> 24 \</safeareaview> 25 \</providers> 26 ); 27 }; 28	 29 export default app; app js의 코드는 원래 create react native app에서 가져온 것입니다 화면 중앙에 콘텐츠를 배치하기 위해 스타일이 적용된 view를 추가했으며, 상단에서 10px의 여백을 두었습니다 그 안에는 출력에 대한 맥락을 제공하는 레이블이 있는 텍스트와 사람 목록을 표시하는 personrenderer가 있습니다 다음 결과를 얻어야 합니다 렌더링 우리의 back4app react native 애플리케이션에서 우리는 personrenderer를 직접 app js app js personrenderer는 루트 컴포넌트이며 queryrenderer를 가지고 있으므로, person은 오류 없이 표시되어야 합니다 6 컴포넌트 타이핑 이 단계는 타입스크립트로 작업하는 애플리케이션에 의미가 있습니다 애플리케이션이 타입스크립트를 사용하지 않는 경우 진행하세요 relay compiler의 강력한 기능 중 하나는 각 데이터 컴포넌트에서 타입을 생성하는 것입니다 personrenderer와 personcard의 타입을 지정하여 애플리케이션을 더 강력하게 만들어 봅시다 personrenderer 타이핑 renderperson 함수의 인수 people people 을(를) personrenderer에 입력하세요 1 const renderpersons = (people personrendererquery\['response']\['people']) => { 2 return people edges map(({node}) => \<personcard person={node} />); 3 }; 다음에서 personrendererquery personrendererquery 타입을 가져오세요 generated generated 폴더는 personrenderer와 동일한 폴더 내에 생성됩니다 personcard 타이핑 personcard로 이동하여 새 타입 객체를 생성하고 이름을 personcardprops로 지정하세요 1 type personcardprops = {}; 다음에서 personcard person personcard person 타입을 가져오세요 generated generated 폴더 1 import {personcard person} from ' / generated /personcard person graphql'; personcardprops 유형 내에 사람을 추가하세요 1 type personcardprops = { 2 person personcard person; 3 }; personcard의 props 인수에서, 다음으로 구성 요소의 유형을 지정하세요 personcardprops personcardprops 두 구성 요소의 최종 결과는 다음과 같아야 합니다 personrenderer 1 import react from 'react'; 2 import {graphql, queryrenderer} from 'react relay'; 3 import {environment} from ' / / /relay'; 4 import personcard from ' /personcard'; 5 import {view, text} from 'react native'; 6 import {personrendererquery} from ' / generated /personrendererquery graphql'; 7	 8 const personrenderer = () => { 9 const renderpersons = (people personrendererquery\['response']\['people']) => { 10 return people edges map(({node}) => \<personcard person={node} />); 11 }; 12	 13 return ( 14 \<queryrenderer 15 environment={environment} 16 query={graphql` 17 query personrendererquery { 18 people { 19 edges { 20 node { 21 personcard person 22 } 23 } 24 } 25 } 26 `} 27 variables={null} 28 render={({error, props}) => { 29 if (error) { 30 return ( 31 \<view> 32 \<text>{error message}\</text> 33 \</view> 34 ); 35 } else if (props) { 36 return renderpersons(props people); 37 } 38 return ( 39 \<view> 40 \<text>loading\</text> 41 \</view> 42 ); 43 }} 44 /> 45 ); 46 }; 47	 48 export default personrenderer; personcard 1 import react from 'react'; 2	 3 import {createfragmentcontainer, graphql} from 'react relay'; 4	 5 import {view, text} from 'react native'; 6 import {personcard person} from ' / generated /personcard person graphql'; 7	 8 type personcardprops = { 9 person personcard person; 10 }; 11	 12 const personcard = ({person} personcardprops) => { 13 return ( 14 \<view> 15 \<text>name {person name}\</text> 16 \<text>salary {person salary}\</text> 17 \</view> 18 ); 19 }; 20	 21 export default createfragmentcontainer(personcard, { 22 person graphql` 23 fragment personcard person on person { 24 id 25 name 26 salary 27 } 28 `, 29 }); 결론 queryrenderer의 최종 결과는 애플리케이션이 어떻게 추상화될 수 있는지를 보여주었습니다 애플리케이션은 query renderer 내에서 person을 표시할 수 있습니다 personcard에 더 많은 구성 요소가 포함되어 있어도 query renderer가 구축된 방식은 변경되지 않습니다 personrenderer는 쿼리를 쉽게 수행할 수 있는 방법을 보여주기 위해 구축되었으며, back4app 서버의 강력함과 결합되었습니다 다음 가이드에서는 특정 person 객체를 검색하고 해당 속성을 표시하는 방법을 배울 것입니다