프로그래밍 기초

GraphQL 맛보기

hs-archive 2023. 8. 24. 00:01

공식 문서 속 GraphQL

GraphQL 공식 문서에 다음과 같은 소개가 적혀있습니다. GraphQL은 API를 위한 쿼리 언어이며 타입 시스템을 사용하여 쿼리를 실행하는 서버사이드 런타임입니다. GraphQL은 특정 DB나 특정 스토리지 엔진과 관계되어 있지 않으며 기존 코드와 데이터에 의해 대체됩니다.

 

정말 무슨 말인지 하나도 모르겠네요!

 

그래도 결국 돌고 돌아 끝끝내 어떠한 개념에 대해 이해했을 때, 공식 문서에 적힌 문장이 가장 정확한 표현임을 항상 느끼므로, 인내심을 갖고 하나하나씩 저 문장을 이해해 봅시다.

 

GraphQL?

GraphQL Spec은 GraphQL에 대한 아이디어와 개념을 모아놓은 집합입니다. 이 GraphQL Spec을 준수한다면 그것은 GraphQL입니다. 따라서 GraphQL을 어떤 언어로 작성하든 상관이 없습니다. 

 

마치 ["hello world!"를 콘솔로 찍는 프로그램을 작성해 주세요!]라는 요구를 받았을 때 해당 요구 사항을 C, Java, Python, JS 등 어떤 언어로도 작성하든 상관없는 것과 비슷합니다.

 

이처럼 GraphQL은 단지 아이디어와 개념의 집합을 자유롭게 구현한 것이기 때문에 [특정 DB, 특정 스토리지 엔진과 관계되어 있지 않는 것]입니다.

 

GraphQL의 목적 및 해결하는 문제 

GraphQL은 웹 클라이언트가 데이터를 서버로부터 효율적으로 가져오는 것이 목적입니다. Over fetching과 Under fetching을 해결함으로써 그러한 목적을 달성합니다.

 

Over fetching

Over fetching이란 필요한 정보보다 더 많은 데이터를 가져온 경우를 뜻합니다. 예를 들어, 영화 정보를 가져오는 REST API가 존재한다고 생각해 봅시다. 우리는 /movies로 GET 요청을 보내면 모든 영화 정보를 가져올 수 있습니다. 그런데 스마트폰 혹은 브라우저에서 영화의 "title"만 필요하다면 어떻게 될까요?

 

나머지 정보들은 다 버려질 것입니다. 어차피 사용되지 않을 데이터였다면 굳이 DB에서 읽어올 필요도, 네트워크를 통해 전달될 필요도 없었을 것입니다. GraphQL 실제 필요한 특정 데이터만 요청하고 받아올 수 있도록 하여서 이러한 Over fetching 문제를 해결합니다. 

// request query
{
    upcoming {
    	title
    }
}

// response
{
    "upcoming" : [
    	{ "title": "1 Movie 1 title ..." },
    	{ "title": "2 Movie 2 title ..." },
    	{ "title": "3 Movie 3 title ..." },
    ]
}

 

Under fetching

Under fetching은 Over fetching의 반대말입니다. 즉, 필요한 데이터보다 적은 양의 데이터를 가져오는 경우를 뜻합니다. 예를 들어, 어떠한 웹 페이지에서 두 가지 리스트를 보여준다고 생각해 봅시다. 하나는 곧 개봉하는 영화 리스트이고 나머지 하나는 현재 상영 중인 영화 리스트입니다. REST API를 사용한다면 2개의 각기 다른 URL로 요청을 보내야 합니다. (곧 개봉하는 영화: /movie/upcoming, 현재 상영 중인 영화: movie/now_playing)

 

즉, 브라우저 혹은 디바이스는 각기 다른 2개의 요청을 보내야 하는 것입니다. 2개의 URL을 통해 서버와 접속해야 하고 이는 로딩 타임의 증가로 이어집니다. GraphQL은 정확히 원하는 것만 요청할 수 있기 때문에 2개의 각기 다른 요청을 보낼 필요 없이 1개의 쿼리에 2개의 정보를 전부 요청할 수 있습니다.

// request query
{
    upcoming {
    	title
    }
    nowPlaying {
    	title
        popularity
    }
}

// response
{
    "upcoming" : [
    	{ "title": "1 Movie 1 title ..." },
    	{ "title": "2 Movie 2 title ..." },
    	{ "title": "3 Movie 3 title ..." },
    ],
    "nowPlaying": [
    	{ "title": "The Godfather", "popularity": 10 },
    	{ "title": "La La Land", "popularity": 8 },
    	{ "title": "The Shawshank Redemption", "popularity": 32 },
    ]
}

 

이처럼 GraphQL은 API요청을 할 때, 마치 DB에서 SQL을 사용하는 것처럼 원하는 데이터만 검색할 수 있습니다. 그래서 GraphQL의 이름에 QL(Query Language, 쿼리 언어)이 있는 것이고, [GraphQL은 API를 위한 쿼리 언어] 라는 말이 공식 문서의 소개에 있는 것입니다.

 

그림으로 보는 REST API와 GraphQL API의 차이

REST API Stack vs GraphQL Stack
REST API vs GraphQL API

REST API와 GraphQL의 차이점을 한눈에 확인할 수 있는 사진입니다. 어떻게 보면 Client 사이드에서 GraphQL은 Multiplex와 비슷한 느낌도 있는 것 같습니다.

 

또한 REST API Stack vs GraphQL Stack 사진을 보면 GraphQL은 [쿼리를 실행하는 서버사이드 런타임]임을 확인할 수 있습니다.

 

GraphQL의 동작 과정

GraphQL 파이프라인

GraphQL을 활용하여 작성된 백엔드 서버에서 GraphQL 요청을 받으면 대략 위와 같은 순서로 해당 요청을 처리합니다.

 

GraphQL Language Processor

서버는 받은 GraphQL 요청을 파싱하여 쿼리 구조를 분석합니다. 이 과정에서 쿼리의 문법 검사와 필드 구조 등을 확인합니다. 또한 파싱된 쿼리는 서버의 스키마와 비교하여 쿼리의 유효성(Validate)을 검증합니다. 요청한 필드가 스키마에 정의되어 있는지 ,필수 필드가 빠져 있는지 등을 확인합니다.

 

GraphQL Resolver (직접 구현)

쿼리의 유효성을 검증한 후 해당 필드에 대응하는 리졸버 함수가 호출됩니다. 리졸버 함수는 필요한 데이터를 가져오는 역할을 수행합니다. 이 단계에서 DB 조회, 외부 서비스 호출 등이 이루어집니다.

 

그 후 가져온 데이터는 리졸버 함수에서 필요한 형식으로 변환됩니다. 데이터를 원하는 형태로 가공하거나 조합하는 작업이 이루어집니다.

 

Output (JSON)

리졸버 함수에서 가공된 데이터를 기반으로 클라이언트에게 줄 응답을 생성합니다. 응답은 JSON 형식으로 전달되며, 이때 HTTP 프로토콜을 사용하여 응답을 반환하거나 WebSocket과 같은 다른 프로토콜을 사용하여 응답을 반환할 수도 있습니다.

 

GraphQL의 스키마 & 타입 시스템

스키마 설계
스키마

GraphQL의 스키마는 API를 사용하는 입장에서 설계하게 됩니다. 스키마를 적절히 설계하여 원하는 데이터만 받아올 수 있습니다.

 

스키마) Field Argument

만약 위 그림처럼 60px짜리 이미지와 42px짜리 이미지가 필요하다면 어떻게 스키마를 설계할 수 있을까요? 아래처럼 모든 url에 대해 필드를 작성해야 할까요?

type Profile {
    name: String
    thumbnailUrl: String
    thumbnailUrl_100px: String
    reviewThumbnailUrl: String
    bigReviewThumbnailUrl: String
    bigReviewThumbnailUrl_200px: String
    ...
}

 

이것은 매우 비효율적인 것처럼 느껴집니다. 사실 GraphQL은 Field Argument를 지원하기에 아래와 같이 작성하여 사용할 수 있습니다.

type Review {
    id: ID! // 느낌표(!)는 필수 인자임을 나타내는 기호입니다.
    nickname: String!
    images(sort: ReviewImageOrder): [Image!]!
}

 

이처럼 GraphQL은 [타입 시스템을 사용]하여 원하는 데이터만 쏙쏙 골라서 요청하고 응답받을 수 있습니다.

 

GraphQL의 단점

지금까지 GraphQL의 장점과 특징에 대해 배웠습니다. GraphQL의 단점에 대해 간단하게 알아봅시다.

 

학습 곡선 및 복잡성

GraphQL은 REST API 방식보다 복잡한 구조를 가지며, 이는 분명한 학습 곡선을 가져옵니다.

 

캐싱 어려움

동일한 데이터를 요청하는 경우라도 쿼리의 구조가 다를 수도 있고, 클라이언트가 요청하는 요청이 매우 유연하기 때문에 서버의 입장에서 어떤 데이터를 어떻게 캐싱해야 하는지 사전에 예측하기 어렵습니다.

 

요약

GraphQL은 API를 위한 쿼리 언어로, 타입 시스템을 이용해 서버에서 원하는 데이터만 효율적으로 가져올 수 있게 해줍니다. Over fetching과 Under fetching 문제를 해결하며, 어떤 언어로든 구현할 수 있습니다.

 

또한, GraphQL을 사용하면 프론트엔드에서 원하는 데이터를 유연하게 요청할 수 있으므로 기존 백엔드-프론트엔드 협업 문화를 많이 바꿀 수 있다고 생각합니다.

 

분명히 단점이 있지만 장점 또한 명확합니다. 조금씩 적용해 가며 상황에 맞게 사용하는 것이 좋아 보입니다.

 

 

 

 

 


https://graphql-kr.github.io/learn/

 

GraphQL: API를 위한 쿼리 언어

GraphQL은 API에 있는 데이터에 대한 완벽하고 이해하기 쉬운 설명을 제공하고 클라이언트에게 필요한 것을 정확하게 요청할 수 있는 기능을 제공하며 시간이 지남에 따라 API를 쉽게 진화시키고

graphql-kr.github.io

https://www.youtube.com/watch?v=N-81mS2vldI

https://tech.kakao.com/2019/08/01/graphql-basic/

 

GraphQL 개념잡기

GraphQL은 페이스북에서 만든 쿼리 언어입니다. GrpahQL은 요즘 개발자들 사이에서 자주 입에 오르내리고 있으나, 2019년 7월 기준으로 얼리스테이지(early-stage)임은 분명합니다. 국내에서 GraphQL API를 O

tech.kakao.com

'프로그래밍 기초' 카테고리의 다른 글

Node.js 이벤트 루프  (0) 2023.09.04
AWS S3에 파일 업로드: pre-signed URL  (0) 2023.08.28
SOLID 원칙  (0) 2023.08.17
PostgreSQL vs MySQL  (0) 2023.08.12
Socket.IO 소개 3 - adapter  (0) 2023.07.28