본문 바로가기

개발/백엔드

빠르게 GraphQL 기본 개념 정리

 

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