GraphQL

B. GraphQL

GraphQL API 맵핑에는 call, publish, subscribe, map 커넥터를 이용 할 수 있습니다.
TypeDefs
GraphQL: {
typeDefs: `
"""Soccer Player"""
type Player implements Node {
id: ID!
email: String!
name: String!
photoURL: String
position: String
"""A team player belongs to"""
team: Team
}
extend type Query {
"""Current Player"""
viewer: Player
player(id: ID!): Player
}
extend type Subscription {
playerMessage: String!
playerUpdated: Player
}
`,
GraphQL 프로토콜에서 typeDefs 속성에 서비스에 필요한 정의(scalar를 제외한 타입, 인터페이스, 열거형 등 모든 형태)을 추가하거나 기존 타입(API Gateway에서 제공하는 기본 타입과 분산 서비스에서 제공한 타입들)을 확장 할 수 있습니다.
Resolvers
resolvers: {
이하 리졸버에 각 타입들의 필드를 call, publish, subscribe, map 커넥터에 맵핑합니다.
Player: {
리졸버가 할당되지 않은 필드들은 source 객체에서 동일한 이름의 속성으로부터 주입됩니다.
Call
team: {
call: {
action: "team.get",
params: {
id: "@source.teamId",
},
},
},
GraphQL API의 QueryMutation 타입의 필드들에는 publishcall 또는 map 커넥터를 이용 할 수 있습니다. params 맵핑에는 @source, @args, @context, @info를 이용 할 수 있습니다.
Map
position: `({ source, args, context, info }) => source.position.toUpperCase()`,
`
GraphQL 프로토콜에서 map 커넥터 (Inline JavaScript Function String)는 간략하게 field: { map: <FN_STRING> } 대신에 field: <FN_STRING> 방식으로 작성 할 수 있습니다.
// be noted that special field __isTypeOf got only three arguments
__isTypeOf: `({ source, context, info }) => return source.someSpecialFieldForThisType != null`,
// be noted that special field __resolveType got only three arguments
__resolveType: `
({ source, context, info }) => {
if (source.someSpecialFieldForThisType != null) {
return "TypeA";
} else {
return "TypeB";
}
}
`,
},
위처럼 Union, Interface 구현 타입을 해석하기 위한 특수 필드에도 Inline JavaScript Function String를 사용합니다.
Batched Call (DataLoader)
Query: {
viewer: {
call: {
action: "player.get",
params: {
id: "@context.user.player.id[]",
},
},
},
player: {
call: {
action: "player.get",
params: {
id: "@args.id[]",
},
},
},
},
위처럼 인증 정보를 포함한 @context나 GraphQL 필드 인자인 @args를 활용해 동일한 액션을 서로 다른 방식으로 맵핑 할 수 있습니다.
또한 call 메소드는 GraphQL 요청에서 발생하기 쉬운 N+1 쿼리를 방지하기 위해 요청을 배치로 처리 할 수 있도록 설계되었습니다. (ref. Dataloader)
한 컨텍스트에서 여러번 호출되는 액션에 배칭을 지원하면 응답 속도를 획기적으로 높힐 수 있습니다. 배칭을 활성화하기 위해서는 call 커넥터의 batchedParams 필드에 배치 처리가 가능한 필드의 이름을 작성하고, 연결된 서비스 액션이 배열로 들어오는 인자 묶음을 처리 할 수 있도록 합니다.
query {
viewer {
id
email
}
one: player(id: 1) {
id
email
}
two: player(id: 2) {
id
email
}
three: player(id: 3) {
id
email
}
}
위와 같은 GraphQL 요청은 player.get 액션을 { id: [context.user.player.id, 1, 2, 3], ...(other common params) } 페이로드와 함께 한번만 호출하게 됩니다. 연결된 액션이 [{ ... }, { ... }, { ... }, { ... }] 묶음으로 응답을 주면 각 필드에 해당하는 응답이 할당됩니다.
만약 id: 3인 플레이어가 없는 경우 배치 요청을 처리하는 과정에서 에러를 발생시켜 제어 흐름을 멈추는 대신에, 에러를 발생키지않고 배치 응답에 포함시키고 나머지 제어 흐름을 마무리합니다. [{ ... }, { ... }, { ... }, { message: "...", isBatchError: true, ... }] 처럼 isBatchError: true 속성을 갖는 에러 객체를 응답에 포함합니다.
Subscribe
Subscription: {
playerMessage: {
subscribe: {
events: ["player.message"],
},
},
GraphQL API의 Subscription 타입의 필드에서는 subscribe 커넥터를 사용 할 수 있습니다. params 맵핑에는 마찬가지로 @source, @args, @context, @info를 이용 할 수 있습니다. @source에 이벤트 객체가 맵핑됩니다.
@source 객체는 { event, payload }로 구성됩니다. Broker에 따라 기타 속성이 추가 될 수 있습니다.
playerMessage: {
subscribe: {
events: ["player.message"],
map: `({ source, args, context, info }) => source.payload.message`,
},
},
},
},
},
subscribe 커넥터에서는 위처럼 수신된 이벤트 페이로드를 다시 map 커넥터로 변환 할 수 있습니다. subscribe 커넥터 안에서 map 커넥터가 사용되지 않는 경우 이벤트 객체 전체(source)를 반환합니다.
Last modified 1yr ago
Export as PDF
Copy link