GraphQL에서 입력 유형의 포인트는 무엇입니까?


83

변이의 입력 인자가 객체라면 왜 입력 유형 이어야하는지 설명해 주 시겠습니까? 아이디를 제공하지 않고 타입 만 재사용하면 훨씬 간단하다고 생각 합니다.

예를 들면 :

type Sample {
  id: String
  name: String
}

input SampleInput {
  name: String
}

type RootMutation {
  addSample(sample: Sample): Sample  # <-- instead of it should be
  addSample(sample: SampleInput): Sample
}

작은 개체에는 괜찮지 만 스키마에 10 개 이상의 속성을 가진 개체가 많으면 부담이됩니다.


30
입력 개체는 직렬화 가능해야합니다. 출력 객체는주기를 포함 할 수 있으므로 입력에 재사용 할 수 없습니다.
Jesse Buchanan

1
제시, 충분한 대답 인 것 같습니다! 대답 할 수 있고 그렇게 표시합니다.
Dmitry Dushkin

궁금 그것과 인터페이스를 결합 할 수있는 경우
MVCDS

답변:


100

사양에서 :

GraphQL 객체 유형 (ObjectTypeDefinition) ...은 [입력으로] 재사용하기에 부적절합니다. 객체 유형은 인수를 정의하는 필드를 포함하거나 인터페이스 및 공용체에 대한 참조를 포함 할 수 있기 때문에 입력 인수로 사용하기에 적합하지 않습니다. . 이러한 이유로 입력 개체는 시스템에서 별도의 유형을 갖습니다.

이것이 "공식적인 이유"이지만, 객체 유형을 입력 객체 유형으로 사용하거나 객체 유형을 입력 객체 유형으로 사용할 수없는 몇 가지 실용적인 이유가 있습니다.

기능성

객체 유형과 입력 객체 유형에는 모두 필드가 있지만 이러한 필드에는 스키마에서 이러한 유형이 사용되는 방식을 반영하는 다른 속성이 있습니다. 스키마는 잠재적 인수 및 개체 유형의 필드에 대한 해결 기능의 어떤 종류를 정의하지만, 이러한 속성 (즉, 당신이 할 수없는 입력 맥락에서 이해가되지 않습니다 해결 - 이미 명시 적 값을 갖는 입력 오브젝트의 필드) . 마찬가지로 기본값은 개체 유형 필드가 아닌 입력 개체 유형 필드에만 제공 될 수 있습니다.

즉, 이것은 중복처럼 보일 수 있습니다.

type Student {
  name: String
  grade: Grade
}

input StudentInput {
  name: String
  grade: Grade
}

그러나 객체 유형 또는 입력 객체 유형에 특정한 기능을 추가하면 서로 다르게 작동 함을 분명히 알 수 있습니다.

type Student {
  name(preferred: Boolean): String
  grade: Grade
}

input StudentInput {
  name: String
  grade: Grade = F
}

유형 시스템 제한

GraphQL의 유형은 출력 유형입력 유형 으로 그룹화됩니다 .

출력 유형은 GraphQL 서비스에서 생성 된 응답의 일부로 반환 될 수있는 유형입니다. 입력 유형은 필드 또는 지시문 인수에 대한 유효한 입력 유형입니다.

이 두 그룹 (예 : 스칼라, 열거 형, 목록 및 Null이 아닌)간에 겹치는 부분이 있습니다. 그러나 공용체 및 인터페이스와 같은 추상 유형 은 입력 컨텍스트에서 의미가 없으며 입력으로 사용할 수 없습니다. 객체 유형과 입력 객체 유형을 분리하면 입력 유형이 예상되는 곳에 추상 유형이 사용되지 않도록 할 수 있습니다.

스키마 디자인

스키마에서 항목을 나타낼 때 일부 항목은 실제로 각각의 입력 및 출력 유형간에 "필드를 공유"할 가능성이 있습니다.

type Student {
  firstName: String
  lastName: String
  grade: Grade
}

input StudentInput {
  firstName: String
  lastName: String
  grade: Grade
}

그러나 객체 유형은 매우 복잡한 데이터 구조를 모델링 할 수 있으며 실제로는 자주 수행합니다.

type Student {
  fullName: String!
  classes: [Class!]!
  address: Address!
  emergencyContact: Contact
  # etc
}

이러한 구조 적절한 입력으로 변환 될 수 있지만 (Student를 생성하므로 해당 주소를 나타내는 객체도 전달 함) 종종 그렇지 않습니다. 목적. 마찬가지로, 반환하고 싶지만 변경하고 싶지 않은 필드가있을 수 있으며, 그 반대도 마찬가지입니다 ( password필드 처럼 ).

더욱이 비교적 단순한 엔터티의 경우에도 개체 유형과 "상대"입력 개체 간의 null 허용 여부에 대한 요구 사항이 다른 경우가 많습니다. 종종 우리는 응답에서 필드도 반환되도록 보장하고 싶지만 입력에 필요한 동일한 필드를 만들고 싶지 않습니다. 예를 들면

type Student {
  firstName: String!
  lastName: String!
}

input StudentInput {
  firstName: String
  lastName: String
}

마지막으로, 많은 스키마에서 주어진 엔터티에 대한 개체 유형과 입력 개체 유형간에 일대일 매핑이없는 경우가 많습니다. 일반적인 패턴은 서로 다른 작업에 대해 별도의 입력 개체 유형을 활용하여 스키마 수준 입력 유효성 검사를 더욱 세부적으로 조정하는 것입니다.

input CreateUserInput {
  firstName: String!
  lastName: String!
  email: String!
  password: String!
}

input UpdateUserInput {
  email: String
  password: String
}

이 모든 예제는 중요한 점을 보여줍니다. 입력 개체 유형이 개체 유형을 언젠가 미러링 할 수 있지만 비즈니스 요구 사항으로 인해 프로덕션 스키마에서이를 볼 가능성이 훨씬 적습니다.


4
이것은 참으로 훌륭한 대답입니다!
Charlie Ng

내가 틀렸다면 정정하지만 귀하의 예에서는 입력에서 유형 Grade을 재사용 할 수 없습니다 StudentInput. 입력 개체의 필드를 인라인하거나 입력 개체가 있어야 GradeInput합니다.
Matt

2
@Matt 좋은 질문입니다! 위의 예에서는 Grade열거 형 유형입니다. 객체와 달리 스칼라 유형 (예 : String, Int 등) 및 enum 유형은 입력 유형 출력 유형 모두 로 사용할 수 있습니다 .
Daniel Rearden

멋진 설명
Visakh Vijayan

참으로 큰 대답!
Johnny

25

Jesse의 의견이 정확합니다. 보다 공식적인 답변을 위해 다음은 입력 유형에 대한 GraphQL 문서에서 발췌 한 것입니다 .

위에서 정의한 Object 유형은 여기서 재사용하기에 부적절합니다. Objects에는 인터페이스 및 공용체에 대한 참조 또는 순환 참조를 표현하는 필드가 포함될 수 있으며, 어느 것도 입력 인수로 사용하기에 적합하지 않습니다. 이러한 이유로 입력 개체는 시스템에서 별도의 유형을 갖습니다.

최신 정보

그것을 게시 한 이후로, 나는 순환 참조가 nilable (또는 무한 체인을 선언하는 한) 한 실제로 허용된다는 것을 발견했습니다. 그러나 입력에 대해 별도의 유형 시스템이 필요한 것처럼 보이는 다른 제한 (예 : 인터페이스)이 여전히 있습니다.


4
이 제한이 존재하는 이유에 대한 더 많은 논의가 있습니다 : github.com/graphql/graphql-js/issues/599
Cam Jackson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.