GraphQL에 대하여

date
Jun 21, 2022
slug
about-graphql
status
Published
tags
GraphQL
summary
GraphQL에 대해 알아보자 🙄
type
Post
Updated At
Aug 1, 2022 01:18 AM
Created At
Jun 21, 2022 09:02 AM

시작하며

이번에 이직을 하게되면서 GraphQL을 다루게 되었다. GraphQL에 대해서 실제로 다뤄 본 적이 없다보니 공부 하면서 적어본다. 실제 적용하는 부분은 나중에 작성해보고 지금은 개념적인 부분에 대해서 이해해보려고 한다.
실제 문법적인 부분들은 또 공식 문서에 정확하게 자세하게 나와있으니 그걸 참고하면 된다.

개념

GraphQL은 페이스북에서 만든 데이터를 효율적으로 가져올 수 있도록 만든 쿼리 언어다. GraphQL에 대해서 이해하기 위해서는 기존에 이미 알고 있던 여러 개념과 비교해가며 이해하면 조금 더 쉽게 이해할 수 있을 것 같다.

GraphQL과 SQL

이름에서도 알 수 있듯이 GraphQL은 우리가 DB를 다룰 때 사용하는 SQL과 마찬가지로 쿼리 언어이다. 이때 말하는 쿼리언어는 데이터베이스를 다룰 때 사용하는 언어를 말하는데, 이 둘의 차이점이라면 sql의 경우에는 데이터베이스에 저장된 데이터를 가져오는 것이 목적이고 gql의 경우에는 웹 클라이언트가 서버로부터 데이터를 효율적으로 가져오는것이 목적이다.

GraphQL과 REST API

gql이 웹 클라이언트가 서버로부터 데이터를 가져오는 기능을 위해 만들어진 언어라면, 기존에 사용해왔던 REST API와의 차이점은 무엇이 있는지 알아보자.
REST API의 경우에는 URL과 메서드(GET, PUT, POST, DELETE 등)을 조합하여 다양한 Endpoint를 가지고 있는 반면에 gql은 단 하나의 Endpoint만 존재하고, 해당 API에서 가져오고자 하는 데이터를 쿼리를 통해 가져오는 형태로 이루어진다.
이러한 차이점 덕분에 REST API를 통해 데이터를 가져오게 될 때에는 불필요한 데이터도 한꺼번에 받게되는 Over-fetching이나 여러 endpoint를 통해 데이터를 가져오는 Under-fetching 문제를 해결 할 수 있다.

구조

쿼리/뮤테이션 (query/mutation)

쿼리를 통해 데이터를 조회하고 뮤테이션을 통해 데이터를 조작하는 형태로 규약을 정해두었다.
쿼리의 구조는 다음과 같이 이루어지고, 이에 따른 응답도 쿼리의 구조와 비슷한 형태이다.
{
	people {
		name
		age	
	}
}
쿼리문
{
	"data" : {
		"people" : {
			"name" : "lee sang min",
			"age" : 10
		}	
	}
}
응답
mutation {
	addPeople(name: "more than min"){
		name
	}
}
뮤테이션

스키마(schema)

위에 설명한 쿼리나 뮤테이션을 그냥 바로 사용할 수는 없다. 어딘가에 정의를 해주어야하는데 그게 바로 스키마이다. schema.graphql 에 작성하게 되고, 사용할 쿼리나 뮤테이션, 그리고 타입 등을 정의한다. 쉽게말해 사용할 데이터에 대한 설명을 스키마에 작성한다고 보면 된다.
type People {
	id: Int!
	name: String!
	age: Int
}

type Query {
	peoples(limit: Int, age: Int): [People]!
	people(id: Int!): People
}
type Mutation {

}

...
스키마 예시
사용하고자 하는 쿼리나 뮤테이션은 반드시 type Querytype Mutation안에 작성해주면 된다.

리졸버 (resolver)

리졸버는 실제 작성한 스키마에 대해서 기능을 구현하는 것을 말한다. 스키마에 정의한 필드의 함수를 하나씩 구현하는 것이라고 생각하면 된다. 데이터를 가져오는 과정을 직접 구현해야한다는 번거로움이 있을 수는 있겠지만, 이로 인해 data의 source의 상관없이 구현이 가능하다. REST API로 구현되어있는 open api에서 가져올 수도 있고, 일반 파일 등에서도 가져올 수 있다.
import { getPeople } from "./db";

const resolvers = {
  Query:{
    people: (_, {name}) => getUser(name)
  }
}

export default resolvers;
리졸버 예시

인트로스펙션 (introspection)

기존의 REST API 형태에서는 API 명세서를 주고 받는 절차가 반드시 필요했다. 하지만 이러한 요소는 프로젝트 관리 측면에서 관리해야할 요소가 증가하므로 생산성에 저하가 발생하기 마련이다.
이러한 REST API에서의 API 명세서의 역할이 바로 gql의 인트로스펙션 기능이다. 해당 기능을 사용하면 서버에 정의된 스키마의 정보를 볼 수 있고, 그에 맞게 쿼리문을 작성 하면 된다.

어떻게 사용할까

앞서 설명 했듯 gql자체는 쿼리언어이기 때문에 이를 실제로 사용하기 위해서는 여러 라이브러리를 사용하는 것이 적합하다. 대표적으로 Apollo와 Relay가 있는데 장단점을 잘 비교하여 사용하면 될 것 같다.
실제 클라이언트에서 적용하는 것은 다음에 해보도록 하자.

마치며

react에서 gql과 apollo를 사용하면 기존의 flux 아키텍쳐 기반인 redux를 완전히 대체 할 수 있다고 하는데… 한번 실제로 사용해보면서 어떠한 차이점이 있고 또 장단점은 뭐가 있을지 비교해보면 좋을 것 같다. 또 보안적인 측면에서는 조금 더 취약할 수도 있다는 생각이 드는 것 같은데 이 부분도 한번 살펴보면 좋을 것 같다.

reference