미래 지향적인 웹 앱 구축: The Codest의 전문가 팀이 제공하는 인사이트
The Codest가 최첨단 기술로 확장 가능한 대화형 웹 애플리케이션을 제작하고 모든 플랫폼에서 원활한 사용자 경험을 제공하는 데 탁월한 성능을 발휘하는 방법을 알아보세요. Adobe의 전문성이 어떻게 디지털 혁신과 비즈니스를 촉진하는지 알아보세요...
이 글에서는 GraphQL에서 다형성의 사용에 대해 설명하겠습니다. 그러나 시작하기 전에 다형성과 GraphQL이 무엇인지 상기할 필요가 있습니다.
다형성 의 핵심 구성 요소입니다. 객체 지향 프로그래밍. 간단히 설명하자면, 서로 다른 클래스의 객체가 동일한 인터페이스에 액세스할 수 있다는 사실에 기반하며, 이는 각 객체에서 동일한 기능을 기대할 수 있지만 반드시 동일한 방식으로 구현될 필요는 없다는 것을 의미합니다. In 루비 개발자 얻을 수 있습니다 다형성 세 가지 방법이 있습니다:
상속 는 부모 클래스와 자식 클래스(즉, 부모 클래스에서 상속)를 생성하는 것으로 구성됩니다. 하위 클래스는 부모 클래스의 기능을 받으면서도 기능을 변경하고 추가할 수 있습니다.
예시:
Document 클래스
attr_reader :이름
end
클래스 PDFDocument < 문서
def 확장
:pdf
end
end
클래스 ODTDocument < 문서
def 확장
:odt
end
end
모듈 Ruby 에는 다양한 용도가 있습니다. 그중 하나가 믹스인입니다(믹스인에 대해 자세히 알아보기 궁극의 분석: 루비 대 Python). Ruby의 믹스인은 다른 프로그래밍 언어의 인터페이스와 유사하게 사용할 수 있습니다(예 Java), 예를 들어 주어진 믹스인을 포함할 객체에 공통된 메서드를 정의할 수 있습니다. 모듈에는 읽기 전용 메서드를 포함하는 것이 좋으므로 이 객체의 상태를 수정하지 않는 메서드는 포함하지 않는 것이 좋습니다.
예시:
모듈 Taxable
def tax
가격 * 0.23
end
end
클래스 자동차
포함 과세 대상
attr_reader :가격
end
클래스 Book
포함 과세 대상
attr_reader :가격
end
이것은 동적 유형 언어의 주요 특징 중 하나입니다. 오리처럼 보이고, 오리처럼 헤엄치고, 오리처럼 꽥꽥거리면 오리라는 유명한 테스트에서 유래한 이름입니다. 그리고 프로그래머 는 주어진 객체가 어느 클래스에 속하는지는 중요하지 않습니다. 중요한 것은 이 객체에서 호출할 수 있는 메서드입니다.
위의 예제에서 정의된 클래스를 사용합니다:
클래스 자동차
attr_reader :가격
def initialize(price)
가격 = 가격
end
end
Book 클래스
attr_reader :가격
def initialize(price)
가격 = 가격
end
end
car = Car.new(20.0)
book = Book.new(10.0)
[car, book].map(&:price
GraphQL 는 비교적 새로운 API용 쿼리 언어입니다. 이 언어의 장점은 구문이 매우 간단하다는 점과 각 고객이 원하는 것을 정확히 얻을 수 있기 때문에 고객이 원하는 것을 정확히 결정할 수 있다는 점입니다.
의 샘플 쿼리 GraphQL:
{
모든 사용자 {
사용자 {
id
로그인
이메일
}
}
}
샘플 응답:
{
"allUsers": {
"users": [
{
"id": 1,
"login": "user1",
"이메일": "[email protected]"
},
{
"id": 2,
"login": "user2",
"이메일": "[email protected]"
},
]
}
}
현재로서는 이것이 우리가 알아야 할 전부일 것입니다. 그럼 본론으로 들어가 보겠습니다.
문제와 해결책을 가장 잘 이해하기 위해 예시를 만들어 보겠습니다. 이 예는 독창적이면서도 현실적인 것이면 좋을 것입니다. 우리 각자가 언젠가 마주칠 수 있는 상황이면 좋겠죠. 동물은 어떨까요? 좋아요! 좋은 생각입니다!
백엔드 애플리케이션이 다음과 같이 작성되어 있다고 가정해 보겠습니다. Ruby on Rails. 이미 위의 체계를 처리하도록 조정되어 있습니다. 또한 이미 다음이 있다고 가정해 보겠습니다. GraphQL 를 구성했습니다. 클라이언트가 다음 구조 내에서 문의를 할 수 있도록 하려고 합니다:
{
allZoos : {
zoo: {
name
city
animals: {
...
}
}
}
}
누락된 정보를 얻으려면 세 개의 점 대신 무엇을 넣어야 하는지 나중에 알아보겠습니다.
아래에서 목표를 달성하는 데 필요한 단계를 설명합니다.
먼저, allZoos 쿼리가 정확히 무엇을 의미하는지 정의해야 합니다. 이를 위해 다음 파일을 방문해야 합니다.앱/그래프QL/유형/쿼리_유형.rb
를 클릭하고 쿼리를 정의합니다:
모듈 유형
QueryType 클래스 < Types::BaseObject
field :all_zoos, [Types::ZooType], null: false
def all_zoos
Zoo.all
end
end
end
쿼리는 이미 정의되어 있습니다. 이제 반환 유형을 정의할 차례입니다.
가장 먼저 필요한 유형은 ZooType입니다. 파일에서 정의해 보겠습니다. app/graphql/types/ zoo_type.rb
:
모듈 유형
ZooType 클래스 < Types::BaseObject
필드 :이름, 문자열, 널: 거짓
field :city, String, null: false
field :animals, [Types::AnimalType], null: false
end
end
이제 AnimalType 유형을 정의할 차례입니다:
모듈 유형
AnimalType < Types::BaseUnion
가능한_유형 코끼리형, 고양이형, 개형
def self.resolve_type(obj, ctx)
if obj.is_a?(Elephant)
ElephantType
elsif obj.is_a?(Cat)
CatType
elsif obj.is_a?(Dog)
DogType
end
end
end
end
에서 무엇을 볼 수 있습니까? 코드 위에?
유형::베이스유니온
.self.resolve_object(obj, ctx),
는 지정된 객체의 유형을 반환해야 합니다.다음 단계는 동물의 종류를 정의하는 것입니다. 하지만 일부 필드는 모든 동물에 공통으로 적용됩니다. 이를 AnimalInterface 유형에 포함시켜 보겠습니다:
모듈 유형
동물 인터페이스 모듈
포함 유형::베이스인터페이스
field :name, 문자열, null: false
field :age, Integer, null: false
end
end
이 인터페이스를 통해 특정 동물의 유형을 정의할 수 있습니다:
모듈 유형
엘리펀트 타입 < Types::BaseObject
Types::AnimalInterface를 구현합니다.
필드 :트렁크_길이, 플로트, 널: 거짓
end
end
모듈 유형
CatType < Types::BaseObject
Types::AnimalInterface를 구현합니다.
field :hair_type, String, null: false
end
end
모듈 유형
DogType 클래스 < Types::BaseObject
Types::AnimalInterface를 구현합니다.
필드 :품종, 문자열, 널: 거짓
end
end
그거예요! 준비 완료! 마지막 질문: 클라이언트 측에서 우리가 만든 것을 어떻게 사용할 수 있을까요?
{
allZoos : {
zoo: {
name
city
animals: {
__유형명
... 엘리펀트 타입 {
name
age
트렁크 길이
}
... on CatType {
name
age
hairType
}
... on DogType {
name
age
breed
}
}
}
}
}
여기에 추가 __typename 필드를 사용하면 주어진 요소의 정확한 유형(예: CatType)을 반환할 수 있습니다. 샘플 답변은 어떤 모습일까요?
{
"allZoos": [
{
"name": "나투라 아티스 매지스트라",
"도시": "암스테르담",
"동물": [
{
"__유형명": "ElephantType"
"name": "프랑코",
"age": 28,
"trunkLength": 9.27
},
{
"__typename": "DogType"
"name": "Jack",
"age": 9,
"품종": "잭 러셀 테리어"
},
]
}
]
}
이 접근 방식의 한 가지 단점은 분명합니다. 모든 동물에 이러한 필드가 있다는 것을 알고 있지만 쿼리에서 각 유형에 이름과 나이를 입력해야 합니다. 컬렉션에 완전히 다른 개체가 포함되어 있을 때는 문제가 되지 않습니다. 그러나 이 경우에는 동물들이 거의 모든 필드를 공유합니다. 어떻게 하면 개선할 수 있을까요?
물론입니다! 파일에서 첫 번째 변경을 수행합니다. app/graphql/types/zoo_type.rb
:
모듈 유형
ZooType 클래스 < Types::BaseObject
필드 :이름, 문자열, 널: 거짓
field :city, String, null: false
field :animals, [Types::AnimalInterface], null: false
end
end
이전에 정의했던 유니온은 더 이상 필요하지 않습니다. 우리는 변화합니다. 유형::동물 유형
에 유형::동물 인터페이스
.
다음 단계는 다음에서 유형을 반환하는 함수를 추가하는 것입니다. 유형 :: 동물 인터페이스
를 추가하고, 직접 사용되지 않는 유형인 orphan_유형 목록도 추가합니다:
모듈 유형
동물 인터페이스 모듈
포함 유형::베이스인터페이스
field :name, 문자열, null: false
field :age, 정수, null: false
정의_방법 do
def resolve_type(obj, ctx)
if obj.is_a?(엘리펀트)
ElephantType
elsif obj.is_a?(Cat)
CatType
elsif obj.is_a?(Dog)
DogType
end
end
end
orphan_types Types::ElephantType, Types::CatType, Types::DogType
end
end
이 간단한 절차 덕분에 쿼리 형식이 덜 복잡해졌습니다:
{
allZoos : {
zoo: {
name
city
animals: {
__유형명
이름
age
... 엘리펀트 타입 {
트렁크 길이
}
... on CatType {
hairType
}
... on DogType {
breed
}
}
}
}
}
GraphQL 는 정말 훌륭한 솔루션입니다. 아직 모르신다면 한번 사용해 보세요. 그만한 가치가 있습니다. 예를 들어 REST API에서 나타나는 문제를 해결하는 데 매우 효과적입니다. 위에서 보여드렸듯이, 다형성 는 실제 장애물이 아닙니다. 이를 해결하기 위한 두 가지 방법을 제시했습니다.
알림:
자세히 보기