GraphQL의 가장 큰 강점 중 하나는 정적 타입 시스템 기반의 명확한 구조이다. 서버에서 스키마(Schema)를 정의하고, 클라이언트는 그 구조에 따라 안전하게 쿼리를 작성할 수 있다.
GraphQL 스키마란?
GraphQL 스키마는 API에서 제공하는 모든 기능과 데이터 구조를 정의하는 설계도이다.
즉, 어떤 데이터를 어떻게 요청하고, 어떤 형식으로 응답받을지를 명시하는 계약서 역할을 한다.
📌 스키마는 쿼리, 뮤테이션, 타입, 디렉티브 등을 포함하여 구성된다.
GraphQL 스키마 구성 요소
- 타입 정의(Type Definition): 데이터 구조를 정의
- 쿼리 및 뮤테이션(Query and Mutation): 데이터 읽기/쓰기 정의
- 디렉티브(Directives): 실행 방식 제어
스키마는 다음을 정의한다.
- 어떤 데이터 타입이 존재하는지
- 어떤 쿼리(Mutation/Subscription)를 호출할 수 있는지
- 각 필드가 어떤 타입을 반환하는지
- 어떤 인자를 받을 수 있는지
🧩 GrphQL 타입 시스템 소개
GraphQL은 타입 시스템을 기반으로 쿼리와 뮤테이션을 수행한다. 모든 데이터 요소는 특정 타입에 속하며, 타입은 필드와 리졸버를 가진다.
타입의 종류
- 스칼라 타입 (Scalar Types)
- 객체 타입 (Object Types)
- 인터페이스 타입 (Interface Types)
- 유니온 타입 (Union Types)
- 열거형 타입 (Enum Types)
- 입력 객체 타입 (Input Object Types)
🔸 스칼라 타입 (Scalar Types)
가장 기본적인 타입으로 단일 값을 나타낸다.
타입 | 설명 |
String | 문자열 |
Int | 32비트 정수 |
Float | 부동 소수점 숫자 |
Boolean | true 또는 false |
ID | 고유 식별자 (보통 문자열로 처리) |
type User {
id: ID!
name: String!
age: Int
verified: Boolean
}
🔸 객체 타입 (Object Types)
GraphQL에서 복잡한 데이터를 표현하는 핵심 타입으로, 하나 이상의 필드를 포함하며, 각 필드는 또 다른 타입을 가질 수 있다.
type Book {
id: ID!
title: String!
author: Author!
}
type Author {
id: ID!
name: String!
books: [Book]
}
🔸 인터페이스 타입 (Interface Types)
공통 필드를 정의하는 추상 타입으로, 여러 타입이 이를 구현할 수 있으며, 여러 타입을 일반화할 때 사용한다.
인터페이스를 구현하는 객체는 해당 인터페이스의 모든 필드를 구현해야 한다.
interface Character {
id: ID!
name: String!
}
type Hero implements Character {
id: ID!
name: String!
power: String
}
🔸 유니온 타입 (Union Types)
하나의 필드가 여러 서로 다른 타입 중 하나를 반환할 수 있을 때 사용한다.
union SearchResult = Book | Author
type Query {
search(keyword: String!): [SearchResult]
}
🔸 열거형 타입 (Enum Types)
제한된 값의 집합을 표현할 수 있는 타입이다.
enum BookStatus {
DRAFT
PUBLISHED
ARCHIVED
}
type Book {
id: ID!
title: String!
status: BookStatus!
}
🔸 입력 객체 타입 (Input Object Types)
Mutation 같은 데이터 변경 작업에서 입력값을 명시적으로 정의할 수 있는 타입이다.
input CreateBookInput {
title: String!
authorId: ID!
}
mutation {
createBook(input: CreateBookInput!): Book
}
🔁 List와 Non-Null 타입
books: [Book!]! // Book 배열이며, null 없음
- List: 배열 형태의 값 (예: [Book])
- Non-Null: ! 기호를 통해 null을 허용하지 않음
📌 전체 예제 스키마
type Query {
getBook(id: ID!): Book
search(keyword: String!): [SearchResult]
}
type Mutation {
createBook(input: CreateBookInput!): Book
}
type Book {
id: ID!
title: String!
author: Author!
status: BookStatus!
}
type Author {
id: ID!
name: String!
books: [Book]
}
enum BookStatus {
DRAFT
PUBLISHED
ARCHIVED
}
input CreateBookInput {
title: String!
authorId: ID!
}
union SearchResult = Book | Author
스키마 확장 (Schema Extension)
GraphQL은 매우 유연한 구조로, 기존 스키마에 새로운 타입이나 필드를 추가하는 것이 가능하다.
새로운 타입 추가
type Mutation {
createUser(name: String!): User
}
type User {
id: ID!
name: String!
}
기존 타입 확장
extend type User {
age: Int
}
사용자 정의 스칼라 타입 (Custom Scalar Types)
GraphQL 기본 타입 외에도 사용자 정의 스칼라 타입을 만들 수 있다.
Custom Date Type
scalar Date
type Event {
id: ID!
title: String!
startAt: Date!
}
- 서버에서 Date 타입에 대해 파싱/직렬화 로직을 직접 구현해야 한다.
import graphql.language.StringValue;
import graphql.schema.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class DateScalar {
public static final GraphQLScalarType DATE = GraphQLScalarType.newScalar()
.name("Date")
.description("Custom scalar for LocalDate")
.coercing(new Coercing<LocalDate, String>() {
private final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE;
@Override
public String serialize(Object dataFetcherResult) {
return ((LocalDate) dataFetcherResult).format(formatter);
}
@Override
public LocalDate parseValue(Object input) {
return LocalDate.parse(input.toString(), formatter);
}
@Override
public LocalDate parseLiteral(Object input) {
if (input instanceof StringValue) {
return LocalDate.parse(((StringValue) input).getValue(), formatter);
}
throw new CoercingParseLiteralException("Invalid date format");
}
})
.build();
}
Custom Email Type
scalar Email
type User {
id: ID!
email: Email!
}
- 이메일 포맷 검증을 추가할 수 있어 데이터 무결성 향상에 도움을 준다.
📌 커스텀 스칼라 타입은 GraphQLScalarType을 통해 정의되며, 유효성 검사 로직 포함이 가능하다.
'기술(Tech) > Network & System' 카테고리의 다른 글
[GraphQL] GraphQL 쿼리(Query) vs 뮤테이션(Mutation) (0) | 2025.03.16 |
---|---|
[GraphQL] GraphQL 쿼리(Query) 언어 (0) | 2025.03.16 |
[GraphQL] GraphQL 개요 (0) | 2025.03.15 |
[gRPC] gRPC의 보안 계층 🔒 (0) | 2025.03.15 |
[gRPC] gRPC 예외 처리 및 에러 핸들링 (0) | 2025.03.13 |
GraphQL의 가장 큰 강점 중 하나는 정적 타입 시스템 기반의 명확한 구조이다. 서버에서 스키마(Schema)를 정의하고, 클라이언트는 그 구조에 따라 안전하게 쿼리를 작성할 수 있다.
GraphQL 스키마란?
GraphQL 스키마는 API에서 제공하는 모든 기능과 데이터 구조를 정의하는 설계도이다.
즉, 어떤 데이터를 어떻게 요청하고, 어떤 형식으로 응답받을지를 명시하는 계약서 역할을 한다.
📌 스키마는 쿼리, 뮤테이션, 타입, 디렉티브 등을 포함하여 구성된다.
GraphQL 스키마 구성 요소
- 타입 정의(Type Definition): 데이터 구조를 정의
- 쿼리 및 뮤테이션(Query and Mutation): 데이터 읽기/쓰기 정의
- 디렉티브(Directives): 실행 방식 제어
스키마는 다음을 정의한다.
- 어떤 데이터 타입이 존재하는지
- 어떤 쿼리(Mutation/Subscription)를 호출할 수 있는지
- 각 필드가 어떤 타입을 반환하는지
- 어떤 인자를 받을 수 있는지
🧩 GrphQL 타입 시스템 소개
GraphQL은 타입 시스템을 기반으로 쿼리와 뮤테이션을 수행한다. 모든 데이터 요소는 특정 타입에 속하며, 타입은 필드와 리졸버를 가진다.
타입의 종류
- 스칼라 타입 (Scalar Types)
- 객체 타입 (Object Types)
- 인터페이스 타입 (Interface Types)
- 유니온 타입 (Union Types)
- 열거형 타입 (Enum Types)
- 입력 객체 타입 (Input Object Types)
🔸 스칼라 타입 (Scalar Types)
가장 기본적인 타입으로 단일 값을 나타낸다.
타입 | 설명 |
String | 문자열 |
Int | 32비트 정수 |
Float | 부동 소수점 숫자 |
Boolean | true 또는 false |
ID | 고유 식별자 (보통 문자열로 처리) |
type User {
id: ID!
name: String!
age: Int
verified: Boolean
}
🔸 객체 타입 (Object Types)
GraphQL에서 복잡한 데이터를 표현하는 핵심 타입으로, 하나 이상의 필드를 포함하며, 각 필드는 또 다른 타입을 가질 수 있다.
type Book {
id: ID!
title: String!
author: Author!
}
type Author {
id: ID!
name: String!
books: [Book]
}
🔸 인터페이스 타입 (Interface Types)
공통 필드를 정의하는 추상 타입으로, 여러 타입이 이를 구현할 수 있으며, 여러 타입을 일반화할 때 사용한다.
인터페이스를 구현하는 객체는 해당 인터페이스의 모든 필드를 구현해야 한다.
interface Character {
id: ID!
name: String!
}
type Hero implements Character {
id: ID!
name: String!
power: String
}
🔸 유니온 타입 (Union Types)
하나의 필드가 여러 서로 다른 타입 중 하나를 반환할 수 있을 때 사용한다.
union SearchResult = Book | Author
type Query {
search(keyword: String!): [SearchResult]
}
🔸 열거형 타입 (Enum Types)
제한된 값의 집합을 표현할 수 있는 타입이다.
enum BookStatus {
DRAFT
PUBLISHED
ARCHIVED
}
type Book {
id: ID!
title: String!
status: BookStatus!
}
🔸 입력 객체 타입 (Input Object Types)
Mutation 같은 데이터 변경 작업에서 입력값을 명시적으로 정의할 수 있는 타입이다.
input CreateBookInput {
title: String!
authorId: ID!
}
mutation {
createBook(input: CreateBookInput!): Book
}
🔁 List와 Non-Null 타입
books: [Book!]! // Book 배열이며, null 없음
- List: 배열 형태의 값 (예: [Book])
- Non-Null: ! 기호를 통해 null을 허용하지 않음
📌 전체 예제 스키마
type Query {
getBook(id: ID!): Book
search(keyword: String!): [SearchResult]
}
type Mutation {
createBook(input: CreateBookInput!): Book
}
type Book {
id: ID!
title: String!
author: Author!
status: BookStatus!
}
type Author {
id: ID!
name: String!
books: [Book]
}
enum BookStatus {
DRAFT
PUBLISHED
ARCHIVED
}
input CreateBookInput {
title: String!
authorId: ID!
}
union SearchResult = Book | Author
스키마 확장 (Schema Extension)
GraphQL은 매우 유연한 구조로, 기존 스키마에 새로운 타입이나 필드를 추가하는 것이 가능하다.
새로운 타입 추가
type Mutation {
createUser(name: String!): User
}
type User {
id: ID!
name: String!
}
기존 타입 확장
extend type User {
age: Int
}
사용자 정의 스칼라 타입 (Custom Scalar Types)
GraphQL 기본 타입 외에도 사용자 정의 스칼라 타입을 만들 수 있다.
Custom Date Type
scalar Date
type Event {
id: ID!
title: String!
startAt: Date!
}
- 서버에서 Date 타입에 대해 파싱/직렬화 로직을 직접 구현해야 한다.
import graphql.language.StringValue;
import graphql.schema.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class DateScalar {
public static final GraphQLScalarType DATE = GraphQLScalarType.newScalar()
.name("Date")
.description("Custom scalar for LocalDate")
.coercing(new Coercing<LocalDate, String>() {
private final DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE;
@Override
public String serialize(Object dataFetcherResult) {
return ((LocalDate) dataFetcherResult).format(formatter);
}
@Override
public LocalDate parseValue(Object input) {
return LocalDate.parse(input.toString(), formatter);
}
@Override
public LocalDate parseLiteral(Object input) {
if (input instanceof StringValue) {
return LocalDate.parse(((StringValue) input).getValue(), formatter);
}
throw new CoercingParseLiteralException("Invalid date format");
}
})
.build();
}
Custom Email Type
scalar Email
type User {
id: ID!
email: Email!
}
- 이메일 포맷 검증을 추가할 수 있어 데이터 무결성 향상에 도움을 준다.
📌 커스텀 스칼라 타입은 GraphQLScalarType을 통해 정의되며, 유효성 검사 로직 포함이 가능하다.
'기술(Tech) > Network & System' 카테고리의 다른 글
[GraphQL] GraphQL 쿼리(Query) vs 뮤테이션(Mutation) (0) | 2025.03.16 |
---|---|
[GraphQL] GraphQL 쿼리(Query) 언어 (0) | 2025.03.16 |
[GraphQL] GraphQL 개요 (0) | 2025.03.15 |
[gRPC] gRPC의 보안 계층 🔒 (0) | 2025.03.15 |
[gRPC] gRPC 예외 처리 및 에러 핸들링 (0) | 2025.03.13 |