- 본 시리즈에서는 How to GraphQL의 Tutorial 문서들을 차례대로 번역합니다.
- 이 글은 GraphQL Advanced - More GraphQL Concepts을 번역한 글입니다.
- 오역 또는 의역이 있을 수 있습니다. 양해 부탁드리며, 수정할 필요한 부분은 댓글로 요청해주세요.
Fragment는 GraphQL 코드의 구조와 재사용성을 향상시키는 데에 도움을 주는 편리한 기능입니다. Fragment는 특정 타입의 필드들로 이루어진 집합입니다.
아래와 같은 타입을 가정합시다.
type User {
name: String!
age: Int!
email: String!
street: String!
zipcode: String!
city: String!
}
사용자의 주소와 관련된 모든 정보를 Fragment를 사용하여 아래와 같이 나타낼 수 있습니다.
fragment addressDetails on User {
name
street
zipcode
city
}
자, 사용자의 주소에 접근하는 쿼리를 작성한다면, 아래와 같은 문법을 사용하여 Fragment를 참조하고, 4개 필드를 직접 작성하는 수고를 덜 수 있습니다.
{
allUsers {
... addressDetails
}
}
위의 쿼리는 아래의 쿼리와 같은 의미를 갖습니다.
{
allUsers {
name
street
zipcode
city
}
}
GraphQL에서 타입을 정의할 떄, 각 필드는 0개 이상의 인자(Argument)를 가질 수 있습니다. 타입이 있는 프로그래밍 언어에서는 함수에 인자를 전달할 수 있습니다. 이와 유사하게 각 인자는 이름과 타입을 가집니다. GraphQL에서는 인자에 기본값을 부여할 수도 있습니다.
예를 들어, 아주 초반에 다루었던 스키마를 다시 보도록 합시다.
type Query {
allUsers: [User!]!
}
type User {
name: String!
age: Int!
}
이제 allUsers
필드에 인자를 추가하여 특정 연령 이상의 사용자만을 필터링하여 포함하도록 만들 수 있습니다. 또한 기본값을 부여하여, 인자가 전달되지 않을 경우 모든 사용자를 반환하도록 만들 수 있습니다.
type Query {
allUsers(olderThan: Int = -1): [User!]!
}
여기서 사용된 olderThan
인자는 아래와 같은 문법을 사용하여 쿼리에 전달할 수 있습니다.
{
allUsers(olderThan: 30) {
name
age
}
}
GraphQL의 중요한 강점 중 하나는 한번의 요청으로 다수의 쿼리를 전송할 수 있다는 것입니다. 하지만 요청되는 필드의 구조에 맞추어 응답 데이터의 구조가 형성되므로, 같은 필드에 대한 여러 쿼리를 전송할 경우 이름이 겹치는 문제가 발생할 수 있습니다.
{
User(id: "1") {
name
}
User(id: "2") {
name
}
}
다른 인자들을 사용하여 같은 필드에 대하여 요청한 것이므로 위와 같은 쿼리는 GraphQL 서버에서 오류를 발생시킵니다. 이러한 쿼리를 전송하려면 Alias를 사용해야 합니다. 예를 들어, 아래와 같이 쿼리 결과에 대하여 이름을 부여해야 합니다.
{
first: User(id: "1") {
name
}
second: User(id: "2") {
name
}
}
반환된 결과를 보면, 각 User
객체들이 지정된 Alias에 따라 이름지어진 것을 알 수 있습니다.
{
"first": {
"name": "Alice"
},
"second": {
"name": "Sarah"
}
}
이전 장에서 다루었던 것 이외에도 SDL은 다양한 기능들을 제공합니다. 실제 예시를 사용하여 이에 대하여 논하도록 하겠습니다.
GraphQL에는 두 가지 종류의 타입이 존재합니다.
String
, Int
, Float
, Boolean
, ID
등 총 5개의 스칼라 타입을 정의하고 있습니다.User
, Post
타입 등이 있습니다.모든 GraphQL 스키마에서 고유한 스칼라 또는 객체 타입을 정의할 수 있습니다. 별도로 정의한 스칼라 타입의 대표적인 예시는 Date
타입으로, 이 타입을 구현할 때에는 타입의 유효성 검사, 직렬화, 역직렬화 방법 등을 모두 정의해야 합니다.
GraphQL에서는 열거(Enumeration) 타입(줄여서 Enums)를 정의할 수 있습니다. Enums 타입이란 일정한 값들의 집합에 대하여 의미를 표현할 수 있는 언어 기능입니다. 이에 따르면 한 주의 요일들을 나타내기 위하여 Weekday
라는 타입을 정의할 수 있습니다.
enum Weekday {
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
}
기술적으로 볼 때 Enums는 스칼라 타입의 특별한 종류 중 하나라는 점을 유의하시기 바랍니다.
인터페이스(Interface)를 사용하면 타입을 추상적인 방식으로 설명할 수 있습니다. 인터페이스는 해당 인터페이스를 구현하는 타입이 반드시 가져야 하는 필드에 대하여 정의합니다. 대부분의 GraphQL 스키마에서 타입에는 id
필드가 필요합니다. 이러한 요구 사항은 해당 필드가 포함된 인터페이스를 정의하고, 모든 타입들이 이 인터페이스를 반드시 구현하도록 함으로써 충족될 수 있습니다.
interface Node {
id: ID!
}
type User implements Node {
id: ID!
name: String!
age: Int!
}
유니온(Union) 타입은 어떤 타입이 여러 타입 중 하나이어야 함을 나타낼 때에 사용합니다. 예시를 보면 쉽게 이해할 수 있습니다. 아래와 같은 타입을 생각해봅시다.
type Adult {
name: String!
work: String!
}
type Child {
name: String!
school: String!
}
이제, Person
타입을 정의할 때에 Adult
와 Child
의 Union으로 정의할 수 있습니다.
union Person = Adult | Child
이렇게 되면 또 다른 문제가 발생합니다. GraphQL 쿼리를 사용하여 Child
에 대한 정보를 불러오려는 상황에서 Person
타입만이 사용 가능하다면, Child
타입의 필드가 사용 가능한지 여부를 어떻게 해야 알 수 있을까요?
답은 바로 조건부 Fragment에 있습니다.
{
allPersons {
name # `Adult`와 `Child` 모두 사용 가능합니다
... on Child {
school
}
... on Adult {
work
}
}
}
Quiz
다음 중 옳지 않은 것은?
- Alias는 다수 쿼리에 대한 결과 객체들을 각기 이름짓는 데에 사용된다.
- Fragment는 GraphQL 코드의 구조와 재사용성을 향상시키는 데에 유용하다.
- GraphQL 타입의 모든 필드는 0개 이상의 인자와 연관될 수 있다.
- GraphQL은 내장 데이터 타입을 가진다.
좋은 글 써주셔서 감사합니다 :)