GraphQL | A query language for your API
Facebook에서 개발한 API를 위한 쿼리언어입니다.
특정 정보를 받기 위해 여러개의 API를 호출(under-fetching) 하거나
단순한 정보를 위해 너무 큰 API를 호출(over-fetching) 하는 문제를 방지 할 수 있습니다.
REST API vs GraphQL
REST: 여러 엔드포인트 (/users, /posts, /comments 등)
GraphQL: 단일 엔드포인트 (/graphql)에서 모든 요청 처리
REST API:
GET /api/users
GET /api/users/1
POST /api/users
GET /api/users/1/posts
GraphQL:
POST /graphql
{
"query": "
// 사용자와 그의 게시글 조회
query {
user(id: 1) {
name
posts {
title
content
createdAt
}
}
}
"
}
POST /graphql
{
"query": "
// 게시글과 작성자, 댓글 정보 조회
query {
post(id: 1) {
title
content
author {
name
email
}
comments {
text
author {
name
}
}
}
}
"
}
SQL vs GraphQL
# SQL (여러 쿼리 필요)
SELECT * FROM users WHERE id = 1;
SELECT * FROM posts WHERE user_id = 1;
SELECT * FROM comments WHERE post_id IN (SELECT id FROM posts WHERE user_id = 1);
# GraphQL (단일 쿼리)
query {
user(id: 1) {
name
posts {
title
comments {
content
author {
name
}
}
}
}
}
즉, 많은 쿼리 or API 호출을 1개의 endpoint에서 처리가 가능합니다.
스키마
1. 3가지 root 타입
# 1. 데이터 조회
type Query {
getUser(id: ID!): User
getAllUsers: [User!]!
}
# 2. 데이터 변경
type Mutation {
createUser(input: UserInput!): User
updateUser(id: ID!, input: UserInput!): User
deleteUser(id: ID!): Boolean
}
# 3. 실시간 구독 (WebSocket)
type Subscription {
userCreated: User
userUpdated: User
}
2. 기본 스칼라 타입
Int # 정수
Float # 실수
String # 문자열
Boolean # true/false
ID # 고유 식별자
3. 객체 타입
# 요청 파라미터용 (DTO)
input UserInput {
name: String!
email: String!
}
# 응답/리턴 타입용
type User {
id: ID!
name: String!
email: String!
}
4. 기본 문법
! # Non-Null (필수값)
[] # List (배열)
@ # Directive (지시어)
... # Fragment (재사용)
$ # Variables (변수)
5. Spring GraphQL schema.graplqls 예시
# src/main/resources/graphql/schema.graphqls
# GraphQL 스키마 정의 파일
# 모든 GraphQL API의 진입점이 되는 타입 시스템을 정의합니다.
"""
Query 타입 - 모든 SELECT 작업
"""
type Query {
# 단일 사용자 조회
# @param id - 사용자 고유 식별자
# @return User 객체 또는 null
user(id: ID!): User
# 모든 사용자 목록 조회
# @return null이 아닌 User 객체 배열
users: [User!]!
# 페이지네이션이 적용된 사용자 조회
# @param page - 페이지 번호 (기본값: 1)
# @param size - 페이지 크기 (기본값: 10)
usersPaginated(page: Int = 1, size: Int = 10): UserConnection!
}
"""
Mutation 타입 - INSERT/UPDATE/DELETE 작업
"""
type Mutation {
# 새로운 사용자 생성
# @param input - 사용자 생성에 필요한 데이터
# @return 생성된 User 객체
createUser(input: UserInput!): User!
# 기존 사용자 정보 수정
updateUser(id: ID!, input: UserInput!): User!
# 사용자 삭제
deleteUser(id: ID!): Boolean!
}
"""
실시간 이벤트 Subscription 타입 - WebSocket 기반의 실시간 업데이트를 처리
"""
type Subscription {
# 새로운 사용자 생성 이벤트 구독
# @return 새로 생성된 User 객체
userCreated: User!
}
"""
객체 타입 - 기본적인 사용자 정보와 관계를 포함
"""
type User {
id: ID! # 필수 필드: 사용자 고유 식별자
name: String! # 필수 필드: 사용자 이름
email: String! # 필수 필드: 이메일 주소
age: Int # 선택 필드: 나이 (null 가능)
posts: [Post!]! # 필수 필드: 사용자의 게시글 목록
createdAt: DateTime! # 필수 필드: 생성 일시
}
type Post {
id: ID!
title: String!
content: String!
author: User! # User와의 관계 표현
comments: [Comment!]!
createdAt: DateTime!
}
type Comment {
id: ID!
content: String!
author: User!
post: Post!
createdAt: DateTime!
}
type UserConnection {
edges: [UserEdge!]! # 사용자 엣지 배열
pageInfo: PageInfo! # 페이지 정보
totalCount: Int! # 전체 사용자 수
}
type UserEdge {
node: User! # 실제 사용자 데이터
cursor: String! # 페이지네이션 커서
}
type PageInfo {
hasNextPage: Boolean! # 다음 페이지 존재 여부
hasPreviousPage: Boolean! # 이전 페이지 존재 여부
startCursor: String # 현재 페이지의 시작 커서
endCursor: String # 현재 페이지의 마지막 커서
}
input UserInput {
name: String! # 필수 입력: 사용자 이름
email: String! # 필수 입력: 이메일
age: Int # 선택 입력: 나이
}
input UserFilter {
nameContains: String # 이름 포함 검색
minAge: Int # 최소 나이
maxAge: Int # 최대 나이
}
# 커스텀 스칼라 타입 정의
scalar DateTime # 날짜/시간 처리를 위한 커스텀 스칼라
"""
사용자 역할을 정의하는 열거형
"""
enum UserRole {
ADMIN
USER
GUEST
}
'개발 > 백엔드' 카테고리의 다른 글
Spring Security OAuth (0) | 2025.01.07 |
---|---|
Spring GraphQL (1) | 2025.01.06 |
Redis Serializer 비교 (0) | 2024.12.31 |
Late Limiter vs Circuit Breaker (0) | 2024.12.30 |
Spring Circuit Breaker (0) | 2024.12.30 |