타입 시스템이란?
타입 시스템은 GraphQL에서 데이터의 구조를 명확하게 정의해서 서버와 클라이언트 간의 데이터 전달을 일관되고 정확하게 해주는 중요한 개념이다.
GraphQL의 타입 시스템은 다음과 같은 요소로 구성된다.
Scalar Type | Int, Float, String, Boolean, ID |
Enum Type | 미리 정의된 값의 집합을 가지는 타입 |
Object Type | 여러 필드를 포함하는 복합 타입 |
Input Type | Mutation 인수로 사용되는 타입 |
Interface | 여러 객체 타입이 공통으로 가져야 하는 필드를 정의 |
Union Type | 여러 객체 타입 중 하나를 반환할 수 있는 타입 |
타입 시스템은 이런 요소들을 통해 데이터의 구조를 명확하게 정의한다.
그리고 이를 통해 인스트로스펙션과 AST기능을 제공할 수 있게 된다.
SDL이란?
SDL은 GraphQL 스키마를 작성하는 언어이다.
SDL을 사용해서 타입 시스템의 요소들을 문서화하고 GraphQL 스키마를 작성할 수 있다.
SDL은 굉장히 직관적이고 사람이 읽기 쉬운 문법으로 만들어졌다.
그래서 서버에서 스키마를 쉽게 작성하고 클라이언트에서는 쉽게 이해할 수 있게 해준다.
interface Product {
id: ID!
name: String!
price: Float!
productType: ProductType!
}
type Electronics implements Product {
id: ID!
name: String!
price: Float!
productType: ProductType!
warrantyPeriod: String
}
type Clothing implements Product {
id: ID!
name: String!
price: Float!
productType: ProductType!
size: String
}
input AddProductInput {
name: String!
price: Float!
productType: ProductType!
warrantyPeriod: String
size: String
}
type Cart {
id: ID!
userId: User!
items: [CartItem!]!
totalAmount: Float!
}
type Subscription {
newProduct: Product!
}: Product!
그럼 이제 스키마 작성을 위해 GraphQL의 타입들을 자세히 알아보자.
Scalar 타입
스칼라 타입은 GraphQL에서 기본적으로 제공하는 5가지 타입이 있다. (String, Int, Float, Boolean, ID)
각 타입들은 기본적으로 Null을 허용하는 Nullable타입이고, 느낌표를 통해 Non-Null 타입을 지정할 수 있다.
또 대괄호로 감싸면 리스트 타입으로 사용 가능하다.
일반적으로 서비스를 개발할 때 이 타입들만으로는 표현이 부족한 경우가 있다.
예를 들어 날짜나 시간 또는 URL이나 이메일 같은 것들이 될 수 있다.
GraphQL에서는 이런 문제를 위해 Custom Scalar 타입을 사용할 수 있다.
Custom Scalar 타입은 서버에서 추가적인 개발을 통해 사용자가 원하는 타입을 정의할 수 있다.
추가적으로 스칼라의 네이밍 컨벤션은 파스칼 케이스이다.
Enum 타입
선언하는 방법은 아래와 같다.
이름은 파스칼 케이스, 값들은 스네이크 케이스를 사용한다.
Object 타입
Object 타입은 타입 내부에 여러 필드를 포함할 수 있는 타입이다.
타입 키워드를 입력하고 타입의 이름을 정의한다.
내부 필드에는 Scalar 타입이나 Enum 타입, 다른 Object 타입들을 정의할 수 있다.
Object 타입의 네이밍 컨벤션은 파스칼 케이스이고 내부 필드는 카멜 케이스이다.
Input 타입
Input 타입은 Mutation이나 Query에서 인수로 사용되는 타입이다.
Input 키워드를 입력하고 타입의 이름을 정의한다.
내부 필드로는 Scalar 타입이나 Enum 타입 또는 다른 Input 타입이 될 수 있다.
Object 타입과 유사하지만 응답 타입으로 사용할 수 없고 입력으로만 사용된다. (Request DTO 역할?)
반대로 Object 타입은 입력으로 사용할 수 없다.
Input 타입의 네이밍 컨벤션은 파스칼 케이스이고, 필드 이름은 카멜케이스를 사용한다.
일반적으로 인풋 접두사를 사용한다.
Query 타입
Query 타입을 작성하는 방법은 타입 키워드와 쿼리를 같이 적으면 된다.
Query 타입의 입력으로는 Scalar 타입이나 Input 타입, Enum 타입을 사용할 수 있고 반대로 타입은 Scalar 타입과 Object 타입, Enum 타입을 사용할 수 있다.
내부 필드의 네이밍 컨벤션은 카멜 케이스를 사용한다.
쿼리의 내부에 정의된 필드는 각각 리졸버와 맵핑된다.
각 프로그래밍 라이브러리를 통해 리졸버의 함수를 쿼리 타입으로 명시하고 입력과 반환 타입을 맞춰야 한다.
Mutation 타입
데이터를 변경하는 데 사용되는 루트 타입이다.
작성하는 방법은 타입 키워드와 Mutation을 같이 입력해준다.
추가적으로 Mutation 타입을 만들 때 권장사항이 몇 가지 있다.
- 이름을 동사로 시작해야 한다.
- 하나의 역할만 가지고 두 개 이상의 역할을 가지면 안된다.(Upsert 하지 말라.!!)
- Mutation의 Input으로는 하나의 Input 타입 사용을 권장한다.
이러한 권장 사양을 지키면서 설계하면 더욱 간결하고 가독성 높은 API를 작성할 수 있다.
Mutation 타입 필드의 네이밍 컨벤션은 카멜 케이스를 사용한다.
Subscription 타입
실시간 데이터를 처리하는 데 사용되는 루트 타입이다.
실시간 채팅이나 새로운 제품 알림 같은 기능에 사용될 수 있다.
새로운 제품을 구독하는 서비스를 예시로 들어보자.
사용자는 Subscription 타입으로 새로운 제품을 구독하고, 관리자는 새로운 제품을 등록한다.
이 제품 정보는 서버에 저장되고 새로운 제품 정보를 서브스크립션에 반환한다.
반환된 정보는 구독하는 사용자들에게 실시간으로 전송되서 UI에 표시할 수 있다.
Subscription은 한 번으로 끝나지 않고 세션이 끊어지는 시점까지 계속된다.
네이밍 컨벤션은 마찬가지로 카멜 케이스를 사용한다.
Interface 타입
여러 타입이 공통으로 가져야 하는 필드를 정의한다.
인터페이스를 구현하는 오브젝트 타입은 인터페이스 타입에 정의된 모든 필드를 필수로 포함해야 한다.
만약 이런 인터페이스가 있고 이 인터페이스를 구현하는 오브젝트 타입이 있다면, Product 인터페이스 내부에 구현되어 있던 필드들을 필수로 구현해야 한다.
그리고 필요에 따라 구현 오브젝트 타입의 고유 필드를 추가로 구현할 수 있다.
내부 필드의 네이밍 컨벤션은 카멜 케이스를 사용한다.
Union 타입
공통 필드를 정의할 수 없는 여러 타입을 공통 타입으로 사용할 수 있는 타입이다.
공통적으로 구현되는 필드가 없는 오브젝트들을 하나의 타입으로 표현할 때 사용된다.
인터페이스처럼 강제로 필드를 구현할 필요가 없으며, 유니온 타입을 반환 타입으로 지정하면 유니온에 포함된 모든 타입을 반환할 수 있다.
유니온 타입의 네이밍 컨벤션은 파스칼 케이스이다.
'DEV > GraphQL' 카테고리의 다른 글
GraphQL 서버 동작 방식에 대해 공부해보자! (1) | 2025.01.03 |
---|---|
RESTAPI와 GraphQL의 차이점과 특징에 대해 공부해보자. (2) | 2025.01.01 |