GraphQL 스키마 설계

기운찬곰·2020년 9월 10일
0

GraphQL

목록 보기
4/6
post-thumbnail

🚀 The Schea Definition Language (SDL)

REST가 엔드포인트 집합이었다면, GraphQL은 타입 집합입니다. 그리고 이런 데이터 타입 집합을 스키마라고 부릅니다. 스키마를 정의하는 언어는 줄여서 SDL이고요.

1. 타입 정의하기

타입은 GraphQL의 핵심단위입니다. 이를 보고 애플리케이션의 핵심기능을 알 수 있죠. 쿼리 예제와 마찬가지로 snowtooth를 이해를 돕기 위해 사용하도록 하겠습니다.

  • Lift 타입은 ID 타입인 id과 String 타입인 name 등 해서 총 7개의 필드를 가집니다.
  • !는 non-nullable(=null 값을 허용하지 않음) 이란 의미입니다. 클라이언트가 쿼리를 호출한다고 했을때 서버가 반드시 반환해줘야 한다는 뜻입니다. (인자로 썼을때는 클라이언트가 반드시 서버에게 넘겨줘야 하는 값을 의미합니다)
  • ID는 형태는 문자열이기는 하나 고유한 값인지를 검사 해줍니다.

2. Object & Scalar 타입

GraphQL에는 두 가지 종류의 타입이 존재합니다.

  • Int, Float, String, Boolean, ID 총 5개는 GraphQL 내장 스칼라 타입입니다. 스칼라 타입은 객체 타입이 아니기 때문에 필드를 가지지 않습니다.
  • 객체(Object) 타입은 해당 타입의 특성을 표현하는 필드들로 구성됩니다. 객체 타입의 예시로는 위에서 살펴본 Lift, Trail 타입 등이 있습니다.

모든 GraphQL 스키마에서 고유한 스칼라 또는 객체 타입을 정의할 수 있습니다. 별도로 정의한 스칼라 타입의 대표적인 예시는 Date 타입으로, 이 타입을 구현할 때에는 타입의 유효성 검사, 직렬화, 역직렬화 방법 등을 모두 정의해야 합니다.

하지만 사용하기 쉽도록 npm 모듈로 만들어진게 이미 있습니다.

npm 모듈 : https://www.npmjs.com/package/graphql-custom-types


3. Enums 타입

GraphQL에서는 열거 타입(Enums)를 정의할 수 있습니다. Enums 타입이란 일정한 값들의 집합에 대하여 의미를 표현할 수 있는 언어 기능입니다.

미리 정의해둔 세트에 속하는 값만 필드에서 반환하도록 만들고 싶다면 열거 타입을 사용하면 됩니다.

위에서 본 LiftStatus가 바로 Enums 타입으로 정의한 것입니다.


4. 리스트

리스트는 GraphQL 타입을 대괄호를 감싸서 만들면 됩니다. 아래 처럼 말이죠.

근데 느낌표가 두개입니다.. 음.. 정리해보면 아래와 같습니다.

  • [String] : 리스트안에 담긴 String는 null이 될 수 있다.
  • [String!] : 리트안에 담긴 String는 null이 될 수 없다.
  • [String]! : 리스트안에 담긴 String는 null이 될 수 있으나, 리스트 자체는 null이 될 수 없다.
  • [String!]! : 리스트안에 담긴 String는 null이 될 수 없고, 리스트 자체도 null이 될 수 없다.

예를 들어 [String!]에서 허용되는 경우와 안되는 경우는 어떤게 있을까요? 리스트 자체가 null이 되어도 상관없지만 안에 들어가는 내용물이 null이 되면 안됩니다.

myField: null // valid
myField: [] // valid
myField: ['a', 'b'] // valid
myField: ['a', null, 'b'] // error

이번에는 [String]!인 경우를 살펴보겠습니다. 여기서 주의할거는 자바스크립트에서 []는 null이랑 같지만 graphql에서 []는 허용이 됩니다. 😨😨

myField: null // error
myField: [] // valid
myField: ['a', 'b'] // valid
myField: ['a', null, 'b'] // valid

뭐 일반적인 경우에는 4번째가 많이 쓰이는거 같습니다.


5. 관계

커스텀 객체 타입으로 필드를 만들면 두 객체가 서로 연결됩니다.

1대1 관계

예를들어, 아래는 Lift와 Trail이 1대1로 연결되어있는 상태를 정의했습니다. "Lift는 반드시 한개의 접근가능한 코스 1개를 가지고 있다" 이런 의미겠네요.

type Lift {
  id: ID!
  name: String!
  trailAccess: Trail!
}

1대다 관계

Trail은 여러개의 접근가능한 Lift를 가질 수 있도록 설정했습니다.

type Trail {
  id: ID!
  name: String!
  accessedByLifts: [Lift!]!
}

다대다 관계

다대다 관계를 만들려면 양쪽 모두에 리스트 타입 필드를 추가하면 됩니다.

type Lift {
  id: ID!
  name: String!
  trailAccess: [Trail!]!
}
type Trail {
  id: ID!
  name: String!
  accessedByLifts: [Lift!]!
}

6. Union 타입 / Interface

리스트에 항상 같은 타입만 들어가지 않는다는 것은 지난 시간에 배웠습니다. Union과 Interface를 이용하면 여러타입도 가능합니다. 저번시간에 배웠던거라서 여기서는 생략하겠습니다.


마침

그외에도 Mutation, Subscription, Input 타입 등이 있지만 저번시간과 중복되는 내용이기도 하고 해서 다음시간부터는 바로 실습을 진행해보도록 하겠습니다.

profile
배움을 좋아합니다. 새로운 것을 좋아합니다.

0개의 댓글