GraphQL 사용하기

hzn·2022년 12월 1일
0

HTTP / 네트워크

목록 보기
7/9
post-thumbnail
post-custom-banner

1. GraphQL 라이브러리 설치

  • graphQL의 쿼리를 로컬 환경에서 수행할 수 있는 라이브러리를 설치
npm install @octokit/graphql

2. GraphQL 라이브러리 불러오기

import { graphql } from "@octokit/graphql";

3. 토큰 발급

  • 요청 시 Github에 접근 가능하도록 토큰 발급

Settings > Developer settings > Personal access tokens

  • Generate new token으로 토큰 발급

4. .env 파일에 토큰 저장하고 불러오기

.env

REACT_APP_GHP_TOKEN=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
  • .env 파일은 수정 후에 반드시 npm run start를 껐다가 새로 해야 한다

App.js

function App() {
  const ghpToken = process.env.REACT_APP_GHP_TOKEN;

5. 쿼리 요청 작성

  • 요청할 수 있는 쿼리(repository, viewer)그 안에 들어갈 수 있는 Field들, 인수(onwer, name, first)
    👉🏽 해당 프로젝트 API 문서에 지정돼 있을 것
  • 여기서는 Github에서 제공하는 GraphQL API를 이용했다.

Github GraphQL API 문서 > 참조 > 쿼리

  • 요청할 수 있는 쿼리(repository, viewer 등) 목록이 나와있음
  • Arguments 항목 : 해당 쿼리 요청할 때 인자로 들어갈 수 있는 것들

  • Type 항목 (Repository 또는 User!) 클릭하면 해당 쿼리 안에 들어갈 수 있는 Field 목록으로 이동 (또는 GraphQL API 문서 > 참조 > Object)

Github GraphQL API 문서 > 참조 > Object

  • 해당 타입 안에 들어갈 수 있는 Fields 목록(과 그 Field의 인자(Argument))이 나와있다.

1) 기본형

// 쿼리 요청 함수 
  async function getRepository() {
    const { repository } = await graphql(
      `
        {
          repository(owner: "codestates-seb", name: "agora-states-fe") {
            discussions(first: 10) {
              edges {
                node {
                  title
                  url
                  author {
                    resourcePath
                  }
                }
              }
            }
          }
        }
      `,
      {
        headers: {
          authorization: `token ${ghpToken}`,
        },
      }
    );
    return repository;
  }

// 첫 렌더링 시 데이터 가져오기
  useEffect(() => {
    getRepository().then((res) => {
      setData(res.discussions.edges);
      console.log(res);
      setIsLoading(false);
    });
  }, []);

응답(res) 들어오는 형태

2) 헤더, 변수와 함께 쿼리 넘기는 경우

  • 필드(인자) {...} : 해당 필드 중 해당 인자(값)에 부합하는 것만 가지고 오겠다는 의미...
 async function getRepository() {
    const { repository, viewer } = await graphql({ // 각 쿼리의 리턴값 각각 받아옴
      headers: {
        authorization: `token ${ghpToken}`,
      },
      owner: 'codestates-seb',
      name: 'agora-states-fe',
      num: 10,
      query: `query recentRepos($owner: String!, $name: String!, $num: Int!) {
        repository(name: $name, owner: $owner) {
          discussions(first: $num) {
            edges {
              node {
                category {
                  name
                }
                author {
                  login
                  avatarUrl
                }
                createdAt
                title
                id
                url
                answer {
                  author {
                    login
                    avatarUrl
                  }
                  bodyHTML
                  createdAt
                  id
                }
              }
            }
          }
        },
        viewer {
          login
          avatarUrl
        }
      }`,
    });
    return { repository, viewer };
  }

  useEffect(() => {
    getRepository().then((res) => {
      setData(res.repository.discussions.edges);
      console.log(res); // res 어떻게 들어오는지 찍어보기
      console.log(res.viewer);
      setIsLoading(false);
    });
  }, []);

응답(res) 들어오는 형태


6. 전체 코드

1) 기본형

import { graphql } from '@octokit/graphql';
import { useState, useEffect } from 'react';

function App() {
  const [data, setData] = useState();
  const [isLoading, setIsLoading] = useState(true);
  const ghpToken = process.env.REACT_APP_GHP_TOKEN;

  console.log(ghpToken);

  async function getRepository() {
    const { repository } = await graphql(
      `
        {
          repository(owner: "codestates-seb", name: "agora-states-fe") {
            discussions(first: 10) {
              edges {
                node {
                  title
                  url
                  author {
                    resourcePath
                  }
                }
              }
            }
          }
        }
      `,
      {
        headers: {
          authorization: `token ${ghpToken}`,
        },
      }
    );
    return repository;
  }

  useEffect(() => {
    getRepository().then((res) => {
      setData(res.discussions.edges);
      console.log(res.discussions.edges);
      setIsLoading(false);
    });
  }, []);

  return (
    <div className="App">
      {isLoading
        ? 'Loading...'
        : data.map((el, index) => {
            return (
              <li key={index}>
                <a href={el.node.url}>{el.node.title}</a>
                <span>{el.node.author.resourcePath}</span>
              </li>
            );
          })}
    </div>
  );
}

export default App;

2) 헤더, 변수와 함께 쿼리 넘기는 경우

import { graphql } from '@octokit/graphql';
import { useState, useEffect } from 'react';

function App() {
  const [data, setData] = useState();
  const [isLoading, setIsLoading] = useState(true);
  const ghpToken = process.env.REACT_APP_GHP_TOKEN;

  console.log(ghpToken);

  async function getRepository() {
    const { repository, viewer } = await graphql({
      headers: {
        authorization: `token ${ghpToken}`,
      },
      owner: 'codestates-seb',
      name: 'agora-states-fe',
      num: 10,
      query: `query repository($owner: String!, $name: String!, $num: Int!) {
        repository(name: $name, owner: $owner) {
          discussions(first: $num) {
            edges {
              node {
                category {
                  name
                }
                author {
                  login
                  avatarUrl
                }
                createdAt
                title
                id
                url
                answer {
                  author {
                    login
                    avatarUrl
                  }
                  bodyHTML
                  createdAt
                  id
                }
              }
            }
          }
        },
        viewer {
          login
          avatarUrl
        }
      }`,
    });
    return { repository, viewer };
  }

  useEffect(() => {
    getRepository().then((res) => {
      setData(res.repository.discussions.edges);
      console.log(res);
      console.log(res.viewer);
      setIsLoading(false);
    });
  }, []);

  return (
    <div className="App">
      {isLoading
        ? 'Loading...'
        : data.map((el, index) => {
            return (
              <li key={index}>
                <a href={el.node.url}>{el.node.title}</a>
                <span>{el.node.author.resourcePath}</span>
              </li>
            );
          })}
    </div>
  );
}

export default App;
post-custom-banner

0개의 댓글