GraphQL 소개
GraphQL은 페이스북에서 만든 API를 위한 쿼리 언어이다.
SQL과 유사하게 사용하는 웹 요청용 쿼리를 정의한 규약이고 많이 사용하는 REST API와 다른 형식의 요청이라고 생각하면 된다.
REST API의 경우 요청 주소에 따라 응답 결과를 얻게 되지만 GraphQL은 단일 요청 주소로 질의한 쿼리 별 대한 응답 결과를 얻는 차이가 있다.
GraphQL for Java/Kotlin
GraphQL은 다양한 언어에 대한 라이브러리를 제공하고 있다.
이 중 Java에서 사용하기 위한 라이브러리 항목은 다음을 참고한다.
Code using GraphQL Java/Kotlin
Spring for GraphQL
이 중 graphql-java에서 spring에서 사용하기 위해 제공하던 graphql-java-spring 라이브러리가 spring project로 이전되어 spring-graphql로 변경되었다.
이 라이브러리를 기반으로 Spring Boot 2.7.0부터 graphql에 대한 autoconfigure를 제공하기 시작하였고 이제 spring-boot-starter-graphql
을 사용하면 된다.
(이전에 별도 라이브러리를 선택하여 사용하던 경우 이제 Spring이 graphql-java를 기반으로 제공하기 시작하였으므로 변경을 고려하면 될 것 같다.)
dependency 설정
Spring Boot에서 사용하려면 다음과 같이 설정한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-graphql</artifactId>
</dependency>
Spring Boot를 사용하면 위 starter 참조 시 GraphQL 사용이 기본 활성화된다.
properties 설정
GraphQL 관련하여 Spring Boot는 2개의 properties를 설정할 수 있게 제공한다.
- GraphQlProperties
- GraphQlCorsProperties
GraphQlProperties에서는 기본적인 graphql 사용 설정을 한다.
default 설정은 다음과 같다.
spring.graphql.path=/graphql
spring.graphql.graphiql.path=/graphiql
spring.graphql.graphiql.enabled=false
spring.graphql.schema.locations=classpath:graphql/**/
spring.graphql.schema.file-extensions=.graphqls,.gqls
spring.graphql.schema.introspection.enabled=true
spring.graphql.schema.printer.enabled=false
spring.graphql.websocket.connection-init-timeout=60s
spring.graphql.websocket.path=
spring.graphql.rsocket.mapping=
GraphQlCorsProperties에서 Cors 관련 설정을 한다.
default 설정은 다음과 같다.
spring.graphql.cors.allow-credentials=
spring.graphql.cors.allowed-headers=
spring.graphql.cors.allowed-methods=
spring.graphql.cors.allowed-origin-patterns
spring.graphql.cors.allowed-origins=
spring.graphql.cors.exposed-headers=
spring.graphql.cors.max-age=1800s
만약 기존 web 관련 cors 설정과 연동하고자 원한다면 따로 처리를 해야 할 것 같다.
여기까지 설정을 하면 이제 사용할 수 있게 된다.
개발 중엔 위에 열거한 설정 중 아래 두 가지 설정을 활성화하는 걸 추천한다.
spring.graphql.graphiql.enabled=true
spring.graphql.schema.printer.enabled=true
graphiql 활성화하기
graphiql은 GraphQL을 사용하면서 만들어야 할 query를 쉽게 만들어서 테스트할 수 있는 편집기이다.
해당 편집기를 통해 GraphQL query를 편하게 작성해서 사용할 수 있다.
spring-boot-starter-graphql
를 사용하는 경우 spring.graphql.graphiql.enabled=true
설정을 하면 /graphiql
주소가 활성화되어 graphiql 편집기를 사용할 수 있게 된다.
schema 활성화하기
작성한 GraphQL schema를 호출을 통해 확인할 수 있다.
schema를 단일 파일로 관리하지 않는 경우 전체 schema 확인 시 유용하다.
spring.graphql.schema.printer.enabled=true
설정을 하면 /graphql/schema
주소가 활성화되어 schema를 확인할 수 있다.
사용해보기
REST API와 차이점
rest API의 경우 해당 resource에 대해 주소가 정해져 있고 GET, POST, PUT, DELETE와 같이 호출하여 해당 resource에 대한 CRUD 처리를 한다.
GraphQL의 경우 고정된 주소에 POST 호출로 쿼리를 사용한다.
spring-boot-starter-graphql
을 사용하는 경우 기본 설정된 주소는 /graphql
이다.
이 주소에 POST 요청을 하며 R (Read) 요청의 경우 Query
로 요청을 하고 그 외의 CUD (Create, Update, Delete) 요청의 경우 Mutation
으로 요청을 한다.
대략 아래와 같은 형태로 요청한다.
// Query 요청의 경우
fetch("/graphql", {
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
body : JSON.stringify({ query : "{ userBlogList { blogId, userId } }" })
})
.then(response => response.json());
// Mutation 요청의 경우
fetch("/graphql", {
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
body : JSON.stringify({ query : "mutation { createBlog { blogId, userId } }" })
})
.then(response => response.json());
GraphQL을 사용하려면 위 요청을 받아 처리할 수 있도록 아래 두 가지 사항에 대한 처리를 해야 한다.
- Controller 설정
- Schema 설정
REST API는 Controller만 설정하면 되지만 GraphQL을 요청을 쿼리로 하기 때문에 쿼리에 대한 Schema 설정이 추가로 더 필요하다.
@SchemaMapping, @QueryMapping, @MutationMapping 설정하기
@SchemaMapping
, @QueryMapping
, @MutationMapping
은 Controller에서 graphql을 사용하기 위해 사용하는 annotation이다.
대략 다음과 같이 사용한다.
@Controller
public class TestController {
private String testAString = "testAString";
@QueryMapping
public String testA() {
return testAString;
}
@MutationMapping
public String testAUpdate(@Argument String changeValue) {
testAString = changeValue;
return testAString;
}
}
@QueryMapping
과 @MutationMapping
은 @SchemaMapping
을 축약해서 사용하기 위해 제공되는 anntation으로 풀어쓰면 다음과 같다.
// 이 annotation은
@QueryMapping
public String someMethod() {
return "TEST";
}
// 이 annotaton을 쓴 것과 같음
@SchemaMapping(typeName = "Query")
public String someMethod() {
return "TEST";
}
@MutationMapping
public String someMethodUpdate(@Argument String changeValue) {
targetString = changeValue
return targetString;
}
@SchemaMapping(typeName = "Mutation")
public String someMethodUpdate(@Argument String changeValue) {
targetString = changeValue
return targetString;
}
기존 REST API의 Controller 설정에선 @RequestMapping
, @GetMapping
, @PostMapping
annotation을 사용하였는데 그에 상응하는 annotation들이라고 생각하면 될 것 같다.
Schema 설정하기
GraphQL을 사용하려면 위에 설정한 Controller의 ScheamMapping
에 대해 Schema를 설정해야 한다.
spring-boot-starter-graphql
를 사용하는 경우 default로 설정된 Schema 파일 위치는 classpath:graphql/**/
으로 /src/main/resources/graphql/
위치에 자유로운 이름으로 *.graphqls
또는 *.gqls
파일을 만들면 된다.
위 controller의 testA 호출의 경우 대략 다음과 같은 Schema를 설정하면 된다.
type Query {
testA: String
}
호출해보기
위에 만들어진 testA를 호출하려면 다음과 같이 하면 된다.
javascript fetch 호출의 예인데 graphiql 을 사용하면 좀더 편하게 호출해볼 수 있다.
fetch("/graphql", {
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
body : JSON.stringify({ query : "{ testA }" })
})
.then(response => response.json());
Object에 대해 호출해보기
여기까지 따라 해 보았다면 기본적인 controller생성과 schema 설정, 그리고 호출하는 것까지 해본 것이다.
단순한 문자열 반환의 경우 이렇게 단순하지만 만약 Object를 반환하는 경우나 매개변수가 있는 경우라면 schema의 설정이 좀 더 복잡해진다.
예를 들면 다음가 같다.
type Query {
getAObject(id: ID): AObject
}
type AObject {
id: ID
name: String
description: String!
amount: Int
}
위와 같이 schema가 정의되어 있으면 아래와 같이 호출한다.
fetch("/graphql", {
"method": "POST",
"headers": {
"Content-Type": "application/json"
},
body : JSON.stringify({ query : "{ getAObject(123) { id, name } }" })
})
.then(response => response.json());
호출할 대상에 대해 argument와 응답할 Object의 field를 지정하고 있다.
마무리
대략적으로 GraphQL을 사용을 해보았다.
기존 사용하던 REST API와 비교해서 어떤 게 더 좋은지 판단하는 것은 각 사용자의 몫일 것 같다.
굳이 한쪽만 사용할 필요 없이 원하는 곳에 REST API / GraphQL을 병행 사용하면 되지 않을까 싶다.
'Study > Java' 카테고리의 다른 글
Spring Boot 3.0 Migration Guide (0) | 2022.11.28 |
---|---|
Spring Boot 3.0 Release Notes (0) | 2022.11.27 |
Selenium 사용해보기 (0) | 2022.11.26 |
JDK 17부터 Locale language old ISO code 사용 비활성으로 기본 설정 변경 (0) | 2022.11.23 |
JDK 19 New Features (0) | 2022.09.21 |
Spring Rest Docs로 OpenAPI (Swagger) 문서를 만들어 Swagger UI로 호출하여 보기 (0) | 2022.06.17 |
Spring Cloud Config Server jdbc backend 사용해보기 (0) | 2022.06.13 |
@Validated annotation을 controller가 아닌 service, component layer에서 사용하기 (0) | 2022.06.08 |
[troubleshooting] eclipse (STS) 에서 refactor rename이 동작하지 않는 현상 (0) | 2022.06.08 |
Spring Boot project STS에서 열어보기 (0) | 2022.05.26 |