GraphQL의 Subscription은 WebSokect을 기반으로 구현되어있다.
기존 HTTP는 비연결성(Connectionless)과 무상태성(stateless)의 특징이 있다. 클라이언트에서 요청시 서버는 응답을 주고 바로 연결을 끊는 단방향 통신을 준수해야한다.
Socket통신에선 HTTP와는 달리 클라이언트가 서버, 서버는 클라이언트에게 요청을 보낼 수 있는 양방향 통신을 할 수 있는 Stateful한 통신방법이다. 연결을 유지해야한 연결 지향형이므로 실시간 통신이 필요한 경우에 사용한다.(스트리밍, 온라인 게임 같은 경우 자주 사용)
이제 WebSocket는 웹 서버와 웹 브라우저간 실시간으로 양방향 통신환경을 제공해주는 실시간 통신기술이다. 최초의 연결시 접속이 끊어질 때 까지 연결을 유지하며, 프로토콜은 WS를 사용한다
웹소켓 특징
GraphQL에는 조회하는 Query, 쓰고, 수정하고, 삭제하는 Mutation, 그리고 실시간(Real-Time) 애플리케이션을 구현하기 위한 Subscription등이 있다. Query/Mutation은 전통적인 서버/클라이언트 모델을 따르는데 반해, SubScription은 발행/구독(publish/subscribe) 모델을 따른다.
Subscription은 WebSocket을 기반으로하여 실시간으로 양방향 통신기능을 제공한다. 구독을 통해 특정 이벤트가 발생했을 때 서버에서 클라이언트로 데이터를 실시간으로 통신한다.
Subscription은 최초의 사용자가 Mutation 요청을 보내면, Node서버의 Resolver 내부에서 Publish Event가 실행되고, Event Bus에게 알려준다. 그 이후 Subscriber에게 이벤트가 발생했다고 알려준다.
pubsub.publish('POST_CREATED', {
postCreated: {
author: 'Ali Baba',
comment: 'Open sesame'
}
});
POST_CREATED
라는 TriggerName은 해당 이름으로 구독할 경우
@Mutation(returns => Post)
async addComment(
@Args('postId', { type: () => Int }) postId: number,
@Args('comment', { type: () => Comment }) comment: CommentInput,
) {
const newComment = this.commentsService.addComment({ id: postId, comment });
pubSub.publish('commentAdded', { commentAdded: newComment });
return newComment;
}
Query나 Mutation 같은 경우 단순한 함수를 필요로 하지만, subscription은 subscribe 속성을 갖는 객체를 필요로한다. Pubsub
객체의 asyncIterator()
메서드의 인자로 이벤트 명(String)을 작성해주면, subscription은 해당 이름의 이벤트가 발생할 때마다 반응한다.
pubsub.asyncIterator('commentAdded')
ref: https://www.daleseo.com/graphql-apollo-server-subscriptions/, https://chanyeong.com/blog/post/41