Spring Boot 서버에서 GraphQL 요청을 처리하는 방법으로 두 가지 방법을 소개하겠습니다.
아래 두 가지 방법은 공통적으로는 아래 처럼 작동합니다. 사용하는 의존성에 따라 구체적인 방법이 조금 다를 뿐입니다.
- GraphQL의 쿼리문이 Resolver 구현체의 메서드로 매핑되고
- 요청 및 응답에 사용되는 GraphQL 타입이 java의 dto 객체에 매핑됩니다.
Resolver는 기존 controller의 역할을 수행한다고 보면 되며, endpoint(요청 주소)에 따라 구분하지 않고 query 및 mutation의 요청을 구분하거나 복잡한 요청 을 구현하는 대상에 따라 구분합니다.
1. Resolver를 구현하여 처리하기(kickstart 의존성 사용)
Resolver를 구현하여 데이터를 처리하기 위해선 스키마를 정의해야합니다. 스키마란 GraphQL의 쿼리문을 정의하고, 요청 및 응답에 사용되는 데이터를 정의하는 데이터 집합입니다. 아래의 의존성을 등록하여 구현할 수 있습니다.
<dependency>
<groupId>com.graphql-java-kickstart</groupId>
<artifactId>graphql-spring-boot-starter</artifactId>
<version>7.1.0</version>
</dependency>
Step1. 스키마 작성하기
스키마는 아래와 같은 형식으로 작성할 수 있습니다. 사용자 지정 스칼라 타입으로 Post, Author를 정의하고, query및 mutation 요청을 Query, Mutation 내부에 정의해줍니다. 내부적으로는 스키마의 타입 안 필드 각각마다 data fetcher가 연관돼있어서 data fetcher의 내부 로직에 따라 데이터를 가져올 수 있습니다.
type Post {
id: ID! #각각에 data fetcher
title: String! #각각에 data fetcher
text: String! #각각에 data fetcher
category: String # ...
author: Author!
}
type Author {
id: ID!
name: String!
}
type Query {
getPosts : [Post]
}
type Mutation {
savePost(title : String, text: String, category : String) : Post
}
Step2. Resolver 구현하기
다음 스키마에서 정의한 쿼리 메소드를 아래의 인터페이스를 구현하여 작성해 줄 수 있습니다.
data fetcher가 데이터를 가져오면 아래 GraphQLResolver<T>, GraphQLMutationResolver, GraphQLQueryResolver 인터페이스를 구현해서 요청을 처리하며 각각의 상위 인터페이스는 아래와 같습니다.
GraphQLMutationResolver → GraphQLResolver<Void> |
GraphQLResolver<PostResponse> |
GraphQLQueryResolver → GraphQLResolver<Void> |
Resolver 구현체는 빈으로 등록해야하므로 반드시 @Component같은 어노테이션을 붙여줍니다.
예시)
@Component
@RequiredArgsConstructor
public class RootQueryResolver implements GraphQLQueryResolver {
private final PostRepository postRepository;
public List<PostResponse> getRecentPosts(int count, int offset) {
final List<Post> all = postRepository.findAll();
return PostResponse.from(all);
}
}
2. annotation을 사용하여 처리하기(spqr 의존성 사용)
스키마를 정의하여 매핑하는 방식이 아닌 어노테이션을 사용하여 매핑을 해주는 방식입니다. 아래의 의존성을 등록해주면 따로 스키마와 resolver를 구현하지 않아도 GraphQL을 사용할 수 있어 편리하다는 장점이 있지만 단점으로 Multipart 를 이용한 파일 업로드 구현이 어렵다는 점이 있습니다.
<dependency>
<groupId>io.leangen.graphql</groupId>
<artifactId>graphql-spqr-spring-boot-starter</artifactId>
<version>0.0.4</version>
</dependency>
링크: https://github.com/leangen/graphql-spqr-spring-boot-starter
Step1. @GraphqlApi로 Resolver 등록
@GraphqlApi 을 달아준 spring application context의 모든 빈은 운영 소스로 간주되며 이 어노테이션은 빈 등록 어노테이션인@Bean, @Component, @Service, @Repository 등과 함께 사용 됩니다.
이렇게 어노테이션을 적용해주면 Resolver 구현체와 같은 기능을 하는 클래스로 인식됩니다.
@Component
@GraphQLApi
private class UserService {
// query, mutation, subscription methods
...
}
Step2. 쿼리 메서드 설정하기(쿼리 유형, 인자 설정)
@GraphqlQuery(조회) 또는 @GraphqlMutation(생성,수정,삭제) 를 달아주면 기본적으로는 메소드 이름, 인자 이름으로 GraphQL 쿼리문에 매핑됩니다. 해당 메서드를 다른 쿼리문에 매핑시키려면 @GraphQLQuery, @GraphQLArgument 에서 name 프로퍼티로 이름을 변경할 수 있습니다.
@RequiredArgsConstructor
@GraphQLApi
@Service
public class demoService {
private final PostRepository postRepository;
@GraphQLQuery(name = "posts")
public List<PostDto> RecentPosts(@GraphQLArgument(name="cnt")int count, int offset) {
final List<Post> all = postRepository.findAll();
return PostDto.from(all);
}
@GraphQLMutation
public PostDto writePost(String title, String text, String category) {
Post post = new Post(title, text, category);
postRepository.save(post);
PostDto dto = PostDto.from(post);
return dto;
}
}
'GraphQL' 카테고리의 다른 글
Spring Boot에서 GraphQLResolver<T> 사용하기 (0) | 2021.05.17 |
---|---|
GraphQL 명명 Convention (0) | 2021.05.17 |
GraphQL 사용하면서 느낀 장단점(+ Spring Boot) (0) | 2021.05.17 |
댓글