회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
AWS 이용 중이라면 최대 700만 원 지원받으세요
지난 2024년 10월 10일, 미국 샌프란시스코에서 GraphQLConf 2024가 열렸습니다. 이 콘퍼런스는 GraphQL 재단(GraphQL Foundation)이 주최하는 공식 행사로, 전 세계의 GraphQL 개발자들이 한자리에 모여 정보를 교류하고 또 새로운 스펙을 채택하는 자리이기도 했습니다.
회원가입을 하면 원하는 문장을
저장할 수 있어요!
다음
회원가입을 하면
성장에 도움이 되는 콘텐츠를
스크랩할 수 있어요!
확인
지난 2024년 10월 10일, 미국 샌프란시스코에서 GraphQLConf 2024가 열렸습니다. 이 콘퍼런스는 GraphQL 재단(GraphQL Foundation)이 주최하는 공식 행사로, 전 세계의 GraphQL 개발자들이 한자리에 모여 정보를 교류하고 또 새로운 스펙을 채택하는 자리이기도 했습니다.
GraphQL은 클라이언트가 필요한 특정 데이터만 요청할 수 있도록 하여 보다 효율적이고 유연한 데이터 검색을 가능하게 하는 API 쿼리 언어입니다.
언어의 발전과 함께 점점 더 많은 기업에서 클라이언트-서버 통신 수단으로 GraphQL을 채택하는 사례가 늘어나고 있습니다. 대표적으로 페이스북(Facebook), 깃허브(GitHub), 그리고 핀터레스트(Pinterest) 같은 서비스들이 GraphQL을 채택하고 있다고 합니다. 대형 서비스들뿐만이 아닙니다. 글을 쓰는 현재 기준(24년 10월), 깃허브에서 “GraphQL”이란 키워드를 포함한 공개 레포지토리가 29,865개에 달할 정도죠.
이번 글에서는 이 쿼리 언어의 특징을 살펴보며, 왜 이토록 많은 관심을 받는지 알아보려고 합니다.
“MATER ARTIUM NECESSITAS”
William Horman, 1519
“필요는 발명의 어머니”라는 말이 있습니다.
GraphQL을 만든 주체는 메타(Meta, 당시 Facebook)입니다. 이들은 왜 GraphQL이라는 새로운 데이터 통신 방식을 만들어야 했을까요?
2004년, 첫 출시 이후 페이스북은 엄청난 인기를 누리며 몇 년 만에 수백만 명의 사용자를 거느린 거대 플랫폼이 되었습니다. 그러던 2007년 애플의 아이폰이 출시되었고, 같은 해 구글의 안드로이드 역시 발표되었죠. 기존 PC 브라우저 기반의 페이스북에도 휴대전화를 이용한 이용자가 늘어나게 됩니다. 그와 함께 웹에 집중하던 페이스북 개발에도 변화가 생기기 시작합니다.
Mark Zuckerberg “Our Biggest Mistake Was Betting Too Much On HTML5”
Olanoff, Drew. TechCrunch. 2012. 09. 11.
2012년 인터뷰에서 메타 창업자 마크 저커버그(Mark Zuckerberg)는 “페이스북이 웹 기반(HTML5)에 치중했던 것이 실수”라고 언급하기도 했습니다. 이는 곧 iOS나 안드로이드(Android) 앱 확대를 키우겠다는 말이었죠.
하지만 당시 모바일 시장으로 나가려면, 이에 앞서 기존 REST API에서 발생했던 문제를 해결할 필요가 있었습니다. 이 시점 페이스북이 직면했던 문제들은 아래와 같습니다.
이러한 문제를 해결하기 위해 페이스북은 2012년, GraphQL을 적용한 새로운 iOS 앱을 출시하게 됩니다.
그렇다면 GraphQL은 어떻게 저 4가지 문제를 해결하는 것일까요? 다시 말해, GraphQL은 기존에 사용하던 REST와 어떤 점이 다른 걸까요?
기존에 클라이언트-서버 통신 수단으로 가장 많이 쓰인 REST API는 2000년, 로이 필딩(Roy Fielding)의 논문에서 처음 등장합니다. REST의 가장 큰 특징은 바로 결과의 일관성입니다. 이를 활용하면 클라이언트가 특정 엔드포인트에 요청을 보낼 때, 그에 해당하는 정해진 데이터 구조로만 응답을 받습니다.
이러한 REST 구조는 현실의 정찬 식당과 유사하다고 볼 수 있습니다. 정찬을 주문하면 누가 시키든 같은 음식이 제공되기 마련이니깐요. 물론 REST 역시 쿼리 매개 변수(query parameter)를 이용해서 약간의 변주를 줄 수는 있지만, 그 또한 범위가 한정적입니다. 마치 중국집에서 코스 요리를 먹고는, 후식으로 짜장면을 먹을지 짬뽕을 먹을지 선택하는 정도죠.
반면 GraphQL은 뷔페에 더 가깝습니다. 뷔페에서는 식당이 정해진 음식을 손님에게 가져다 주지 않습니다. 손님이 직접 원하는 음식을 선택하는 구조이죠. 마찬가지로 GraphQL도 클라이언트가 필요한 데이터만 정확하게 선택해 요청할 수 있습니다. 마치 뷔페에서 손님이 접시에 원하는 종류의 음식을 필요한 양만큼 덜어가듯, 클라이언트가 서버로부터 필요한 데이터만 골라 갈 수 있는 것입니다.
예를 들어, GraphQL에서는 다음과 같은 쿼리를 한 번에 보낼 수도 있습니다: “사용자의 민감 정보를 제외한 기본 정보와 그들이 작성한 게시글, 그리고 그 게시글에 달린 댓글들, 그 댓글에 좋아요를 누른 사람”. 일반적인 REST API라면 여러 번 쿼리를 반복해야 할지도 모를 요구사항이죠.
또한 식당에서 메뉴를 추가하거나 없앨 때는 메뉴판을 새로 만들어야 합니다. 게다가 기존 음식을 찾는 단골 손님들에게는 일일이 설명도 해줘야 하죠. 반면 뷔페에서는 손님이 메뉴 구성을 직접 확인하며 시각적, 후각적 정보를 얻을 수 있습니다.
REST와 GraphQL의 차이도 이와 비슷합니다. GraphQL이 API 수정 문제에서 좀 더 자유로운 편입니다. 물론 REST 역시 오픈 API 스펙을 사용해 명세하긴 하지만, 명세가 바로 코드로 이어지는 것은 아닙니다. 반면 GraphQL은 스키마 정의 언어(Schema Definition Language)이기 때문에 스키마-우선 개발 면에서 훨씬 매끄러운 흐름을 보여줍니다.
다음은 REST와 GraphQL이 각각 사용자의 정보를 가져오는 예시입니다.
아래 JSON 형식의 데이터를 서버에서 클라이언트로 전송한다고 가정해 봅시다.
REST API의 경우 먼저 특정 user를 받아올 수 있는 URI 엔드포인트(Endpoint)를 준비합니다.
GET /users/123456789
*여기서 맨 마지막 숫자는 user의 ID에 해당합니다.
REST는 대표적인 명세 방법인 오픈에이피아이(OpenAPI Specification, 이하 OAS)를 이용해 해당 엔드포인트의 응답을 명세해 줍니다. 이 명세는 스웨거(Swagger)나 리도클리(Redocly) 등의 툴로 시각화해서 클라이언트가 서버에게, 어떤 요청에 대해 어떤 응답이 오는지 알 수 있게 해줍니다.
여기서 GraphQL과 REST의 가장 큰 차이가 나타납니다. REST는 OAS로 명세하는 것이 모범 사례이지만, 실제 구현이 문서와 다르다고 해서 직접적인 오류가 발생하지 않습니다. 문서가 오래되어 업데이트가 이뤄지지 않았거나, 개발자의 실수로 구현과 명세가 일치하지 않을 수 있습니다. REST에서는 문서가 권장 사항에 가깝기 때문이죠.
반면 GraphQL은 스키마 정의 언어(Schema definition language)로써 API의 구조를 명확하게 정의하고 강제합니다. 이는 API 설계 단계에서부터 데이터를 어떻게 조회하고 조작할지 명확하게 규정하는 역할을 하며, 클라이언트와 서버 간에 엄격한 계약을 형성하여 일관성과 안정성을 높입니다.
예시로 보겠습니다. 일단 OAS에서처럼 GraphQL 스키마를 정의했습니다.
다음으로는 REST의 GET 엔드포인트와 같은 역할을 하는 쿼리 타입을 정의해야 합니다.
마지막으로, 실제 쿼리에서는 아래처럼 원하는 필드(field)만을 선택하여 요청할 수 있습니다.
이런 방식으로 요청할 수 있다면, 쿼리로 필요한 필드만을 불러오면서 앞서 제기된 오버패칭 문제를 해결하게 됩니다.
그렇다면 같은 화면에서 사용자 한 명의 정보, 해당 사용자의 친구들에 대한 정보를 한 번에 불러올 수도 있을까요?
REST 원칙을 잘 지키는 API라면, 이런 복잡한 과정을 거쳐야 할지도 모릅니다.
여기에 N명의 친구를 보유한 사용자의 친구 정보를 모두 얻기 위해선 N+1번의 요청이 필요해집니다.
GraphQL은 좀 더 손쉬운 방법으로 이를 해결할 수 있습니다. User 스키마에 ‘friends’ 필드를 추가했습니다.
다만 여기서 friends 필드는 필수가 아닙니다. 그러므로 평소에는 쿼리하지 않다가 필요한 경우에만 쿼리할 수 있습니다.
이 쿼리만으로 아래처럼 필요한 데이터 구조를 한 번에 반환받을 수 있었습니다. 이런 특성으로 언더패칭 문제 역시 해결할 수 있습니다. 특히 GraphQL을 이용할 경우, 실제 쿼리 예시처럼 name과 email의 조합뿐만 아니라 가능한 16개(=2^4)의 조합으로 데이터를 쿼리해올 수 있습니다.
물론, REST를 사용한다고 해서 이런 응답 형태를 받지 못한다는 것은 아닙니다. 다만 소위 말하듯 REST스럽지 않은(Not RESTful) API가 되는 것이죠.
그렇다고 GraphQL이 REST를 완전히 대체하는 도구는 아닙니다. 오히려 REST의 단점을 보완하기 위한 대안이라고 할 수 있습니다. 그렇다면 어떤 경우에 GraphQL을 사용하는 것이 유리할까요?
GraphQL은 여러 UI 컴포넌트에 필요한 데이터를 효과적으로 받아올 수 있습니다. 소셜 미디어 앱의 홈페이지를 예로 들어 보겠습니다. 이 페이지에는 사용자의 프로필 정보, 최근 게시물, 친구 목록, 알림 등 다양한 정보가 한 번에 보여야 합니다. REST API를 사용한다면 각각의 정보를 얻기 위해 API를 여러 번 호출할 필요가 있지만, GraphQL을 사용하면 단일 쿼리로 필요한 모든 데이터를 한 번에 가져올 수 있습니다.
GraphQL은 API가 점진적으로 발전할 수 있도록 만듭니다. 새로운 필드를 추가하거나 기존 필드를 미사용(deprecated)으로 표시함으로써, 기존 클라이언트에 영향을 주지 않고 API를 변경할 수 있습니다. API 버전 관리의 복잡성을 줄이고 클라이언트와 서버 간의 호환성을 유지하는 데 도움이 됩니다.
GraphQL은 프론트엔드와 백엔드 개발을 병렬적으로 진행할 수 있게 해줍니다. 프론트엔드 개발자는 직접 필요한 데이터 구조를 정의하고 쿼리를 작성할 수 있으며, 백엔드 개발자도 이에 맞춰 리졸버를 구현할 수 있습니다. 이러한 접근 방식은 개발 속도를 올려 팀의 원활한 협업을 돕습니다.
GraphQL은 강력한 개발자 도구를 제공합니다. 이를 기반으로 API 개발과 테스트를 더욱 효율적으로 만듭니다. GraphiQL과 같은 도구는 실시간으로 쿼리를 작성하고 테스트할 수 있는 환경을 제공하며, 스키마 탐색과 자동 완성 기능으로 개발 속도를 높입니다.
마지막으로 가볍게 실제 서비스가 REST에서 GraphQL로 전환한 사례도 살펴보겠습니다. 깃허브는 지난 2016년에 GraphQL API를 공개하며, 전환 이유를 공식 블로그 글에서 상세히 설명했습니다.
전환을 결심한 첫 요인, ‘확장성’입니다. 당시 REST API로 발생하는 요청은 전체 데이터베이스 요청의 60% 이상을 차지하고 있었다고 합니다. 이때 필요한 정보를 얻기 위해 클라이언트와 서버가 여러 번 통신해야 하는 구조적 한계가 있었습니다.
두 번째 요인은 ‘API에 대한 메타 정보 관리’입니다. 예를 들어, 각 엔드포인트에 필요한 OAuth 스코프를 파악하고, 페이지네이션을 개선하고, 타입 안정성을 높이는 일들이 포함되었습니다.
이런 이유로 깃허브는 GraphQL을 도입했고, API 사용성을 크게 올릴 수 있었습니다. 깃허브의 실제 GraphQL API는 깃허브 공식 문서의 GraphQL API 문서에서 확인할 수 있죠. GraphQL 모범 사례를 함께 살펴볼 수 있는 가이드도 제공하고 있습니다. GraphQL 도입을 고민하고 있다면, 깃허브의 사례를 잘 살펴보면 도움이 될 것입니다.
GraphQL은 현대적인 API 개발에 있어 중요한 도구로 자리 잡았습니다. 복잡한 데이터 요구 사항을 효율적으로 처리하고, API의 유연성과 확장성을 높이며, 개발 프로세스를 간소화하는 장점으로 많은 기업의 관심을 끌고 있습니다. GraphQL의 장점을 잘 이해하고 프로젝트의 특성과 요구사항을 고려하여 적절히 선택해 보는 것은 어떨까요?
GraphQL 공식 홈페이지 https://graphql.org
Nest.JS의 GraphQL 가이드 https://docs.nestjs.com/graphql/quick-start
Amazon AppSync https://aws.amazon.com/appsync/
요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.