REST API에서 GraphQL로의 패러다임 전환 - Facebook이 주목한 기술

2023.10.20
15분
댓글

글을 시작하며

항상 새로운 기술을 배울 때는 기술이 어떤 문제를 해결하기 위해 등장했는지
그리고 이 기술을 사용함으로써 얻을 수 있는 것과 잃을 수 있는 것들을 고민하는 능력이 필요합니다.

이번 글에서는 GraphQL이 어떤 문제를 해결하기 위해 등장했는지와 GQL을 사용함으로써 얻을 수 있는 가치
이와 반대로 REST API와 비교하여 잃을 수 있는 점들을 중점으로 다뤄보고자 합니다.

마지막으로는 GQL 도입을 고민 중이신 분들을 위해
GQL을 사용했을 때 이점이 있는 서비스의 예시GQL의 철학과 사용 의의에 대해 알아보면서
글을 마무리하도록 하겠습니다.


GraphQL은 어떻게 세상에 나오게 되었을까요?

GraphQL은 REST API의 한계를 극복하기 위해서 Meta(전 facebook)가 고안한 쿼리 언어입니다.

즉, Meta가 REST API의 어떤 부분이 불편했다고 느꼈는지에 집중해보면
GraphQL의 존재의의와 이 기술을 언제 사용하면 좋을지에 대한 그림이 그려질 것입니다.

GraphQL이 극복하고자한 REST API의 한계는 다음과 같습니다.

✔️ Overfetching

  • REST API는 일부 데이터만 필요하다고 해도 resource의 전체 데이터를 모두 불러와야 합니다.
  • 프로젝트의 규모가 커지고 방대한 데이터를 다루게 되면 overfetching으로 인한 성능 이슈가 발생할 수 있습니다.
  • Meta가 GQL을 개발한 초기 이유 중 하나는 모바일 사용의 증가 때문이라고 합니다.

GQL은 어떻게 개선했나요?

  • API 통신은 네트워크 환경의 영향을 많이 받기 때문에 데이터 크기에 따라 속도 차이가 발생합니다.
  • GQL을 사용하면 필요한 필드만 명시적으로 요청할 수 있기 때문에 HTTP 응답 사이즈를 최소화해서 모바일 환경에서의 부담을 줄일 수 있습니다.

✔️ Underfetching

  • REST API에서는 특정 데이터를 얻기 위해 여러 개의 엔드포인트를 통해 데이터를 요청 해야하는 상황이 있습니다.
  • 네트워크가 좋지 않은 환경에서 여러 개의 API를 호출하게 되면 FCP, LCP가 느려질 수 있고 이는 사용자 경험에 치명적인 영향을 줄 수 있습니다.
  • 또한, HTTP1.1을 사용하는 환경이라면 한 Origin 당 동시에 요청을 보낼 수 있는 개수도 제한되기 때문에 더 느려질 수도 있습니다.

GQL은 어떻게 개선했나요?

  • GQL에서는 필요한 데이터 구조를 정의할 수 있기 때문에 하나의 쿼리로 원하는 여러 데이터들을 한 번에 불러올 수 있습니다.

231020-193016

query {
  book(id: "1") {
    title
    author {
      firstName
      lastName
    }
  }
}
{
  "title": "Romance of the Three Kingdoms",
  "author": {
    "firstName": "Luo",
    "lastName": "Guanzhong"
  }
}

흠.. 그래도 REST API 자체적으로 해결하는 방법은 없을까요? 🤔

물론 REST API에서도 필요한 데이터만을 가져오기 위해 커스텀 엔드 포인트를 만들거나 데이터 필터링 기능을 추가할 수도 있습니다.

하지만 이러한 방법들은 API의 복잡성을 증가시킬 수 있고
특정 상황에서만 적용 가능한 제한적인 방법이기 때문에 문제를 근본적으로 해결한다고 보기는 어렵습니다.

✔️ API 버전 관리 문제

  • REST API에서는 새로운 기능을 추가하거나 기존 기능을 변경할 때 새 버전의 엔드포인트를 만드는 것이 필요합니다.
  • 따라서 클라이언트와 서버간의 버전 관리가 어려워집니다.

GQL은 어떻게 개선했나요?

  • GQL은 엔드포인트가 아닌 스키마 기반으로 동작하기 때문에 새로운 필드를 추가하거나 변경해도 기존 쿼리에 영향을 주지 않고 스키마를 확장할 수 있습니다.

✔️ 서버-클라이언트 의존성 문제

  • REST API에서는 서버 엔드포인트 구조에 맞춰서 데이터를 요청하고 파싱하는 것이 필요합니다.
  • 따라서 서버에서 변경이 발생하면 클라이언트에서도 코드를 수정해야 하는 경우도 왕왕 있습니다.

GQL은 어떻게 개선했나요?

  • GQL은 스키마를 기반으로 클라이언트에서 필요한 데이터 구조를 요청하기 때문에, 서버와 클라이언트의 의존성을 보다 낮출 수 있습니다.

GQL을 사용하지 않을 이유가 없는 것 같은데요..? 😯

위 내용을 읽다보면 GQL이 REST API의 모든 한계를 극복한 것만 같아서 선택하지 않을 이유가 없다는 생각이 들기도 합니다. 하지만 당연하게도 GQL에도 다양한 문제들이 존재합니다.

GQL의 가장 큰 특징인 단일 엔드포인트가 REST의 많은 한계점들을 해결해주었지만
단일 엔드포인트에 의한 단점들도 발생합니다.

그 일례로 요청이 3천건이 넘어가면 REST보다 성능이 떨어진다는 연구 결과가 있으며
단일 엔드포인트와 공개된 스키마로 인한 보안 위협도 존재합니다. 또한, HTTP 내장 캐시 기능을 사용하기도 어렵습니다.

GQL의 단점

  • 요청이 3천건이 넘어가면 REST보다 성능이 떨어짐
  • 단일 엔드포인트와 공개된 스키마로 인한 보안 위협
  • HTTP 내장 캐시 기능을 활용하기 어렵

어떤 서비스에서 GQL을 사용하는 것이 좋을까요?

이 문제에 대한 답을 구하기 위해선 GQL과 REST API의 등장 배경의 차이점을 비교해보는 것이 필요합니다!

REST API자원을 효율적으로 주고 받는 방식에 대한 고민에서 시작된 것이라면
GQL화면 구현을 더 잘하고자 하는 고민에서 시작된 기술입니다.

따라서 팀이 만들고자 하는 서비스가 자원 통신에 집중을 해야하는지
화면 구현에 집중을 하는 것이 필요하는지 점검하는 것이 필요합니다.

✔️ 등장 배경

  • REST API: 자원을 효율적으로 주고 받기 위해서
  • GQL: 화면 구현을 더 잘하기 위해서

자원 통신에 집중하는 서비스

자원 통신에 집중해야하는 서비스는 쉽게 말해서 UI를 그릴 필요가 없는 경우를 말합니다.
예를 들어, 구글 맵을 연동하거나 네이버 페이를 연동하는 등 유저가 보지 않는 내부 기능을 구현하기 위해
통신하는 경우에는 REST API를 사용하는 것이 더 유리할 수 있습니다.

UI를 구현하는데 많은 데이터가 필요한 서비스

반면 화면을 그리는데 많은 데이터들을 필요로하는 서비스라면
데이터를 한 번의 요청으로 받아올 수 있는 GQL이 더 많은 이점을 가질 것입니다.

✅ 도입 전 고민해볼 체크 리스트

  • 우리가 만드는 서비스는 얼마나 크고 복잡한가?
  • 요청하는 데이터의 형태가 얼마나 다양한가?
  • 데이터 요청 횟수는 얼마나 많은가?
  • 우리의 서버 아키텍처는 GraphQL을 도입하기 적절한가?

Fragment-driven Development

사실 GQL을 사용하기만 한다고 해서 overfetching과 같은 문제점들이 마법처럼 해결되는 것은 아닙니다.

중요한 것은 GQL을 ‘잘’ 활용하는 것입니다.

‘잘’이라는 말이 굉장히 추상적으로 느껴지죠 🧐
개인적으로 저도 추상적인 표현보다는 확실한 표현을 좋아하기 때문에 더 자세히 풀어보도록 하겠습니다 ㅎㅎ

GQL을 ‘잘’ 활용한다는 것은 Fragment-driven하게 개발한다는 것입니다.
Fragment-driven하게 개발한다는 것은
화면을 구성하는 컴포넌트마다 표현하는 데이터 fragment가 완전히 일치하도록 하는 것입니다.

✔️ 컴포넌트 의존성

예를 들어, 부모 컴포넌트가 불러온 데이터를 자식 컴포넌트들이 공유하게 된다면 컴포넌트간의 의존성이 발생하게 됩니다.

만약 기획 변동 등의 이유로 상위 컴포넌트에서 특정 필드를 사용하지 않아서 삭제하게 된다면
해당 필드를 사용하는 다른 컴포넌트들에서 에러가 발생할 수 있습니다.

이러한 문제가 무서운 이유는 대규모의 팀이 개발을 진행할 경우 문제가 바로 드러나지 않을 수도 있다는 점입니다.

따라서 각 컴포넌트들은 자신만의 데이터 fragment를 갖는 것이 이상적입니다.

✔️ relay의 데이터 마스킹

이러한 규칙을 지키기 위해 relay에서는 다른 컴포넌트에서 사용하는 데이터를 현재 컴포넌트에서 사용하지 못하게 하는 데이터 마스킹 기능을 제공하기도 합니다.

하지만 relay를 사용하지 않더라도 GQL의 철학과 사용 의의를 고려하여 의식적으로 Fragment-driven한 개발을 할 수 있도록 해야할 것입니다.

팀에서 Fragment-driven한 개발 문화가 합의된다면 컴포넌트간의 의존성으로 인한 버그 발생률을 크게 낮출 수 있고
다른 컴포넌트와의 의존성을 고려하지 않아도 되기 때문에 개발 생산성이 굉장히 높아질 수 있다고 생각합니다.


글을 마치며

이번 글을 통해 GraphQL이 해결하고자 하는 문제들에 집중하면서 GraphQL을 도입했을 때 얻을 수 있는 이익과
REST API와 비교했을 때 잃을 수 있는 점들에 대해서 알아보았습니다.

Facebook과 같은 해외 기업 뿐만 아니라 네이버, 당근마켓, 카카오와 같은 국내 빅테크 기업들도 데이터를 유연하게 사용하기 위해 GraphQL을 도입하여 사용하고 있습니다.
왜 많은 기업들이 GraphQL을 채택하게 되었는지 이번 글을 통해 이해하는데 도움이 되셨으면 좋겠습니다.

참고 문서