GQL(GraphQL)로 불리는 API용 쿼리 언어로 특정 datasource에 종속되어 있지 않으며 서버측 런타임 라이브러리 형태로 제공하는 쿼리언어. Facebook에서 제작
기존의 REST API는 클라이언트가 리소스를 엊기 위해 서버에서 정의한 여러 엔드포인트로 호출하는 형태였다면 GQL은 서로 협의한 Schema의 정보를 가지고 다양하게 동적 쿼리 를 하는 형태이다.
마케팅/광고 도메인의 플랫폼개발시 주로 사용하는 기술로 고객 니즈를 파악에 도움되는 것으로 보임
graphql-java-annotations
spring boot graphql starter 라이브러리도 제공 추후 스터디를 해서 포스팅하는걸로
<dependency>
<groupId>com.graphql-java</groupId>
<artifactId>graphql-java-annotations</artifactId>
<version>${graphql-java-annotations.version}</version>
</dependency>
<dependency>
<groupId>io.ratpack</groupId>
<artifactId>ratpack-core</artifactId>
<version>1.4.6</version>
</dependency>
public class UserSchema {
private final GraphQLSchema schema;
public UserSchema() throws IllegalAccessException, NoSuchMethodException, InstantiationException {
schema = newSchema().query(GraphQLAnnotations.object(UserQuery.class))
.mutation(GraphQLAnnotations.object(UserMutation.class))
.build();
}
public GraphQLSchema getSchema() {
return schema;
}
}
@Data
@GraphQLName(SchemaUtils.USER)
public class User {
@GraphQLField
private Long id;
@GraphQLField
private String name;
@GraphQLField
private String email;
@GraphQLField
private Integer age;
}
@Override
public void handle(Context context) throws Exception {
context.parse(Map.class)
.then(payload -> {
Map<String, Object> parameters = (Map<String, Object>)
payload.get("parameters");
ExecutionResult executionResult = graphql
.execute(payload.get(SchemaUtils.QUERY)
.toString(), null, this, parameters);
Map<String, Object> result = new LinkedHashMap<>();
if (executionResult.getErrors().isEmpty()) {
result.put(SchemaUtils.DATA, executionResult.getData());
} else {
result.put(SchemaUtils.ERRORS, executionResult.getErrors());
LOGGER.warning("Errors: " + executionResult.getErrors());
}
context.render(json(result));
});
}
@GraphQLName(SchemaUtils.QUERY)
public class UserQuery {
@GraphQLField
public static User retrieveUser(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.ID) final String id) {
final Optional<User> any = getUsers(env).stream()
.filter(c -> c.getId() == Long.parseLong(id))
.findFirst();
return any.orElse(null);
}
@GraphQLField
public static List<User> searchName(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.NAME) final String name) {
return getUsers(env).stream()
.filter(c -> c.getName()
.contains(name))
.collect(Collectors.toList());
}
@GraphQLField
public static List<User> listUsers(final DataFetchingEnvironment env) {
return getUsers(env);
}
}
@GraphQLName(SchemaUtils.MUTATION)
public class UserMutation {
@GraphQLField
public static User createUser(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.NAME) final String name, @NotNull @GraphQLName(SchemaUtils.EMAIL) final String email, @NotNull @GraphQLName(SchemaUtils.AGE) final String age) {
List<User> users = getUsers(env);
final User user = new User(name, email, Integer.valueOf(age));
users.add(user);
return user;
}
@GraphQLField
public static User updateUser(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.ID) final String id, @NotNull @GraphQLName(SchemaUtils.NAME) final String name, @NotNull @GraphQLName(SchemaUtils.EMAIL) final String email,
@NotNull @GraphQLName(SchemaUtils.AGE) final String age) {
final Optional<User> user = getUsers(env).stream()
.filter(c -> c.getId() == Long.parseLong(id))
.findFirst();
if (!user.isPresent()) {
return null;
}
user.get()
.setName(name);
user.get()
.setEmail(email);
user.get()
.setAge(Integer.valueOf(age));
return user.get();
}
@GraphQLField
public static User deleteUser(final DataFetchingEnvironment env, @NotNull @GraphQLName(SchemaUtils.ID) final String id) {
final List<User> users = getUsers(env);
final Optional<User> user = users.stream()
.filter(c -> c.getId() == Long.parseLong(id))
.findFirst();
if (!user.isPresent()) {
return null;
}
users.removeIf(c -> c.getId() == Long.parseLong(id));
return user.get();
}
}
curl --location --request POST 'http://localhost:5050/users' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": "mutation($name: String! $email: String! $age: String! ){ createUser ( name: $name email: $email age: $age) { id name email age } }",
"parameters": {
"name": "John",
"email": "john@email.com",
"age": 34
}
}'
{
"data": {
"createUser": {
"id": 1,
"name": "John",
"email": "john@email.com",
"age": 34
}
}
}