Web/[JS] Common

GraphQL 4 - Wrapping REST API

ihl 2021. 2. 17. 00:21

  기존 REST API를 GraphQL로 감싸는 방법은 다음과 같다. 이를 실습을 통해 직접 알아보자.

  1. 기존 REST API의 정보를 기반으로 스키마를 만든다.
  2. 기존 REST API에 정보를 요청하고 이를 반환하는 함수를 만든다.
  3. GraphQL의 리졸버에 2에서 만든 함수를 연결한다. 

 

1. 스키마 작성

  기존 API를 기반으로 스키마를 작성하여야한다. 나는 Tour API의 searchKeyword 에서 검색 부분을 GraphQL로 감싸보기로 하였다. searchKeyword의 응답메시지는 다음과 같다.

 

Tour API 응답 메시지

  Tour API의 응답 메시지는 위와 같다. 이 항목들을 모두 포함한 데이터가 GraphQL의 응답이 될 것이다. 원래라면 위 항목을 모두 스키마로 표현해야하지만 나의 경우 연습을 위한 것이므로 몇 가지 항목을 제외한 나머지 부분만 사용할 것이다. 

 

type Sight {
  contentid:Int!
  contenttypeid: Int!
  homepage:String
  tel:String
  title:String!
  firstimage:String
  addr1:String!
  addr2:String
  mapx:Float
  mapy:Float
  overview:String
}

Tour API의 응답메시지는 스키마에서 위와 같은 Sight라는 커스텀 타입으로 표현할 수 있다. 방법은 항목들의 이름과 리턴형을 매칭시켜 Sight라는 새롭게 정의한 타입에 묶어주기만하면 된다. 이 Sight란 타입은 작성할 쿼리의 리턴형식에 사용될 것이다.

 

Tour API의 요청 메시지

이번엔 요청메시지를 보고 쿼리를 작성해보자. 요청메시지 또한 몇 가지 항목을 제외한 나머지 부분만 사용하였다.

 

type Query {
  sights(city: Int, district:Int, keyword:String, numOfRows:Int, pageNo:Int):[Sight]
}

위 정보를 기반으로 sights라는 쿼리를 만들었다. 이 쿼리는 지역과 키워드를 입력하면 해당하는 관광지의 목록을 반환해주는 쿼리이다. 따라서 요청 메시지에서 가져온 지역과 키워드라는 조건은 쿼리 이름(sights) 옆에 괄호로 묶어 표현해주었다. 그리고 쿼리의 결과는 관광지 목록이므로 이전에 만든 Sight 타입에 대괄호를 붙여 Sight의 배열을 리턴할 것을 명시해주었다.

 

2. REST API Request

  GraphQL의 쿼리 결과는 기존 REST API에서 얻을 수 있으므로 쿼리가 발생할 때마다 REST API에 데이터를 요청하고 결과를 GraphQL로 반환하여야 한다. 즉, 기존 REST API에 요청하는 함수가 필요한 것이다.

 

import axios from "axios";

export const getSights = async (city = "", district = "", keyword = "", numOfRows = 6, pageNo = 1) => {
  keyword = encodeURI(keyword);

  let API_URL_BODY = `areaCode=${city}&sigunguCode=${district}&keyword=${keyword}&numOfRows=${numOfRows}&pageNo=${pageNo}`
  let API_URL = API_URL_LIST_HEAD + API_URL_BODY + API_URL_TAIL;

  return await axios(`${API_URL}`)
    .then(res => res.data)
    .then(json => { return json.response.body.items.item })
    .catch(function (error) {
      console.log(error);
    });
}

위 코드는 GraphQL을 통해 받은 요청의 인자들(city, district...)을 사용하여 API에 요청을하고 결과를 반환하는 함수이다. 기존의 REST API에 요청을 날리듯이 작성하면 된다.

 

3. Resolver

import { getSights, getSight } from "./sight-db"

const resolvers = {
  Query: {
    sights: (_, { city, district, keyword, numOfRows, pageNo }) =>
      getSights(city, district, keyword, numOfRows, pageNo)
  }
};

이제 리졸버에서 쿼리와 REST API 요청 함수를 연결시키기만 하면 된다. 연결 방법은 위와 같다. 구조 분해 할당으로 쿼리의 인자를 받아온 후 이를 함수의 인자로 다시 넣어주면 된다.

 

import { GraphQLServer } from "graphql-yoga"
import resolvers from "./graphql/resolvers"

const server = new GraphQLServer({
    typeDefs: "graphql/schema.graphql",
    resolvers
});
server.start(() => console.log('Server is running on localhost:4000'));

참고로 서버 생성부분의 구조는 위와 같다. 서버 생성 시 스키마와 리졸버를 주었기 때문에 이 둘이 연계되어 GraphQL이 작동하는 것이다.

 

결과

작성 후에는 위와 같이 REST API의 데이터를 GraphQL로 받아볼 수 있다!

 

 


참고 영상:

www.youtube.com/watch?v=LP9Y35D4x_8