React + Apollo Tutorial (2) - Queries: Loading Links
이 글은 다음 페이지를 번역한 글입니다.
https://www.howtographql.com/react-apollo/2-queries-loading-links/
Queries: Loading Links
Preparing the React components
앱에서 구현할 첫 번째 기능은 Link 엘리먼트의 목록을 로드하고 표시하는 것입니다. React 컴포넌트 계층 구조를 따라 올라가서 단일 링크를 렌더링할 컴포넌트부터 시작하겠습니다.
components 디렉토리에 Link.tsx라는 새 파일을 만들고 다음 코드를 추가합니다:
import React from 'react'; interface LinkProps { link: { description: string; url: string }; } const Link = ({ props }: LinkProps) => { return ( <div> <div> {link.description} ({link.url}) </div> </div> ); }; export default Link;
이것은 props로 link를 받고 link의 description과 url을 렌더링하는 간단한 React 컴포넌트입니다. 식은 죽 먹기죠?!
다음으로 링크 목록을 렌더링하는 컴포넌트를 구현해 보겠습니다.
다시 components 디렉토리에서 LinkList.tsx라는 새 파일을 만듭니다. 그리고 아래와 같이 코드를 작성합니다:
import React from "react"; import Link from "./Link"; const LinkList = () => { const linksToRender = [ { id: "1", description: "Prisma gives you a powerful database toolkit 😎", url: "https://prisma.io", }, { id: "2", description: "The best GraphQL client", url: "https://www.apollographql.com/docs/react/", }, ]; return ( <div> {linksToRender.map((link) => ( <Link key={link.id} link={link} /> ))} </div> ); }; export default LinkList;
여기서는 컴포넌트 설정이 작동하는지 확인하기 위해 로컬 모의 데이터(local mock data)를 사용하고 있습니다. 우리는 곧 이것을 서버에서 로드된 실제 데이터로 대체할 것입니다 - 인내심을 가지세요, 어린 Padawan!
설정을 완료하려면 App.tsx를 열고 코드를 다음과 같이 작성해보세요.
import React from "react"; import LinkList from "./LinkList"; function App() { return <LinkList />; } export default App;
지금까지 모든 것이 작동하는지 확인하기 위해 앱을 실행하세요! 이제 앱은 linksToRender 배열로부터 두 개의 링크를 표시해야 합니다.
Writing the GraphQL query
이제 데이터베이스에 저장된 실제 링크를 로드해 보겠습니다. 이를 위해 가장 먼저 해야 할 일은 API에 보낼 GraphQL 쿼리를 정의하는 것입니다.
쿼리는 다음과 같습니다:
{
feed {
id
links {
id
createdAt
description
url
}
}
}
우리는 Playground에서 이 (애플리케이션 스키마에 대한) 쿼리를 간단히 실행하고 GraphQL 서버에서 결과를 검색할 수 있습니다. 그런데 이걸 어떻게 타입스크립트 코드 안에서 사용할 수 있을까요?
Queries with Apollo Client
Apollo Client로 쿼리를 만드는 가장 일반적이고 (아마도 가장 유연한) 방법은 Apollo Client가 제공하는 useQuery hook을 사용하는 것입니다. useQuery hook를 이용하면, GraphQL 쿼리 문서를 전달했을 때 Apollo가 가져오기(fetching)를 처리하고 반환된 데이터와 오류를 표시합니다.
LinkList.tsx를 열고 파일 상단에 쿼리를 추가합니다:
...
import { useQuery, gql } from "@apollo/client";
const FEED_QUERY = gql`
{
feed {
id
links {
id
createdAt
url
description
}
}
}
`;
...
다음으로, 하드코딩된 linksToRender 배열을 반복(iterate)하는 대신 FEED_QUERY 쿼리 문서를 useQuery로 전달하고 반환된 링크를 반복합니다.
const LinkList = () => { const { data } = useQuery(FEED_QUERY); return ( <div> {data && ( <> {/* 아직 이 부분에서 타입을 어떻게 정의해야 할 지 모르겠습니다. 조만간 수정하겠습니다. */} {(data.feed.links as any[]).map((link) => ( <Link key={link.id} link={link} /> ))} </> )} </div> ); };
잠시 시간을 가지고 이 새로운 코드에서 어떤 일이 일어나는지 살펴보겠습니다.
FEED_QUERY 변수는 gql을 사용합니다. gql이란 tagged template literals를 사용하여, 우리가 정의한 GraphQL 쿼리 문서를 파싱하는 라이브러리입니다. gql을 통해 파싱된 쿼리 문서는 LinkList 컴포넌트의 useQuery hook으로 전달됩니다.
useQuery는 이 시점에서 우리의 목적과 관련된 세 가지 항목을 반환합니다.
- loading: 요청(request)이 계속 진행 중이고 응답(response)이 수신되지 않은 한 true입니다.
- error: 요청이 실패하는 경우, 이 필드에는 정확히 무엇이 잘못되었는지에 대한 정보가 포함됩니다.
- data: 서버로부터 받은 실제 데이터입니다. Links 엘리먼트의 목록을 나타내는 Link 프로퍼티가 있습니다.
주입된 props에는 실제로 더 많은 기능이 포함되어 있습니다. API overview에서 자세한 내용을 읽을 수 있습니다.
LinkList 컴포넌트가 처음에 렌더링될 때는 data 변수에 대한 정보가 없습니다. 이러한 이유로 데이터에서 나올 링크를 렌더링하기 전에 data에 값이 들어있는지 확인해야 합니다. GraphQL 요청이 데이터를 받음으로써 리졸브되면, LinkList 컴포넌트가 다시 렌더링되고 데이터가 참 값이 됩니다. 우리의 링크(links)는 렌더링을 위해 map 함수를 실행하는 data.feed.links에서 사용할 수 있습니다.
이게 전부입니다! 모의 데이터를 사용했을 때와 똑같은 화면이 표시되어야 합니다(만약 데이터베이스에 어떤 데이터도 추가하지 않았다면).
참고: http://localhost:4000의 브라우저에 오류만 표시되고 비어있다면, 서버를 실행하는 것을 잊은 것일 수도 있습니다. 앱이 작동하려면 서버도 실행되어야 합니다. 따라서 터미널에 두 개의 실행 중인 프로세스가 있어야 합니다. 하나는 서버용이고 다른 하나는 React 앱용입니다. 서버를 시작하려면 server 디렉토리로 이동하여 yarn start를 실행하십시오.