본문 바로가기

개발바닥/GraphQL

[개발] GraphQL - Interface와 Union에 대한 이해

안녕하세요 devport 입니다. 이번 포스팅에서는 graphql의 interface와 union 타입에 대해서 알아보도록 하겠습니다.

 

interface Type

interface type은 지정된 타입에서 특정 필드를 구현할 것을 약속하는 추상형식의 타입입니다.  그렇기 때문에 인터페이스에서 선언된 필드들은 정확히 유사하게 구현되어야 합니다.

 

interface Human {
  id: ID!
  name: String
  guildId: ID
}

Type Knight implements Human {
  id: ID!
  name: String
  guildId: ID
  energy: Int
}

Type Wizard implements Human {
  id: ID!
  name: String
  guildId: ID
  mana: Int
}

Knight, Wizard에서 Human 인터페이스를 구현하기 위해서 Human에서 지정된 필드값을 똑같이 구현되어야 합니다.

두 타입 모두 id와 name의 필드를 가지고 있습니다.

또한, interface의 규칙을 지켜나가면서 여러 Type의 데이터를 사용하여 Query를 할때에도 유용합니다.

예를 들자면 길드에 가입되어 있는 모든 Human을 찾는다고 할때에 "findHumanAtGuild" 쿼리로 할 수 있도록 한다면

type Query {
  findHumanAtGuild(guildId: ID!): [Human]
}

type Guild {
  id: ID!
  name: String
  address: String
}

"findHumanAtGuild"는 guildId와 일치하는 Human의 목록을 반환하게 됩니다. 

id, name, guild 속성은 Human의 공통 속성이기 때문에 별도의 처리는 필요하지 않지만 Knight, Wizard가 지니는 고유 속성은 inline fragment를 사용하여 쿼리를 하여야 합니다. inline fragment로 처리 하지 않고 공통 필드로 지정하게 된다면 에러가 발생하게 됩니다.

아래에 인터페이스를 사용하는 쿼리를 구현해보겠습니다.

query {
  findHumanAtGuild(guildId: 0) {
    id
    name
    guildId
    ... on Knight {
      energy
    }
    ... on Wizard {
      mana
    }
  }
}

위와 같이 쿼리를 하게 된다면

{
  "data": {
    "findHumanAt": [
      {
        "id": 0,
        "name": "기사"
        "guildId": 1
        "energy": 10
      },
      {
        "id": 1,
        "name": "마법사"
        "guildId": 1
        "mana": 10
      }
    ]
  }
}

위와 같이 Knight, Wizard타입이 혼재되어 반환될 수 있다는 것을 알 수 있습니다.

 

Union Type

Union Type은 Interface Type 과 유사하지만 타입 간의 공통필드를 지정되지 않는다는 부분이 있습니다.

예로, union Type을 SearchResult와 같이 정의 할 수 있습니다. 

type Query {
  findHumanAtGuild(guildId: ID!): [Human]
  search (query: String!): [SearchResult]
}

union SerachResult = Knight | Wizard

SearchResult를 결과로 사용하는 search로 쿼리를 한다면 아래와 같이 하면 됩니다.

query {
  ... on Knight {
    id
    name
    guildId
    energy
  }
  ... on Wizard {
    id
    name
    guildId
    mana
  }
}