Programming Guide/GraphQL

GraphQL 시작하기

발효홍삼 2023. 1. 19. 04:15
728x90

What is GraphQL?

GraphQL은 React.js를 개발한 meta(전 facebook)에서 개발하였으며 기존의 REST API가 가진 단점을 극복하기 위해 개발되었다.

GraphQL은 QueryLanguage를 통해 연결되어 있는 데이터를 필요한 데이터만 골라 전송받을 수 있게 만들어준다.

또 GraphQL은 개발자가 단일 API 호출로 다양한 데이터 소스에서 데이터를 끌어오는 요청을 구성할 수 있도록 지원한다.

GraphQL의 쿼리는 직관적으로 구성되어 있다.

Content 스키마 중 contentId, contentTitle 그리고 comment 스키마 중 commentId, commentBody만을 담은 Array가 반환될 것이다.

//쿼리
{
  content {
    contentId
    contentTitle
    comments {
      commentId
      commentBody
    }
  }
}
//응답
{
  "data": {
    "content": {
      "contentId": "ct1",
      "contentTitle": "title",
      "comments": [
        {
          "commentId": "comment1",
          "commentBody": "comment"
        }
      ]
    }
  }
}

GraphQL 쿼리 용어

  • Fields
//Field
{
  content {
    contentId
  }
}

위 쿼리에서 contentId가 Field이다.

  • Arguments
//Arguments
{
  content(id : 1) {
    contentId
  }
}

쿼리에 인자를 넣어 보낼 수도 있다. int 형 외에도 다양한 자료형과 사용자 정의형도 보낼 수 있다.

  • Aliases
//쿼리
{
  content1 : content(id : 1) {
    contentId
  }
  content2 : content(id : 2) {
    contentId
  }
}

//응답
{
  "data" : {
    "content1" : {
      "contentId" : "1"
    },
    "content2" : {
      "contentId" : "2"
    }
  }
}

Aliases는 쿼리의 앞에 위치하여 사용된다. 위의 예시와 같이 인자만 다른 같은 쿼리를 보낼 때 Aliases를 사용하지 않는다면 응답에서 어느 것이 content 데이터가 될지 몰라 오류가 날 것이며 이를 해결하기 위해 Aliases를 사용한다.

  • Fragments
//Fragments
{
  content1 : content(id : 1) {
    ...fields
  }
  content2 : content(id : 2) {
    ...fields
  }
  
  fragment fields on Character {
    contentId
    contentTitle
  }
}​

Fragment는 쿼리에서 불필요한 반복을 줄이기 위해 사용된다. 공통부분은 Fragment로 따로 빼서 사용할 수 있다.

  • Operation Name
query {
  content : {
    contentId
  }
}​

꼭 필요하지 않지만 쿼리의 목적을 위해 맨 앞에 명시할 수 있다. Operation Name에는 query,  mutation, subscription이 있다.

  • Variables
query getContents($contentId : Int) {
  content(id : $contentId) : {
    contentId
  }
}

클라이언트 쪽에서 쿼리를 보낼 때 쿼리 내에 static하게 인자를 넣어 보내는 경우는 흔치 않기 때문에 변수를 사용한다.

서버 측 GraphQL

GraphQL에서도 SQL를 사용할 때 처럼 스키마를 작성해야 한다. 스키마는 *.graphqls 확장자 파일로 생성해야 한다. 그리고 classPath 내 어디에든 존재 가능하며 개수도 제한이 없지만 루트 Query와 루트 Mutation이 존재해야 한다.

// *.graphqls 파일

type Content {
  contentId: ID!
  contentTitle: String!
  contentBody: String
  comments: [Comment]
}

type Comment {
  commentId: ID!
  commentBody: String
}

// Root Query
type Query {
  contentList: [Content]
}

extend type Query {
  commentList: [Comment]
}

type Mutation {
  writeContent(title: String!, body: String): Int
}

schema {
  query: Query
  mutation: Mutation
}
  • type Content, Comment
    DB에서 Content 테이블과 Comment 테이블을 만드는 것과 같은 역할
    - Content, Comment : 오브젝트 타입
    - contentId, commentId... : 필드
    - (!) : 필수값
    - [] : 배열
  • type Query, Mutation
    기본적으로 루트 Query와 루트 Mutation을 의미한다. 이것들을 단 하나씩만 존재해야 하며 이름은 아래의 schema를 이용해 변경할 수도 있다.
  • extend
    스키마 파일에서 이름이 같은 오브젝트는 있을 수 없다. 하지만 파일 또는 오브젝트를 분리하고 싶을 수도 있기 때문에 exnted를 이용해 오브젝트를 확장 및 분리할 수 있다. 이외에도 여러 방식으로 사용된다.
  • schema
    스키마 내의 루트 Query와 루트 Mutation, Subscription을 지정할 수 있다. 이것은 명시적인 표현으로서 작동하며 명시하지 않으면 스키마 파일 내의 "Query", "Mutation", "Subscription" 이름을 가진 오브젝트가 루트 오브젝트가 된다.

 

728x90