GraphQL 톺아보기 - (2) GraphQL 기본 문법(Query & Mutation)

ooesny·2024년 4월 22일

GraphQL 스터디

목록 보기
2/2
post-thumbnail

이전 글에서 GraphQL의 기본 개념, 등장 배경, REST API와 비교 했을 때 가지는 장단점 비교, 전체적인 흐름 소개를 다루었다.

본 글에서는 GraphQL의 세부 문법인 Query와 Mutation에 대해 정리해보고자 한다.
본 글의 내용은 GraphQL 공식 문서를 참고 했으며, 세부적인 예제는 공식 문서로 확인하는 것을 추천한다.


1️⃣ Query & Mutation : GraphQL 서버에 쿼리하는 방법

GraphQL의 기본 내용들을 살펴봤으니, 가장 기본적인 문법인 Query와 Mutation에 대한 공식문서 예제들을 살펴보며 보다 자세한 사용 방식에 대해 알아보자.

▷ 1-(1) Query

: 데이터를 가져오는(fetch) 요청 시 사용

📍 Fields (필드)

  • GraphQL은 서버에서 클라이언트가 요청하는 필드를 정확히 알고 있기 때문에 쿼리와 결과가 정확히 동일한 형태이다.
  • GraphQL 쿼리는 연관된 객체와 필드를 탐색할 수 있어 해당 객체에 대한 필드를 하위 선택할 수 있다. → 한 번의 요청으로 많은 데이터를 가져올 수 있다.
  • GraphQL 쿼리는 스키마를 기반으로 예상되는 결과를 알 수 있다.

📍 Argument (인자)

  • GraphQL에서는 모든 필드와 중첩된 객체가 인자를 가질 수 있어, 여러번의 API fetch를 대체하여 서버에서 데이터 변환을 한 번만 구현할 수 있다.
  • Graph QL의 인자는 다양한 타입이 될 수 있다.
    → 기본 타입을 함께 제공하며, 데이터를 직렬화 할 수 있는 한 직접 커스텀 타입 선언도 가능하다. ➡️ 열거형(enumeration) 타입을 사용한 예제

📍 Aliases (별칭)

  • 기본적으로 결과 객체 필드는 쿼리의 필드명과 일치하나, 같은 필드에 대해 서로 다른 인자 값을 주면 동일 객체 필드에 대해 충돌이 일어날 수 있다.
  • 이때, 별칭을 사용하여 같은 필드에 다른 인자를 줄 경우 필드의 결과를 원하는 이름으로 바꿀 수 있다.

📍 Fragment (프래그먼트)

  • 프래그먼트는 중복되는 쿼리에 사용할 수 있는 재사용 가능한 단위이다. 프래그먼트를 이용해 필드셋을 구성한 후 필요한 쿼리에 포함시킬 수 있다.
  • 복잡한 데이터 요구 사항을 작은 단위로 분할하기 위해 사용한다.
  • 추가적으로, 쿼리나 뮤테이션에 선언된 변수는 프래그먼트에 접근이 가능하다.
    ➡️ 자세한 예시는 공식문서를 참고.

📍 Operation name (작업 이름)

  • query 키워드와 이름을 생략한 단축 문법을 사용할 수도 있지만 실제로는 작업 이름을 정해 코드를 헷갈리지 않게 사용하는 것이 좋다.
  • 어떤 작업의 타입인지를 기술하는 작업 타입은 query, mutation, subscription 중 하나를 선택할 수 있다.
  • 명시적인 작업의 이름인 작업 이름을 사용하면 디버깅 하거나 서버에서 로깅할 때 유용하다.
    ➡️ query를 작업 타입, HeroNameAndFriends를 작업 이름으로 한 예제

📍 Variables (변수)

  • GraphQL은 동적 값을 쿼리에서 없애고, 이를 별도로 전달하는 방법인 변수를 제공한다.
    → 이 방법은 쿼리의 어떤 인자가 동적인지를 나타내는 좋은 방법이기도 하다.
  • 변수를 사용하기 위해서는 다음 세 가지 작업을 해야 한다.
    - (1) 쿼리 안의 정적 값을 $variableName 으로 변경한다.
    - (2) $variableName 을 쿼리에서 받는 변수로 선언한다.
    - (3) 별도의 전송규약(일반적으로 JSON) 변수에 variableName: value 를 전달한다.
    - (4) 타입 선언 다음에 기본값을 병시하여 쿼리의 변수에 기본 값을 할당할 수 있다.
    → 모든 변수에 기본 값이 제공되면 변수를 전달하지 않고도 쿼리를 호출할 수 있다.
    → 변수는 기본 값을 덮어 쓴다.
    ➡️ ($episode: Episode = "JEDI")로 기본값을 명시한 예제

📍 Directives (지시어)

  • 지시어는 필드나 프래그먼트 안에 삽입 될 수 있으며, 서버가 원하는 방식으로 쿼리 실행에 영향을 줄 수 있다.
  • GraphQL에서 사용되는 지시어는 아래의 두 가지이다.
    - @include(if: $variableName): 인자가 true 인 경우에만 이 필드를 결과에 포함한다.
    - @skip(if: $variableName) : 인자가 true 이면 이 필드를 건너뛴다.
    $variableName은 type이 Boolean이어야 한다.
    !은 필수로 포함되어야 할 때 사용한다.


▷ 1-(2) Mutation

: 서버 측 데이터를 수정하는 요청 시 사용

  • GraphQL도 변경이 발생하는 작업이 명시적으로 뮤테이션을 통해 전송되는 것이 좋다.
  • 쿼리와 마찬가지로 뮤테이션 필드가 객체 타입을 반환하면 중첩 필드를 요청할 수 있으며, 이는 변경된 객체의 새로운 상태를 가져오는데에 유용하다.
  • 하나의 요청으로 필드의 새 값을 변경하고 쿼리할 수 있기 때문에 기존 데이터를 변경하는 경우 특히 유용하다. ➡️ (보다 자세한 예시는 docs를 참고)
    ➡️ createReview 필드가 새로 생성된 리뷰의 stars와 commentary 필드를 반환한다.

📍Multiple Fields in Mutation (뮤테이션의 다중 필드)

  • 쿼리 필드는 병렬로 실행 되지만 뮤테이션 필드는 차례대로 실행 된다.
    • 만약 하나의 요청에서 두 개의 incrementCredits 뮤테이션을 보내면 첫 번째 요청이 완료된 다음 두 번째 요청이 완료 된다.


▷ 1-(3) Inline Framents

  • 인라인 프래그먼트로 스키마에 인터페이스와 유니온 타입을 정의할 수 있다.
  • 인터페이스나 유니언 타입을 반환하는 필드를 쿼리하는 경우, 인라인 프래그먼트를 사용 한다.
  • 특정 타입의 필드를 요청하기 위해서는 타입 조건과 함께 인라인 프래그먼트를 사용한다.
    ➡️ 위 쿼리에서 hero 필드는 Character 타입을 반환하는데, 이 때 episode 인자에 따라 Droid 혹은 Human 타입을 반환하게 된다(union).
    ➡️ 즉, hero의 타입이 Droid이면 primaryFunction 필드를 반환하고 타입이 Human이면 height 필드를 반환한다.

📍 Meta Field (메타 필드)

  • 리턴 될 타입을 모르는 상황에서 사용하며, 쿼리의 어느 지점에서나 메타 필드 __typename 을 요청하여 그 시점에서의 객체 타임의 이름을 얻을 수 있다.
    ➡️ 위 쿼리에서 search 는 3가지 중 하나인 유니언 타입 반환하므로, __typename 메타 필드가 없으면 클라이언트가 다른 타입을 구별하는 것을 불가능



2️⃣ Introspection (인트로스펙션 : 스키마 확인)

GraphQL은 인트로펙션이라는 시스템을 제공한다. 다음에서 자세히 알아보자.

  • GraphQL은 인트로스펙션 시스템을 통해 스키마가 어떤 쿼리를 지원하는지에 대한 정보 요청을 가능하게 한다.
  • 인트로스펙션은 서버 자체에서 현재 서버에 정의된 스키마의 실시간 정보를 공유할 수 있게 한다.
  • 이를 확인하여, 클라이언트에서는 실시간으로 현재 서버에서 정의하고 있는 스키마에 맞게 쿼리를 작성할 수 있다.
  • 인트로스펙션을 활용하여, 사용하여 타입 시스템에 대한 문서에 접근 할 수 있고 문서탐색기나 풍부한 IDE 환경을 만들 수도 있다.
  • 보안상의 이슈로 상용환경에서는 이러한 스키마는 공개하지 않도록 하는 것이 좋다고 한다.

💬 ex. 공식 문서 예제

  • __Schema, __Type, __TypeKind, __Field, __InputValue, __EnumValue, __Directive : 모두 앞에 두 개의 밑줄이 붙어있는데, 이것은 스키마 확인 시스템의 일부임을 나타낸다.

1개의 댓글

comment-user-thumbnail
2025년 9월 6일

graphql 정리 감사합니다 👍

답글 달기