티스토리 뷰
1. Apollo
React에서 GraphQL API를 호출하기 위해 Apollo Client가 제공하는 Apollo Hooks를 사용했다.
Apollo Hooks?
기존 react-apollo 패키지에서 HOC(Higher Order Components)를 사용한 <Query/>나<Mutation/>을 통해
GraphQL API를 호출하는 방법에서 React Hooks를 도입하여 useQuery, useMutation과 같은 함수로 GraphQL API를
호출하는 새로운 방법
○ @apollo/react-hooks 패키지를 사용하며, 클래스 대신 함수형 컴포넌트를 사용하게 되어 코드의 가독성과 유지보수에 대한 이점이 있다.
Apollo Client 사용하기
1. 패키지 설치
React 프로젝트에 Apollo Client와 GraphQL 패키지들을 설치한다.
$ npm install @apollo/react-hooks apollo-cache-inmemory apollo-client apollo-link-http graphql graphql-tag
2. Apollo Client 생성
apollo-client 패키지의 ApolloClient 생성자를 통해 Apollo Client를 생성한다.
○ link : GraphQL API의 endpoint HttpLink 객체
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { createHttpLink } from 'apollo-link-http';
const client = new ApolloClient({
link: createHttpLink({ uri: "GraphQL API URI" }),
cache: new InMemoryCache()
});
3. 연결
ApolloClient를 React에 연결한다.
모든 컴포넌트에서 GraphQL API 호출을 하기 위해 최상단의 App 컴포넌트를 ApolloProvider로 wrapping 해주었다.
import React from 'react';
import App from './App';
import client from "./apollo";
import {ApolloProvider} from "@apollo/react-hooks";
ReactDOM.render(
<ApolloProvider client={client}>
<App/>
</ApolloProvider>
, document.getElementById('root')
);
4. GraphQL API 호출
graphql-tag 패키지의 gql을 사용하여 자바스크립트 문자열을 GraphQL 구문으로 변환한 뒤,
@apollo/react-hooks의 useQuery 함수에 변환된 쿼리를 인자로 넘겨서 GraphQL API를 호출한다.
-
useQuery 함수는 기본적으로 비동기함수며 data, loading, error를 리턴한다. useMutation, useSubscription도 동일하며, 이를 이용하여 쉽게 예외처리를 할 수 있다. ※ 참고 :https://www.apollographql.com/docs/react/data/queries/
-
@apollo/react-hooks의 함수형 컴포넌트 방식
import React from 'react'
import gql from 'graphql-tag';
import { userQuery } from '@apollo/react-hooks';
const GET_USER = gql`
query user($idx:Int!){
user(idx: $idx) {
idx
name
email
}
}
`;
function User() {
const { loading, error, data } = useQuery(GET_USER, {variables: {idx: id}});
if (loading) return <p>Loading...</p>;
if (error) return <p>Error!(</p>;
return (
<p>{data.name}, {data.email}</p>
);
}
export default User;
- 기존 react-apollo 패키지의 HOC 방식
import React from "react";
import { gql } from "apollo-boost";
import { Query } from "react-apollo";
const GET_USER = gql`
query user($idx:Int!){
user(idx: $idx) {
idx
name
email
}
}
`;
function User() {
return (
<>
<Query query={GET_USER} variables={{idx: id}}>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error!(</p>;
return (
<p>{data.name}, {data.email}</p>
);
}}
</Query>
</>
);
}
export default User;
2. GraphQL
GraphQL은 페이스북이 2012년에 개발하여 2015년에 공개적으로 발표된 데이터 질의어이다.
GraphQL은 REST 및 부속 웹서비스 아키텍쳐를 대체할 수 있다.
클라이언트는 필요한 데이터의 구조를 지정할 수 있으며, 서버는 정확히 동일한 구조로 데이터를 반환한다.
GraphQL은 사용자가 어떤 데이터가 필요한 지 명시할 수 있게 해 주는 강타입 언어이다.
이러한 구조를 통해 불필요한 데이터를 받게 되거나 필요한 데이터를 받지 못하는 문제를 피할 수 있다.
REST API와 GraphQL API의 차이
-
REST API를 사용할 때에는 특정 엔드포인트를 통하여 데이터를 불러오게 된다.
클라이언트의 요구 사항은 접근하는 해당 API를 호출하는 URL에 작성한다. -
GraphQL은 단 하나의 엔드포인트만을 노출시킨다.
필요한 데이터를 서버에 알려주기 위하여 클라이언트가 보다 많은 정보를 보내야 한다.
따라서 클라이언트 측에서 필요한 데이터를 결정할 수 있다. 여기서 클라이언트가 보내는 정보를 쿼리라고 한다.
문법
GraphQL의 문법은 Query, Mutation, Subscription의 세 가지 종류가 있다.
GraphQL에 대한 자세한 내용은 https://graphql.org/ 에서 확인할 수 있다.
- Query : 데이터를 받아올 때 사용 → REST의 "GET" 역할
- Mutation : 데이터를 생성, 수정, 삭제할 때 사용 → REST의 "POST, PUT, PATCH, DELETE" 역할
- Subscription : 웹소켓을 사용해 실시간 양방향 통신을 구현할 때 사용
GraphQL 사용하기(server)
1. GraphQL 스키마 작성
GraphQL에서 사용할 스키마를 작성한다.
-
스키마(Schema)는 GraphQL API가 할 수 있는 행위를 정해주고, 클라이언트가 데이터를 요청하는 방법을 정의하다.
-
대부분의 경우 스키마는 GraphQL 타입들의 집합이다.
하지만 API를 위한 스키마를 작성할 때는, 아래와 같은 특별한 루트 타입이 존재한다.
type Query { ... }
type Mutation { ... }
type Subscription { ... }
Query, Mutation, Subscription 타입은 클라이언트가 보내는 요청을 위한 진입점이다.
-
The Schema Definition Language (SDL)
GraphQL은 API의 스키마를 정의하기 위한 고유의 타입 시스템을 갖추고 있다.
스키마를 작성하는 문법을 스키마 정의 언어(SDL)라고 한다. -
GraphQL은 반드시 JSON으로만 요청과 응답을 실행한다.
요청한 쿼리 JSON과 동일한 형태의 JSON으로 응답한다.
useQuery를 사용할 Query 타입과, 주고 받을 사용자 정의 타입(JSON)을 정의한다.
2. GraphQL 서버 환경 설정 & Resolver 함수 작성
- index.js
GraphQL 서버를 설정한다.
여기서는 graphql-yoga라는 패키지를 사용했는데, graphql-yoga는 GraphQL 서버를 쉽게 실행시켜주는 도구다.
const { GraphQLServer } = require('graphql-yoga');
const { UserResolvers } = require("./resolvers/UserResolvers");
const { typeDefs } = require("./Type");
const resolvers = {
Query: {
user: UserResolvers.user,
}
};
const server = new GraphQLServer({
typeDefs,
resolvers
});
server.start(options,() => console.log(`Server address: http://localhost:4000`));
-
graphql-yoga를 통해 서버를 띄운 뒤, localhost:4000으로 접속하면 GraphQL Playground라는 GraphQL IDE를 사용할 수 있다.
(GraphQL Subscriptions, interactive docs & collaboration) https://github.com/prisma-labs/graphql-playground -
UserResolver.js
실제 GraphQL API 호출 시 처리할 서비스 로직을 작성한다.
여기서는 Sequelize ORM을 통해 User를 찾는 서비스를 작성했다.
const { User } = require("../db");
const UserResolvers = {
user: async(_, args) => {
const idx = args.idx;
const user = User.findByPk(idx);
return user;
}
};
module.exports = {
UserResolvers
};
3. GraphQL API 호출
GraphQL의 엔드포인트로 쿼리를 전송한다. (위에서는 localhost:4000)
-
Client에서 useQuery를 통한 호출
-
GraphQL 서버의 PlayGround IDE에서 호출 Test
-
지금까지의 프로젝트 구조를 간단히 정리하면 아래과 같다.
GraphQL 서버에 DB를 연결할 때 ORM은 Sequelize를 사용했는데, Prisma도 많이 사용되고 있다. https://www.prisma.io/