티스토리 뷰

do/graphQL

React + Apollo + GraphQL

dooo.park 2020. 7. 21. 14:49

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/

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함