이번 장에서는 GraphQL을 통해 조회하는 방법과 조회하는 객체를 정의하는 방법에 대해 작성하겠습니다.
1. 조회하는 방법
POST 메서드를 통해 하나의 API로 요청을 보냅니다.
조회의 경우 query { ... } 를 body에 담아서 전송합니다. (query 지시어는 생략 가능)
조회하는 필드를 작성하여 클라이언트 측에서 필요한 데이터만 받을 수 있습니다. (REST에서 overfetching 문제 개선)
2. 조회하는 객체
조회하는 객체는 일반적으로 type { ... } 으로 선언합니다.
! 기호가 붙으면 non-null type을 의미하며, [ ... ] 는 리스트 객체를 의미합니다.
Scalr 타입으로 Int, Float, String, Boolean, ID가 있습니다. ID는 객체를 다시 요청하거나 캐시의 key로써 고유 식별자를 의미합니다.
Type System
{
hero {
name
appearsIn
}
}
{
"data": {
"hero": {
"name": "R2-D2",
"appearsIn": [
"NEWHOPE",
"EMPIRE",
"JEDI"
]
}
}
}
- 루트 객체로 시작합니다. (type Query { ... } 에 선언한 유형 선택)
- 조회할 객체의 필드를 작성합니다.
- hero에 의해 반환된 객체에 대해 요청한 필드를 반환합니다.
스키마가 필요한 이유
- GraphQL 쿼리의 형태가 결과와 거의 일치하기 때문에 서버에 대해 모르는 상태에서 쿼리가 반환할 결과를 예측할 수 있다.
- 스키마를 통해 미리 요청할 수 있는 데이터와 타입을 정의하여 제공할 수 있는 데이터 형태를 정의합니다.
Object types and fields
type Character {
name: String!
appearsIn: [Episode!]!
}
- Character : GraphQL Object Type (GrpahQL의 객체 타입)
- name, appearsIn : fields on the Character type (객체의 필드)
- String!: ! is Non-Null type
- [Episode!]! : [ .. ] represents an List type of Episode objects
Query type & Mutation type
스키마 대부분의 타입은 객체 타입이지만 스키마 내에 특수한 2가지 타입이 있습니다. (query, mutation)
schema {
query: Query
mutation: Mutation
}
모든 GraphQL 서비스는 query 타입을 가지며 mutation 타입은 가질 수도 있고 가지지 않을 수도 있습니다.
이러한 타입은 모든 GraphQL 쿼리의 Entry Point를 정의합니다. (Controller에서 같은 이름으로 메서드명을 작성해야 하며, GraphQL 요청 시에도 같은 이름으로 요청을 보내야 합니다.)
type Query {
hero(episode: Episode): Character
droid(id: ID!): Droid
}
---
query {
hero {
name
}
droid(id: "2000") {
name
}
}
---
{
"data": {
"hero": {
"name": "R2-D2"
},
"droid": {
"name": "C-3PO"
}
}
}
Enum type
열거형 타입도 지원하며 특정 값들로 제한되는 종류의 객체입니다.
- 타입의 인자가 허용된 값 중 하나인지 검증합니다.
- 필드가 항상 값의 열거형 집합 중 하나가 될 것임을 type system에도 적용해야 합니다.
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
Interface type
다른 언어에서와 같은 개념의 인터페이스 타입을 제공합니다.
이를 구현할 때 가져야 하는 필드와 타입을 선언합니다.
interface Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
}
Character을 구현한 모든 타입은 해당 필드와 리턴 타입을 가진 정확한 필드를 가져야 합니다.
type Human implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
starships: [Starship]
totalCredits: Int
}
type Droid implements Character {
id: ID!
name: String!
friends: [Character]
appearsIn: [Episode]!
primaryFunction: String
}
- Character 객체의 필드와 리턴 타입을 정확하게 가지고 있으며, 추가 필드를 선언할 수 있습니다.
query HeroForEpisode($ep: Episode!) {
hero(episode: $ep) {
name
... on Droid {
primaryFunction
}
}
}
- hero는 Character 객체 타입을 반환하는데, episode 인자에 따라 Human, Droid 중 하나일 수 있어, 타입을 정확하게 표기해 줘야 에러가 발생하지 않습니다.
Query types
type Query {
droid(id: ID!): Droid
}
- 정의한 유형을 GraphQL로 조회할 수 있습니다.
{
droid(id: "2000") {
name
}
}
- That means that the GraphQL service needs to have a Query type with a droid field
Aliases
since the result object fields match the name of the fields in the query but don’t include arguments, you can’t directly query for the same field with different arguments. That’s why you need aliases
- 결과 객체 이름은 쿼리했을 때의 필드명과 같은 것을 알 수 있다.
- 결과 객체의 이름을 변경하기 위해서 aliases를 사용할 수 있다.
Fragments
Fragments let you construct sets of fields, and then include them in queries where needed.
Mutations Types
Add new data
enum Episode {
NEWHOPE
EMPIRE
JEDI
}
input ReviewInput {
stars: Int!
commentary: String
}
type Mutation {
createReview(episode: Episode, review: ReviewInput!): Review
}
- mutation fields are added to one of the root operation types that provide an entry point to the API.
- input type은 mutation 인자로 사용할 수 있습니다.
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
{
"data": {
"createReview": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
}
Input Object types
input ReviewInput {
stars: Int!
commentary: String
}
type Mutation {
createReview(episode: Episode, review: ReviewInput!): Review
}
- input type is particularly valuable in the case of mutations, where you might want to pass in a whole object to be created.
createReview(
episode: JEDI,
review: {
stars: 5
commentary: "This is a great movie!"
}
) {
stars
commentary
}
}
{
"data": {
"createReview": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
}
Update existing data
we use mutations to update existing data.
mutation UpdateHumanName($id: ID!, $name: String!) {
updateHumanName(id: $id, name: $name ) {
id
name
}
}
{
"data": {
"updateHumanName": {
"id": "1000",
"name": "Luke Starkiller"
}
}
}
mutation을 통해 생성, 수정, 삭제 모두를 처리할 수 있으며, 모두 post로 처리됩니다.
update와 delete 같은 경우 ID 값을 인자로 전달하여 서버에서 처리합니다. 올바르게 type Mutation { ... } 을 정의해서 각 요청을 구분합니다.
참고자료
'Web > GraphQL' 카테고리의 다른 글
Spring GraphQL 예외 처리 설정하기 Error Handling - GraphQLError, DataFetcherExceptionResolverAdapter (0) | 2025.01.01 |
---|