프로듀스48과 함께하는 GraphQL(그래프큐엘)

최근에 새로운 프로젝트를 시작했는데 간단한 프로토타이핑을 위해 빠르고 쉽게 개발할 수 있는 스택을 찾아보게 되었습니다. 저는 주로 javascript로 개발을 했기 때문에 프론트는 react를, 서버사이드에는 express를 사용하기로 정했죠.

그런데 개발을 하다보니 RESTful API를 구성하는것이 너무너무 귀찮았습니다. 필요에 따라서 endpoint를 파는게 정말 귀찮더군요.. 무언가 나은 방안이 없을까? 라는 질문을 가지고 검색해보니 GraphQL을 알게되었습니다.

GraphQL의 개념을 훑고나니 “헐! 이거면 내 귀차니즘을 해결해주겠구만!” 라는 생각을 가지게 되었고, 프로젝트에 활용하게 되었습니다. 대체 GraphQL이란 무엇일까요?

기본 개념

GraphQL이란 간단히 말하면, 데이터를 요청하는 방법을 정의한 문법입니다. 일반적으로 클라이언트가 서버에 데이터를 요청할 때 사용하게 되죠.

GraphQL은 이런 특징이 있습니다.

  1. 필요한 데이터만 요청할 수 있다.
  2. 한번의 요청으로 여러 리소스의 데이터를 전송받을 수 있다.
  3. 타입 시스템(type system)을 활용하여 데이터를 정의한다.

그러면 GraphQL은 어떤 이유로 탄생하게 되었고, 어째서 이런 특성을 가지게 되었을까요? 함께 살펴보시죠.

탄생 배경

최근 몇 년간은 클라이언트와 서버, 또는 서버와 서버 간의 통신에 REST API를 활용해 왔습니다. 하지만 이를 사용하다보면 몇가지 문제를 겪을 수 있습니다.

예를 들어 프로듀스 48의 연습생 리스트와 댓글을 확인할 수 있는 페이지를 만든다고 가정하겠습니다.

위와 같은 페이지의 데이터를 조회하기 위해 다음과 같이 REST API를 구성할 수 있습니다. 이 API로 연습생들(trainees)의 리스트를 조회하고 각 연습생(trainee)에 대한 정보들(name, agency) 과 댓글( comments) 리스트를 조회할 수 있습니다.

연습생 정보와 댓글 리스트 API

이번에는 댓글을 제외한 단순한 연습생 리스트 페이지를 만들고자 합니다.

그런데 위와 같은 페이지에서 위에서 구성한 API를 활용한다면 불필요한 데이터까지 요청하게 됩니다. 이런 상황을 피하기 위해 새로운 API를 추가로 구성해야 합니다.

연습생 정보 단순 리스트 API

이와 같이 간단한 예제에서도 API가 두 가지 다른 API로 분리될 수 있습니다. 복잡한 웹 서비스의 경우라면, 생성해야 할 endpoint의 수는 끝도없이 늘어나게 됩니다. 수 많은 API endpoint를 관리하기는 쉽지 않습니다.

여기서 또 한 가지 문제가 발생할 수 있습니다. 만약 연습생 데이터와 댓글 데이터가 서로 다른 리소스에 저장되어 있다면, 이를 위해 클라이언트는 여러 네트워크 요청을 생성해야 합니다. 이는 네트워크 오버페칭(overfetching)으로 이어질 가능성이 높죠.

이와같이 전통적인 RESTful API에서 발생할 수 있는 문제들을 해결하기 위해 페이스북은 2012년에 GraphQL을 오픈소스로 공개했습니다.

문제점 해결

페이스북이 공개한 GraphQL은 위의 문제를 “불필요한 여러 API를 두지말고, 필요한것만을 요청할 수 있는 하나의 API만을 두자”라는 방식으로 해결합니다.

GraphQL에서 데이터를 요청하는 방식을 간략히 살펴보도록 하겠습니다. 프로듀스 48의 연습생 데이터를 GraphQL문법으로 다음과 같이 요청할 수 있습니다.

GraphQL 연습생 데이터 query

위의 GraphQL 문법은 trainees 리스트를 조회하고 각 리스트 아이템의 name , agency , comments 를 조회합니다. 위 query를 GraphQL 서버에 요청하면 다음과 같은 데이터를 전달 받습니다.

GraphQL 서버의 응답 데이터

GraphQL query 에서 요청한 필드와 그 형태와 같은 구조의 데이터가 반환됩니다. 이와같이 원하는 데이터 필드를 요청할 수 있고, 응답 데이터의 구조를 예상할 수 있습니다.

이번에는 댓글을 제외한 연습생의 리스트를 조회해보겠습니다.

댓글을 제외한 연습생 리스트 조회하기

이번 query에는 단순히 trainees 리스트의name, agency 필드만을 요청했습니다.

댓글을 제외한 연습생 리스트

그랬더니 위와같이 요청한 query의 형태 그대로 구성된 데이터가 응답으로 돌아왔습니다.

이렇게 GraphQL을 활용하면 기존의 RESTful API와 같이 여러 endpoint로 나눌 필요없이, 하나의 GraphQL API endpoint 에 대해 필요한 데이터를 요청하기만 하면 됩니다. 완전 편하죠! 😝

로직 작성하기

GraphQL서버에 대해 query를 요청하면 그에 알맞은 데이터가 반환됩니다. 하지만 이때 데이터가 반환되는것은 마법처럼 자동적으로 되지 않습니다. 저희가 직접 로직을 작성해야죠!

GraphQL에서는 resolver 에 이 로직을 작성할 수 있습니다. Resolver란, query에서 특정 필드에 대한 요청이 있을 때, 그것을 어떤 로직으로 처리할지 GraphQL에게 알려주는 역할을 합니다.

저희의 프로듀스 48 예제에서는 다음과 같이 resolver를 작성할 수 있습니다.(node.js 기준으로 작성했습니다.)

먼저, 가장 최상위의 trainees 필드의 로직은 Query 에 작성합니다. 왜냐하면 trainees 필드는 루트(root) 레벨에서 직접 부를 것이기 때문이죠.

그 다음, 서브 필드(subfields)의 resolver를 순차적으로 작성했습니다. trainees가 반환하는 Trainee의 각 필드를 Trainee 객체에 작성했죠. 이때 Traineecomments 필드를 반환하기 위해 Comment 객체의 resolver도 함께 작성합니다.

이와 같이 resolver를 작성함으로써, 각 필드가 처리할 로직과 반환할 데이터의 종류를 지정할 수 있습니다.

정리하며

GraphQL은 REST API를 완전히 대체하기 위한 기술이라기 보다는 몇몇 발생 가능한 문제를 해결할 수 있는 한가지 방법중의 하나입니다. 천천히 살펴보시고 이를 활용하기에 적당한 프로젝트에 사용하시면 될 것 같습니다.

저는 개인적으로 프론트엔드 개발의 입장에 보았을 때 GraphQL이 굉장히 매력적입니다. 특히 컴포넌트 단위로 코드를 모듈화 하는 리액트 개발에 있어서 여러가지 API에 요청을 생성하는 것 대신에, 컴포넌트에 필요한 데이터만을 요청하는 GraphQL이 훨씬 더 코드를 간결하게 만듭니다. 귀찮은 일이 훨씬 줄어들어요!

처음에는 GraphQL이 복잡하고 어려워보일 수 있지만, 차분히 개념을 살피고 해결하고자 하는 문제를 이해하면 쉽게 활용하실 수 있을거에요. 👍

읽어 주셔서 감사합니다! 이 글이 도움이 될 만한 분에게 공유해주시고, 박수를 (50번)쳐주시면 정말 힘이 날 겁니다! 😝