ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • GraphQL (Schema & Type)
    Graphql 2023. 4. 23. 11:06

    2023.04.16 - [Graphql] - GraphQL이란에 이어서 GraphQL에 대해 더 알아보도록 하겠다.

    지금까지는 Rest API를 대체할 수 있는 무언가가 있고 그게 GraphQL이 될 수 있다 까지 생각할 수 있다.
    지난 글에서는 아래와 같이 GraphQL에 대한 두 가지 장점이 있었다.

    • Schema를 정해 데이터의 일관성을 보장할 수 있다.
    • Client에서 필요한 data만을 요청하기에 overfetching을 줄일 수 있다.

    그럼 이제부터 GraphQL에 대해 더 자세히 알아보도록 하자.

    Schema & Type

    우선 설명에 앞서 아래와 같은 User에 대한 예시 Shema을 작성하겠다.

    #user.graphqls
    
    #enum type 선언
    enum Gender {
      MALE
      FEMALE
    }
    
    #user type 선언
    type User {
      uid: Int!
      email: String!
      name: String!
      phone: String
      gender: Gender!
      favorite_friends:[Int!]
      birth_date: Time!
      created_at: Time!
      updated_at: Time!
    }
    
    #user input 선언
    input UserInput { 
      uid: Int64!
    }
    
    #create user input 선언
    input CreateUserInput {
      email: String!
      name: String!
      phone: String
      gender: gender!
      birth_date: Time!
    }
    
    #update user input 선언
    input UpdateUserInput {
      email: String!
      name: String!
      phone: String
      gender: gender!
      birth_date: Time!
    }
    
    input UpdateUserFavoriteFiendsInput {
      uid: Int!
      friends: [Int!]!
    }
    
    #delete user input 선언
    input DeleteUserInput {
      uid: Int64!
    }

     여기서 type User와 같이 type으로 선언된 경우 요청 시 사용하는 field들을 정의한 것이고 input으로 선언될 경우 argument를 정의한 것이다.

     field뒤에 "!"를 붙이는 이유는 "!"가 있을 경우 non-null field이고 "!"가 없을 경우 nullable이다. 

     예를 들어 user.name의 경우 반드시 존재해야 하는 값이기 때문에 null일 시 문제가 있기 때문에 "!"를 붙였고 phone의 경우 없을 수 있기 때문에 "!"가 제외되어 있다.

      배열의 경우 [Int!]!와 같이 사용할 수 있는데 배열 내부에 "!"가 있을 경우 배열의 요소는 항상 Int값(선언한 타입의 값)이어야 한다. 또한 배열 뒤에 "!"가 있을 경우 [somethine]! 배열은 null이 아니고 0개 이상의 항목을 포함한 값이어야 한다.

    Query & Mutation

    Rest API의 경우 API의 사용 용도에 따라 GET, POST, PUT, DELETE 등과 같이 Method를 달리 사용한다. GET method는 read 시에 사용, POST method는 create시에 사용, PUT Method는 update에 사용, Delete Method는 delete 시에 사용한다.
     GraphQL 또한 Query / Mutation으로 이를 구분한다. Query는 read 용 그 외의 용도는 Mutation을 사용하면 된다.

     여기서는 간단하게 위에 선언한 Schema를 다루기 위한 Query & Mutation을 선언하겠다.

    scalar Time
    scalar Int64
    
    type Query {
      users: [User!]!
      user(input: userInput): User!
    }
    
    type Mutation {
      createUser(input: createUserInput!): User!
      updateUser(input: updateUserInput!): User!
      updateUserFavoriteFriends(input: updateUserFavoriteFriendsInput!): User!
      deleteUser(input: deleteUserInput!): String!
    }

    Type system

      graphql은 type system이다. graphql은 field를 select 함으로써 overfetching을 방지할 수 있다. 

    query{
      users{
        uid
        name
      }
    }

     위의 요청 예시를 보면 실제로 User에는 uid,name 뿐아니라 email, phone, gender 등이 있는데 이와 같이 uid, name만 요청하면 아래와 같이 uid, name의 정보만 받을 수 있다.

     Quey에서 선언한 Type 대로 users는 user의 배열을 받을 수 있다.

    {
      "data":{
        "users":{
          {
            "uid":1
            "name":"zzihyeon"
          },
          {
            "uid":2
            "name":"jihyeon"
          }
        }
      }
    }

     이와 같이 요청한 정보와 그 결과의 값의 형태가 일정하기 때문에 일관성이 유지된다. 모든 요청은 선언된 Schema내에서만 가능하기 때문에 Client는 요청 시 Schema를 먼저 확인해야 한다.

    Argument

     우리는 Schema를 정의할 때 "input"을 통해서 argument type을 정의했다. 그럼 이는 어떻게 사용할 수 있을까?

    예를 들어서 uid가 1인  user를 찾고 싶을 때 위에 선언한 "input UserInput" 을 사용할 수 있다. 만약 user 중 uid가 1인 user 정보만 받고 싶다면 아래와 같이 사용한다.

    query {
      user(input: {uid: 1}){
        uid
        name
      }
    }

     user query를 요청할 때 input에 UserInput을 넣으면 된다.

    {
      "data":{
        "user":{
          "uid":1
          "name":"zzihyeon"
        }
      }
    }

    Scalar

     GraphQL에서는 아래와 같은 Type만을 지원한다.

    • Int: A signed 32‐bit integer.
    • Float: A signed double-precision floating-point value.
    • String: A UTF‐8 character sequence.
    • Boolean: true or false.
    • ID: The ID scalar type represents a unique identifier, often used to refetch an object or as the key for a cache. The ID type is serialized in the same way as a String; however, defining it as an ID signifies that it is not intended to be human‐readable.

    따라서 우리가 원하는 type을 사용하기 위해서는 Scalar를 선언해야만 한다. 본인의 경우 Schema 선언 시 "Time"이라는 type을 사용했으며 이는 Query & Mutation선언에 나와 있듯이 아래와 같이 선언할 수 있다.

    scalar Time

    다음에는 interface & Union Type에 대해서 알아보도록 하자.

    'Graphql' 카테고리의 다른 글

    GraphQL에 대하여 ( Resolver & Dataloader / Aliases & Fragment)  (1) 2023.06.03
    GraphQL에 대하여 (Interface & Union Type)  (0) 2023.05.07
    GraphQL이란  (0) 2023.04.16
    DataLoader  (0) 2022.10.09

    댓글

Designed by Tistory.