GraphQL이란?

moontag·2022년 8월 2일
0

GraphQL

목록 보기
1/1

탄생 배경

Meta(Facebook)에서 만든 API를 위한 Query 언어다. 기존 REST API 한계점 을 극복할 수 있다.


REST API 한계점?

  1. URL,METHOD ...조합하기 때문에 다양한 Endpoint가 존재.

  2. 클라이언트 구조변경 시 엔드포인트 변경이나 데이터 수정 필요.
    서버에서 자원의 크기,형태를 결정하므로 클라이언트에서 필요한 데이터 변경 시 다른 엔드포인트로 변경된 데이터 수정하거나 가져와야 함

  3. Over fetching, Under fetching 발생.

  • Over fetching
    요청영역보다 많은 정보를 받은 것.

    • 리소스 낭비로 비효율적.
    • ex) username 하나만 필요한데 그 외 모든 데이터 받아와짐
  • Under fetching
    모든 정보 얻기 위해 많은 요청해야 함.

    • 각 자원에 따라 엔드포인트 구분하므로 각 엔드포인트마다 요청해야 함

    • ex) 앱 시작하면 피드,알림,프로필... 요청해야함




REST API와 GraphQL 차이점

REST APIGraphQL
리소스 형태정의와 데이터 요청 방법연결됨분리됨
리소스 크기,형태 결정서버가 결정리소스 정보만 정의하고 필요한 크기,형태는 클라이언트 단에서 요청 시 결정
리소스 / 작업 유형URI가 리소스 나타내고, Method가 작업 유형 나타냄Schema가 리소스 나타내고, Query, Mutation 타입이 작업 유형 나타냄
요청 횟수리소스 접근할 때 여러번 요청여러 리소스들 한번 요청으로 접근 가능
작업 처리각 요청은 엔드 포인트에 정의된 핸들링함수 호출하여 작업 처리요청받은 각 필드에 대한 resolver 호출하여 작업 처리






GraphQL

Graph + Query Language

  • Graph란?
    마인드맵처럼 여러 정점(vertex) 또는 Node가 간선(edge)으로 연결되어 있는 자료구조다. 그래프를 어느입장에서 정렬하는지에 따라 트리구조를 이룰 수 있다.

장점

  • 클라이언트는 원하는 데이터만 받을 수 있음
  • URL 체계 없음
  • 1개의 Endpoint로 요청
    모든 클라이언트 요청은 POST 메소드 사용
  • 모든 것을 한개의 쿼리로 만들 수 있음
  • Over fetching, Under fetching의 문제 해결
  • playground GUI
    grqphql 서버 실행하면 GUI에서 resolver, schema 데스트 가능
  • 클라이언트 구조 변경해도 서버에 지장 없음
    필요한 데이터 결정하고 받는 주체가 클라이언트이므로 서버에 지장 없음

단점

  • 고정된 요청/응답만 필요할 시 Query 때문에 요청 크기가 RESTful API 보다 커짐
  • 캐싱이 REST보다 복잡함
    • GraphQL에선 POST 메소드만으로 요청 보내기 떄문에 각 메소드에 따른 캐싱을 지원받을 수 없다. 이를 보안하기 위해 Apollo 엔진의 캐싱과 영속 쿼리 등이 등장했다.



특징

  • 클라이언트 요청에 따른 유연한 트리구조 JSON 데이터를 응답으로 전송 가능
  • HTTP통해 API서버로 요청/응답 받음
  • 응답은 데이터 결과를 JSON형식으로 받음
  • 서버가 작성한 각 필드에 대응하는 resolver함수로 각 필드 데이터 조회 가능
  • GraphQL 라이브러리가 조회대상 schema가 유효한지 검사





GraphQL 구조

  • Query : 데이터 읽기(R) 서버에 요청

  • Mutation : 데이터 변조(CUD) 한다는 규약 정한 것

  • schema : 내가 사용자에게 보내거나 받을 data에 대한 설명

  • resolver : Query를 해결하는 해결사. 서버가 Query나 Mutation 정의 발견하면 resolver를 찾아서 함수 실행한다.

  • Subscription: 특정 이벤트가 발생 시, 서버가 대응하는 데이터를 실시간으로 클라이언트에게 전송

    • 발행/구독(pub/sub) 모델을 따름
      클라이언트가 어떤 이벤트를 구독하면, 클라이언트는 서버와 WebSocket을 기반으로 지속적인 연결을 유지한다. 그 후 특정 이벤트가 발생하면, 서버는 대응하는 데이터를 클라이언트에 전송해준다.



Query

데이터 조회

  • 필드(field)
  • 전달인자(Arguments)
# 요청
{
  human(id: "1000") { # 인자로 원하는 값만 받아오기
    name   # 필드
    height # 필드
  }
}
# 응답결과
{
  "data": {
    "human": {
      "name": "Luke Skywalker",
      "height": 1.72
    }
  }
}
  • 별명(Aliases)
    필드명 중복 불가하므로 , 중복해서 쿼리할 때는 별명을 붙인다
# bad
{
	hero(episode: EMPIRE) {
    name
  }
  hero(episode: JEDI) {
    name
  }
}

# good
{
  empireHero: hero(episode: EMPIRE) {
    name
  }
  jediHero: hero(episode: JEDI) {
    name
  }
}
# 응답
{
  "data": {
    "empireHero": {
      "name": "Luke Skywalker"
    },
    "jediHero": {
      "name": "R2-D2"
    }
  }
}

  • 오퍼레이션 타입(Operation type)
    : query, mutation, subscription, describes

  • 오퍼레이션 네임(Operation name)
    : 오퍼레이션 타입에 맞는 이름으로 작성

쿼리 keyword(query)와 쿼리 name(HeroNameAndFriends)을 작성해야 한다.

query HeroNameAndFriends {
  hero {
    name
    friends {
      name
    }
  }
}

  • 변수(Variables)
    동적으로 인수 받기 위해서 변수 사용
    ($변수 이름: 타입 형태)
    • ($변수 이름: 타입 형태!) : 뒤에 !붙이면 필수여야 한다는 뜻(optional)
query HeroNameAndFriends($episode: Episode) {
  hero(episode: $episode) {
    name
    friends {
      name
    }
  }
}



Mutation

데이터 수정

  • mutation 키워드를 사용하여 서버 측 데이터 수정
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
  createReview(episode: $ep, review: $review) {
    stars
    commentary
  }
}



Schema/Type

사용자에게 보내거나 받을 data에 대한 설명

  • 구성요소
    서비스에서 가져올 수 있는 객체 종류, 포함하는 필드를 나타내는 객체 유형
type Character {
  name: String!
  appearsIn: [Episode!]!
}
  • Character
    : GraphQL 객체 타입이며 필드가 있는 타입임을 의미.
    스키마에 있는 대부분은 객체 타입.

  • name , appearIn
    : Character 타입의 필드 field.
    GraphQL 쿼리의 Character 타입 어디서나 사용 가능한 필드.

  • String
    : 내장된 스칼라 타입 중 하나.
    단일 스칼라 객체로 확인되는 유형이며 쿼리에서 하위 선택을 가질 수 없다. 스칼라 타입에는 ID, Int도 있다.

  • !가 붙으면 이 필드는 nullable하지 않고 반드시 값이 들어온다는 의미. 반드시 값을 받을 수 있다는 예상을 할 수 있다.

  • [ ] : 배열을 의미.
    배열에도 !가 붙을 수 있다. null 값을 허용안하므로 항상 0개 이상의 요소를 포함한 배열을 예상을 할 수 있다.



Resolver

Query를 해결하는 것.

  • 서버가 Query, Mutation, Subscription 타입의 스키마 정의를 발견하면 스키마 필드에 해당하는 resolver 함수 찾아서 실행한다.
  • 데이터 가져오는 구체적인 과정(ex. 데이터베이스 쿼리, 원격 API 요청)을 Resolver가 담당함.
const db = require("./../db")
const resolvers = {
  Query: { // **Query :** 저장된 데이터 가져오기 (REST 에 GET 과 비슷합니다.)
		getUser: async (_, { email, pw }) => {
			db.findOne({
				where: { email, pw }
			}) ... // 실제 디비에서 데이터를 가져오는 로직을 작성합니다. 
			...
		}
  },
  Mutation: { // **Mutation :** 저장된 데이터 수정하기 ( Create , Update , Delete )
		createUser: async (_, { email, pw, name }) => {
			...
		}
  }
  Subscription: { // **Subscription :** 실시간 업데이트
    newUser: async () => {
      ...
		}
  }
};





참조

kakao Tech - GraphQL 개념잡기

GraphQL의 Learn

profile
터벅터벅 나의 개발 일상

0개의 댓글