컨텐츠 바로가기

07.08 (월)

"API를 위한 유연한 쿼리 언어" 그래프QL 제대로 시작하기

댓글 첫 댓글을 작성해보세요
주소복사가 완료되었습니다
페이스북이 개발해 모두가 사용할 수 있도록 오픈소스 표준으로 공개한 그래프QL(GraphQL)은 REST API의 대안을 표방한다. 그래프QL은 REST와 마찬가지로 웹 기반 API를 만들고 소비하는 방법을 제공하지만, 쿼리와 반환된 데이터는 형식 스키마와 유형 시스템을 사용해 일관성을 보장한다.

여기서는 그래프QL API 설계와 구현의 기본 사항을 살펴보고 여러 가지 주요 고려 사항과 이 과정에서 내리게 되는 의사 결정에 대해 알아본다.
ITWorld

ⓒ Tim Gouw/Unsplash

<이미지를 클릭하시면 크게 보실 수 있습니다>



그래프QL 언어와 프레임워크

웹 애플리케이션 API로 그래프QL을 사용할 계획이라면 이미 사용 중인 언어 및 데이터 구성요소가 이를 지원할 가능성이 높다. 그래프QL 라이브러리는 프로덕션에 사용되는 거의 모든 주요 언어에 제공된다. 클라이언트는 C#/닷넷, 고, 자바, 안드로이드, 자바스크립트, 스위프트/오브젝티브 C, 파이썬용으로 제공되며 서버 라이브러리는 그보다 더욱 광범위하게 지원된다.

완전히 새로 시작한다 해도 다른 프로젝트에서 가장 익숙한 언어와 런타임, 데이터 계층을 선택하는 것이 최선이다. 그래프QL은 서버나 클라이언트에 많은 제약을 두지 않으며 데이터베이스를 가리지 않는다. 다만 데이터 계층에 따라 얼마간의 수동 통합이 필요할 수는 있다. (이 부분에 대해서는 다음 섹션에서 더 자세히 살펴본다.)

여기서는 참고용으로 그래프QL의 파이썬 구현을 사용한다. 개념과 기능은 다른 언어에서도 대체로 동일하다.


그래프QL의 데이터 쿼리 스키마

그래프QL은 다양한 계층 구조의 강한 유형의 필드에서 구성된 쿼리를 받는다. 그래프QL API를 만들 때 가장 잘 생각해야 하는 부분은 쿼리에 제공할 스키마다.

많은 경우 쿼리 필드를 기반 데이터 소스에 일 대 일로 매핑해서 쿼리를 위해 데이터베이스(또는 다른 데이터 소스)의 모든 관련 필드를 노출할 수 있다. 그래프QL 쿼리는 REST 쿼리에 비해 훨씬 더 제약이 없고 다양할 수 있으므로 처음부터 쿼리 가능한 필드와 이러한 필드를 데이터베이스에 매핑할 계획을 세워야 한다.

예를 들어, 영화를 위한 데이터베이스 테이블이 있고 이 테이블에 titleyear(정수)가 있다면 다음과 같은 그래프QL을 사용할 수 있다.

type Character {
title: String!
year: Int
}

String 뒤에 나오는 !는 필드가 필수임을 의미하므로, 이 쿼리를 수행하려면 최소한 제목은 필요할 것이다.

또한 그래프QL을 통해 노출하는 필드가 기반 데이터와 정확히 일치하는 유형을 사용하도록 해야 한다. 예를 들어 그래프QL에는 기본 "date" 또는 "datetime" 데이터 유형이 없다. 사용 가능한 구현이 매우 다양하다는 것이 주된 이유다. 날짜 범위에 따른 검색을 허용하려면 API를 통해 가져온 날짜의 서식을 강제하고, 쿼리할 때 이러한 날짜 요청이 백엔드 데이터베이스에 적절한 유형으로 변환되도록 해야 한다.

사용 중인 프레임워크에 따라 이 작업이 이미 이뤄졌을 수도 있다. 파이썬에서 인기 있는 그래프QL 라이브러리인 그래핀(Graphene)은 ISO-8601 형식의 날짜-시간 값을 유형 네이티브로 제공하므로 직접 처리할 필요가 없다.

데이터 집합에 많은 필드가 있다면 복잡한 유형 강제가 불필요한 최소 기능 하위 집합을 노출하는 것부터 시작한다(예를 들어, 간단한 문자열 또는 숫자 쿼리). 그런 다음 사용 중인 그래프QL 커넥터를 통해 쿼리를 구현하는 방법을 파악하면서 사용 가능한 필드를 점진적으로 확대할 수 있다.


그래프QL 데이터 저장과 검색

백엔드에 데이터를 저장하고 검색하려면 일반적으로 사용 중인 언어의 그래프QL 라이브러리에서 지원하는 미들웨어를 사용한다.

많은 경우 일반적인 애플리케이션 프레임워크의 데이터 계층을 통해 그래프QL이 이 작업을 수행하도록 할 수 있다. 예를 들어 파이썬의 그래프QL용 그래핀 라이브러리는 장고(Django) 웹 프레임워크와 함께 장고의 내장된 ORM을 지원한다. 그래핀은 SQL알케미(SQLAlchemy) ORM을 지원하며, 인기 있는 스탈렛(Starlette)과 패스트API(FastAPI) 프레임워크에 대한 지원도 추가됐다. 또한 구글 앱 엔진의 데이터 커넥터, 릴레이 자바스크립트 프레임워크(리액트에 사용됨)와 상호운용이 가능하다.

이런 구성요소에 의해 기술되지 않은 데이터 계층을 사용하는 경우 그래핀의 미들웨어와 DataLoader 객체를 사용해 빈 틈을 채울 수 있다. 이 둘은 데이터 계층에 필요한 통합을 수동으로 연결할 수 있게 해준다. DataLoader를 사용하면 관련 데이터에 대한 여러 개의 통시 요청을 합쳐서 백엔드를 오가는 횟수를 줄일 수 있다.

한편 이 중 어느 것도 애플리케이션의 아무 계층에서 직접 캐싱을 수행하는 것을 막지는 않는다. 예를 들어 반환하는 응답은 프록시를 사용하여 캐시할 수 있고, 백엔드 데이터는 멤캐시드(Memcached) 또는 레디스를 사용해 캐시할 수 있다. 다만 데이터가 변경될 때마다 이러한 캐시를 비우는 작업도 직접 챙겨야 한다.


그래프QL 쿼리와 뮤테이션

그래프QL은 "뮤테이션(mutation) 쿼리"라고 하는 특정 쿼리 형식을 사용해서 데이터 집합에서 요소를 생성, 업데이트하거나 삭제한다. 이러한 쿼리가 작동하는 방식, 즉 어느 쿼리를 허용하고 어느 필드를 요구할지 뿐만 아니라 뮤테이션 후 쿼리에서 어떤 데이터를 반환할지에 대해서도 잠시 생각해 보자.

뮤테이션 쿼리를 설계할 때 원하는 수만큼의 출력 필드를 반환하도록 허용할 수 있다. 그러나 응답 객체를 한두 계층 이상으로 중첩하는 것은 대체로 좋은 생각이 아니다. 그렇게 하면 쿼리 자체를 볼 때, 그리고 결과를 처리하기 위한 코드를 작성할 때 모두 결과를 구문 분석하기가 어렵기 때문이다.

또 다른 중요한 주의 사항은 오랜 REST API 설계 습관이 뮤테이션 쿼리 작성 방식에 영향을 미치지 않도록 하는 것이다. 예를 들어 동일한 객체에 대한 여러 종류의 변경을 처리하기 위해 여러 뮤테이션 쿼리를 만드는 대신(REST에서 일반적인 패턴) 하나의 뮤테이션 쿼리로 통합할 수 있다. 이를 위한 한 가지 방법은 이 예제의 "upvote/downvote"와 같이 별도의 비선택적 필드를 사용해서 가능한 각 작업을 기록하는 것이다.

또 다른 방법은 값 필드와 열거형을 함께 사용해서 이 값으로 원하는 동작을 기술하는 것이다. 열거형의 한 가지 큰 장점은 모호하지 않은 명확성이다. 즉, 열거형을 사용해서 정확하게 의도를 반영할 수 있으므로 고도의 자체 문서화가 가능하다. 어느 언어든 언어의 그래프QL 라이브러리는 대부분 언어 자체의 개념 구현과 일치하는 열거형을 사용할 방법을 제공한다. 예를 들어 파이썬용 그래핀의 그래프QL 열거형은 파이썬 표준 라이브러리 enum 클래스와 상당히 비슷해 보일 수 있다.


그래프QL 캐싱과 성능 가속화

내부적으로 그래프QL 쿼리는 다른 쿼리와 마찬가지로 데이터를 폴링하고 검색한다. 즉, API 쿼리 속도를 높이기 위해 사용되는 많은 방법을 똑같이 사용해서 가속화할 수 있다.
  • 캐싱 : 데이터베이스를 백엔드로 두거나 프론트엔드에서 데이터를 반환하는 모든 서비스는 두 끝단 모두에서 캐싱을 통한 이점을 얻을 수 있다. 단, 이러한 캐시의 만료에 대한 책임은 여러분 각자에게 있음을 유의해야 한다. 따라서 앞서 그래핀용으로 설명한 것과 같은 그래프QL 프레임워크의 미들웨어 후크를 사용해서 만료를 트리거해야 할 수 있다. 가능한 고유 식별자를 사용해서 클라이언트 측 캐싱을 지원하는 것이 좋다.
  • 커서와 페이지 매김 : 클라이언트와 서버의 과부하를 방지하기 위해서는 요청에 한 번에 반환하는 레코드의 수에 대한 기본 상한선이 필요하다. 또한 클라이언트가 반환할 레코드의 최대 수와 요청할 레코드의 "페이지"를 명시적으로 기술하도록 허용하는 것이 좋다. 공식 그래프QL 문서에서 그래프QL 요청 형식에 페이지 매김 메타포를 통합하는 방법에 관한 몇 가지 유용한 팁을 볼 수 있다.


그래프QL 툴

다양한 언어용으로 제공되는 라이브러리 외에, 그래프QL에는 클라이언트, 서버, 스키마, 쿼리 처리 계층을 더 쉽게 개발하기 위한 다음과 같은 다양한 네이티브 및 서드파티 툴이 있다.
  • 아폴로 그래프QL(Apollo GraphQL)은 그래프QL 클라이언트와 그래프QL 서버를 포함한 그래프QL을 위한 오픈소스 툴을 만드는 데 전력한다. 또한 아플로 그래프QL은 그래프QL 스키마를 생성 및 모킹하고 여러 API를 하나의 API로 "이어 붙이기" 위한 일련의 유틸리티인 그래프QL 툴도 유지관리하면서 여러 API 엔드포인트를 통합하고 관리 편의성을 높인다는 그래프QL의 목표를 추구한다.
  • 기존 스웨거(Swagger) 생성 API를 그래프QL로 이식하려는 경우 스웨거2그래프QL(Swagger2GraphQL)을 사용하면 된다. 또한 이 툴은 레거시 스웨거 생성 API를 함께 유지하도록 허용하므로 전환 기간 동안 두 가지 표준을 모두 사용할 수 있다.
  • 마지막으로, 페이스북 자체 그래프QL 그룹도 몇 가지 주목할 만한 툴을 만들었다. 그래피QL(GraphiQL)은 그래프QL 쿼리를 생성하기 위한 브라우저 내 IDE다. 내부적으로 또는 공개 솔루션으로 사용 가능하다. 그래프QL의 자바스크립트 구현인 그래프QL 오버 HTTP(GraphQL-over-HTTP) 서버 및 클라이언트 제품군, 그리고 IDE를 위한 그래프QL 언어 서비스도 있다.
editor@itworld.co.kr

Serdar Yegulalp editor@itworld.co.kr
저작권자 한국IDG & ITWorld, 무단 전재 및 재배포 금지
기사가 속한 카테고리는 언론사가 분류합니다.
언론사는 한 기사를 두 개 이상의 카테고리로 분류할 수 있습니다.