아키텍처
아키텍처디렉티브 설계

디렉티브 설계

디렉티브는 중요한 역할을 합니다. GraphQL 명세나 GraphQL 서버 자체에서 기본적으로 지원하지 않는 기능을 구현하는 데 활용할 수 있습니다. 디렉티브는 기능적 공백을 메워 API가 알려진 요구사항이든 알려지지 않은 요구사항이든 충족할 수 있도록 합니다.

이러한 이유로 디렉티브는 GraphQL 서버의 기반에서 매우 중요한 요소입니다. Gato GraphQL은 디렉티브에 대한 견고하고 탄탄한 아키텍처 설계를 채택하여 확장성과 강력한 기능을 모두 갖추고 있습니다.

저수준 기능

설계상의 결정으로, 엔진은 쿼리를 해결하기 위해 디렉티브 파이프라인에 직접 의존합니다. 이러한 이유로 디렉티브는 저수준 컴포넌트로 취급되며, 응답이 저장되는 객체에 대한 접근 권한을 가집니다.

그 결과, 커스텀 디렉티브는 GraphQL 응답을 수정할 수 있는 기능을 갖습니다.

이에 대한 명확한 사용 예로 @remove 디렉티브가 있습니다. 이는 필드의 응답으로 null 값을 받는 것보다 생략하고 싶을 때 쿼리에서 지정할 수 있는 기능입니다(이 기능에 관한 명세의 이슈가 있습니다).

효율적인 디렉티브 호출

디렉티브는 영향을 받는 모든 객체와 필드를 한꺼번에 받아 한 번의 실행으로 처리합니다.

예를 들어, Google Translate API는 최소한의 횟수로 호출되어야 합니다. 다음 쿼리에서는 5개의 게시물에 대해 2개의 필드(title과 excerpt)를 번역하는 총 10개의 텍스트를 포함하여 API 호출이 단 한 번만 이루어집니다.

query {
  posts(pagination:{ limit: 5 }) {
    title
    excerpt
    titleES: title @translate(from: "en", to: "es")
    excerptES: excerpt @translate(from: "en", to: "es")
  }
}

다음 쿼리에서는 언어(스페인어, 프랑스어, 독일어)별로 한 번씩 총 3번의 API 호출이 이루어집니다. 각 호출에는 10개의 문자열이 포함되며, 모든 호출은 동시에 실행됩니다.

query {
  posts(pagination:{ limit: 5 }) {
    title
    excerpt
    titleES: title @translate(from: "en", to: "es")
    excerptES: excerpt @translate(from: "en", to: "es")
    titleDE: title @translate(from: "en", to: "de")
    excerptDE: excerpt @translate(from: "en", to: "de")
    titleFR: title @translate(from: "en", to: "fr")
    excerptFR: excerpt @translate(from: "en", to: "fr")
  }
}

함수 시그니처

다음은 필드 디렉티브 인터페이스입니다. 함수 resolveDirective가 받는 매개변수에 주목해 주세요.

public function resolveDirective(
  RelationalTypeResolverInterface $relationalTypeResolver,
  array $idFieldSet,
  FieldDataAccessProviderInterface $fieldDataAccessProvider,
  array $succeedingPipelineFieldDirectiveResolvers,
  array $idObjects,
  array $unionTypeOutputKeyIDs,
  array $previouslyResolvedIDFieldValues,
  array &$succeedingPipelineIDFieldSet,
  array &$succeedingPipelineFieldDataAccessProviders,
  array &$resolvedIDFieldValues,
  array &$messages,
  EngineIterationFeedbackStore $engineIterationFeedbackStore,
): void;

이러한 매개변수들은 디렉티브의 저수준적 특성을 잘 보여줍니다.

  • $idFieldSet: 디렉티브가 처리할 필드별 ID 목록
  • $succeedingPipelineIDFieldSet: 파이프라인의 후속 단계에서 디렉티브가 처리할 필드별 ID 목록
  • $resolvedIDFieldValues: 응답 객체

그 외의 매개변수들을 통해 쿼리 변수에 접근하고 동적 변수를 정의하거나, 커스텀 데이터를 포함한 메시지를 디렉티브 간에 전달하거나, 오류 및 경고를 발생시키거나, 사용 중단(deprecated)항목을 식별 및 표시하거나, 메트릭을 저장하는 것이 가능합니다.