GraphQL

GreenBean·2023년 3월 22일
0
post-thumbnail

GraphQL

GraphQL 공식문서 ( 한글 )
GraphQL 이란 무엇인가

기존 API 호출 방식의 한계

  • 클라이언트 개발을 하면서 서버와 통신을 해야할 때 보통 서버가 구현해놓은 API 를 호출해 데이터를 보내거나 받음
    • 보통 앱에서 하나의 View 를 그리기 위해서는 보통 여러 번 API 를 호출해야하고 호출을 통해 받아온 데이터를 조합해 사용해야 함
    • 예를 들어 여러번 REST API 를 호출해 하나의 View 를 만들어내는 경우
      • 앱의 페이지가 복잡해질수록 많은 호출을 해야하고 데이터 조합을 위해 순차적인 처리가 들어가야 하는 경우가 많아지기 때문에 데이터를 조합하는 것은 매우 복잡해짐

  • 이를 편하게 하기 위해 데이터 흐름을 만들고 해당 흐름에 순차 처리 로직을 위한 로직을 넣는 방식의 프로그래밍이 많이 사용됨
    • 대표적으로 Rx 와 Coroutine 의 Flow 등이 존재
    • 하지만 결국 하나의 페이지를 그리기 위한 데이터를 조합하는 것을 클라이언트에서 처리해주어야 하기 때문에 클라이언트의 로직이 복잡해지는 문제가 발생
      • 로직이 복잡해지는 것은 유지보수가 어려워진다는 뜻
  • 기존의 REST API 나 다른 API 호출 방식은 이 문제를 해결하지 못함
    • 기존 API 들에서 사용자는 서버에서 정의한 데이터 구조만을 한번에 하나씩 가져올 수 있기 때문
    • 이를 해결하기 위해 클라이언트에서 직접 View 에 보여질 쿼리를 만들어 모든 데이터를 한 번에 가져와야 함

GraphQL 이란?

  • GraphQL 은 Server API 를 구성하기 위해 Facebook 에서 만듬
    • GraphQL클라이언트에서 필요한 데이터만을 쿼리할 수 있도록 하여 위의 문제를 매우 직관적이고 깔끔하게 해결
      • 이를 위해 GraphQL 은 클라이언트에서 사용할 Query Language 를 정의
    • 클라이언트가 필요한 데이터에 대한 쿼리를 선언해서 GraphQL 에 넘기면 GraphQL 은 쿼리를 해석해 서버에서 필요한 데이터를 가져온 후 클라이언트에 해당 데이터를 반환

Tip! 쿼리 언어 ( Query Language )

  • 쿼리 언어는 정보를 얻기 위해 보내는 질의문 ( Query ) 를 만들기 위해 사용되는 컴퓨터 언어
    • 가장 잘 알려져있는 예시로는 데이터베이스 시스템에 저장된 데이터를 가져오기 위해 사용하는 SQL 이 있음
    • 예시: SELECT user_id, username, age FROM users;
  • GraphQL ( Graph Query Language )
    • SQL 이 데이터베이스 시스템으로부터 데이터를 가져오는 목적을 가진다면 GraphQL 은 클라이언트가 데이터를 서버로부터 가져오는 것을 목적으로 함
    • GraphQL 은 아래와 같은 쿼리를 통해 서버로부터 데이터를 가져옴
{
    user {
        user_id
        username
        age
    }
}
  • 예를 들어 id 에 따라 저자의 이름과 이메일을 가지고 오고 싶다면 아래와 같은 쿼리 사용
query Author($id: Int) {
    author(id: $id) {
        name
        email
    }
}
  • 주소도 추가하여 가져오고 싶다면 한 줄을 추가하면 됨
query Author($id: Int) {
    author(id: $id) {
        name
        email
        address
    }
}
  • GraphQL 은 다른 Query Language 인 SQL 등과 같이 쿼리를 선언하면 해당 값에 맞는 데이터를 가져옴
    • 절차적으로 쿼리를 처리하는 것이 아니라 선언적으로 쿼리를 처리함으로써 어떤 데이터가 오는지 더욱 직관적으로 알 수 있게 됨

Tip! GraphQL 의 구조

  • GraphQL 은 데이터의 구조를 정의하는 스키마 ( Schema ) ∙ 데이터 조회를 위한 쿼리 ( Query ) ∙ 데이터 위한 뮤테이션 ( Mutation ) ∙ 조회 결과에 대한 구현을 위한 리졸버 ( Resolver ) 로 구성되며, 이 외에 API명세서의 기능을 하는 인스로펙션 ( Instropection ) 으로 구성

Tip! GraphQL 의 파이프라인

  • GraphQL Query
  • Query Language Processor ( Parse ∙ Validate )
  • GraphQL Resolver: RDB / NoSQL
  • Output ( JSON )

GraphQL vs REST

  • GraphQL 은 RESTful API 가 이미 존재하고 많이 사용되던 2012년 만들어졌음
    • GraphQL 은 어떤 이유에서 만들어졌고 RESTful 과는 어떤 차이가 있을까?
  • GraphQL 이 REST 와 비교해서 가지는 차이점
    • GraphQL API 는 보통 하나의 엔드포인트를 가짐
    • GraphQL API는 요청할 때 사용하는 쿼리에 따라 다른 응답을 받을 수 있음

하나의 엔드포인트

  • REST API 는 보통 여러 엔드포인트를 가지며 각각의 엔드포인트가 동일한 응답을 반환
    • 하지만 GraphQL 은 보통 하나의 엔드포인트만을 사용하며 요청하는 쿼리에 따라 다른 응답을 반환하는 방식
  • REST API 예시
    • example.com/class
    • example.com/class/{반 index}
    • example.com/class/{반 index}/students
    • example.com/class/{반 index}/students/{학생 index}
  • GraphQL 예시
    • example.com
      • 하나의 엔드포인트에 다른 쿼리를 사용해 요청
  • REST API 의 경우 반에 속해있는 데이터를 가져오는데에 응답마다 다양한 엔드포인트를 가지게 됨
    • 엔드포인트가 많아질 경우 관리하기 힘들 뿐더러, 많은 엔드포인트의 노출을 막기위해 추가적인 처리가 필요 할 수 있음
    • 하지만 GraphQL 은 하나의 엔드포인트 ( Root Endpoint ) 에 다른 쿼리로 요청함으로써 다른 응답을 받을 수 있음

원하는 응답 값만 받을 수 있음

  • 엔드포인트에 따라 정해진 응답 값만 받아올 수 있는 REST API 와 달리 GraphQL 은 쿼리 작성을 통해 필요한 데이터만 골라 받아올 수 있음
  • REST API 예시
    • GET https://restapi.com/api/people/1
# REST API 응답 예시

{
    "name": "Luke Skywalker",
    "height": "172",
    "mass": "77",
    "hair_color": "blond",
    "skin_color": "fair",
    "eye_color": "blue",
    "birth_year": "19BBY",
    "gender": "male",
    "homeworld": "http://swapi.dev/api/planets/1/",
    "films": [
      "http://swapi.dev/api/films/1/", 
      "http://swapi.dev/api/films/2/", 
      "http://swapi.dev/api/films/3/", 
      "http://swapi.dev/api/films/6/"
    ],
    "species": [],
    "vehicles": [
      "http://swapi.dev/api/vehicles/14/", 
      "http://swapi.dev/api/vehicles/30/"
    ],
    "starships": [
      "http://swapi.dev/api/starships/12/", 
      "http://swapi.dev/api/starships/22/"
    ],
    "created": "2014-12-09T13:50:51.644000Z",
    "edited": "2014-12-20T21:17:56.891000Z",
    "url": "http://swapi.dev/api/people/1/"
}
  • REST API 를 통해서 인물의 정보를 받아오면 필요한 정보 이외에도 너무나 많은 정보까지 함께 받아야 함
    • 여기서 이름 ∙ 키 ∙ 몸무게의 데이터만 필요하다고 할 때 GraphQL API 를 사용하면 아래와 같이 요청 할 수 있음
  • GraphQL 예시
    • POST https://graphqlapi.com
# GraphQL API 요청 예시

query {
    person(personID: 1) {
        name
        height
        mass
    }
}
# GraphQL API 응답 예시

{
    "data": {
        "person": {
            "name": "Luke Skywalker",
            "height": 172,
            "mass": 77
        }
    }
}
  • REST API 로는 3개의 데이터를 가져오기 위해 13개의 불필요한 데이터까지 함께 가져와야 했지만 GraphQL 은 클라이언트에서 필요한대로 쿼리를 작성해 원하는 데이터만을 가져올 수 있음

REST API 의 한계

  • REST API 는 단순한 서비스에서는 아주 좋지만 복잡한 서비스나 클라이언트의 요청 사항에 따라 Over-FetchingUnder-Fetching 이 발생
  • 또한 REST API 로 여러 환경에서 필요한 정보들을 리소스 별로 엔드포인트를 갖도록 구현하는 것은 어려움
    • 한마디로 비슷하지만 엔드포인트가 다른 API 가 많이 파생됨

Over-Fetching

  • 예를 들어 사용자의 데이터를 조회하는 /user API 가 있다고 가정
    • 이 때 사용자 번호 1 에 해당하는 데이터를 조회하면 아래와 같은 형태가 됨
# GET /user/1
# 응답 예시

{
    "user_no": 1,
    "user_name": "test",
    "user_grade": "VVIP",
    "zip": "11053",
    "last_login_timetamp": "2019-08-08 12:11:44",
    ...
}
  • 여기서 클라이언트는 1번에 해당하는 유저의 이름만을 사용하고자 한다고 해도 유저 이름만 반환하는 API 가 없다면 위와 같은 /user/1 API를 호출한 다음 user_name 을 가져와 사용해야함
    • 이 때 user_gradezip 등의 데이터는 사용하지 않는 데이터도 같이 반환 받는데 이는 곧 리소스의 낭비라고 볼 수 있고 이와 같은 낭비를 Over-Fetching 이라 함

Under-Fetching

  • 쇼핑몰 서비스의 경우 로그인한 사용자의 장바구니 정보를 보여준다고 가정하면 여러 API를 호출하게 됨
# GET /user/1/
# GET /cart/
# GET /notification/
# GET /wish/
...
  • 요청에 맞게 유효한 데이터를 보여주기 위해 여러 API를 호출하게 되는 경우를 Under-Fetching 이라 함

GraphQL 의 장점

  • GraphQL 이 REST API 와 비교해서 가지는 장점

HTTP 요청 횟수를 줄일 수 있음

  • RESTful 의 경우 필요한 리소스 별로 요청 해야하고 필요한 데이터들이 부분적으로 나눠서 개발되어 있다면 그만큼 요청 횟수가 늘어남
    • 하지만 GraphQL 은 원하는 정보를 하나의 쿼리에 모두 담아 요청 할 수 있음

HTTP 응답 사이즈를 줄일 수 있음

  • Restful 의 경우 응답의 형태가 정해져있기 때문에 필요한 정보만 부분적으로 요청하는 것이 힘들고 자연스럽게 데이터의 사이즈가 클 수 밖에 없음
    • Facebook 이 GraphQL 을 개발한 초기 이유 중 하나는 모바일 사용의 증가라고 함
    • GraphQL 을 사용함으로써 데이터 사이즈를 최소화하여 모바일 환경의 부담을 줄일 수 있음

프론트엔드와 백엔드 개발자의 부담을 덜 수 있음

  • Restful API 를 사용한다면 프론트엔드 개발자는 API 의 request/response 형식에 의존하게 됨
    • 따라서 새로운 엔드포인트를 효율적이게 개발하기 위해서는 프론트엔드와 백엔드 개발자의 커뮤니케이션이 강제되는 경우가 많음
  • 하지만 GraphQLrequest/response 의존도가 많이 없기 때문에 개발자들의 API 개발 부담을 덜 수 있음

GraphQL 의 구조와 한계

  • 클라이언트에서 쿼리를 선언하면 데이터를 절차적으로 처리하는 것은 누가 하는가?
    • SQL 은 RDB 가 해당 역할을 수행하는데 GraphQL 은 도대체 누가 그 역할을 할까?
    • 바로 서버와 클라이언트 사이에 GraphQL 이라는 Service Broker 레이어가 더 들어가고 이 GraphQL 에서 절차적으로 처리를 수행
  • GraphQL 을 사용하기 위해서는 서버와 클라이언트의 중간에 GraphQL 이 레이어로 하나 더 있다고 보아야 함
    • 클라이언트는 서버까지 접근할 필요 없이 GraphQL 레이어와 통신하여 데이터를 가져오게 됨
    • 즉, 기존에 클라이언트에서 데이터를 조합하던 역할이 GraphQL 로 옮겨감
  • 이는 결국 역할의 분리
    • 모듈과 라이브러리를 만드는 이유도 모두 역할의 분리
    • 하지만 모듈로 역할을 분리하면 분리할수록 개별 모듈의 유지보수는 쉬워지지만 구현은 복잡해짐
    • 이 때문에 간단한 앱은 단일 모듈로 만들고 앱의 크기가 커지면 커질수록 모듈을 분리하는 것
  • 마찬가지로 GraphQL 을 만들면 클라이언트에서는 통신 로직의 구현이 편해지지만 그만큼 서버에서는 일이 가중됨
    • 따라서 서비스의 규모와 사이즈에 따라 GraphQL 도입을 결정하는 것이 좋음

Tip! GraphQL단점

  • 고정된 요청과 응답만 필요할 때에는 쿼리로 인해 요청의 크기가 Restful 보다 커질 수 있음
  • 캐싱이 REST 보다 복잡
  • 파일 업로드 구현 방법이 정해져있지 않아 직접 구현해야 함
profile
🌱 Backend-Dev | hwaya2828@gmail.com

0개의 댓글