thumnail.png

최근 프로젝트에서 GraphQL을 통해 프로젝트를 진행했고, 그 과정에서 GraphQL Subscription이라는 기능을 많이 사용했다. 최근 포스팅한 React와 GraphQL로 채팅 구현하기 포스트 또한 해당 부분을 공부하기 위해 정리한 포스트이다. 그래서 오늘은 GraphQL Subscription에 대해 좀 더 깊게 정리해보려고 하는데 사용법 보다는 Subscription이 어떤 방식으로 동작하는지에 대해 알아보려고 한다.

Subscription이란?

GraphQL에서 수행할 수 있는 Query, Mutation에 이은 세 번째 작업 타입이다. 데이터 조회에 Query를 사용하고 데이터 조작에 Mutation을 사용하면 Subscription은 어디에 사용할까? 바로 실시간 통신에 사용한다.

Subscription은 이름 그대로 구독/발행 모델을 기반으로 WebSocket을 통해 실시간 양방향 통신 기능을 제공한다. 구독을 통해 특정한 이벤트가 발생했을 때 서버에서 클라이언트로 데이터를 실시간으로 통신하게 된다.

basic.png

Subscription은 다음과 같은 과정으로 진행된다. 처음에 사용자가 Mutation요청을 보내면 해당 Mutation의 Resolver 내부에서 Publish Event가 실행되며 Event Bus에게 알려준다. 그러면 Event Bus는 해당 이벤트를 구독하고 있는 Subscriber에게 이벤트가 발생되었다고 알려주게 된다.

왜 Subscription을 사용해야 하는데?

Subscription을 사용하지 않고 서버의 상태 변화를 감지하기 위해서는 주기적으로 HTTP요청을 서버로 보내 변경된 상태가 있는지 지속적으로 확인하는 방법 또한 있다.

하지만 아무리 자주 호출하더라도 완벽하게 실시간으로 통신하기는 어렵고 클라이언트에서 주기적으로 요청을 보내줘야 하기 때문에 자원의 낭비가 심할 수 있다.

구독 과정

그렇다면 GraphQL에서 Subscription이 어떻게 동작하는지 더 자세하게 알아려고 한다. 먼저 구독 과정부터 살펴보자!

st1.png

구독 과정은 다음과 같이 진행된다.

  1. 클라이언트가 서버로 Subscribe 요청(쿼리와 변수 포함)을 보낸다.
  2. 서버는 해당 쿼리가 올바른 쿼리인지 확인한다.
  3. 단일 PubSub객체를 통해 Event Bus에 이벤트 발생을 감지
  4. 클라이언트가 요청한 Subscription 활성화

여기서 PubSub이란 Publish-Subscribe의 줄임말로 구독 이벤트 발생 및 감지를 위해 사용하는 객체이다. 그런데 여기서 Single PubSub을 사용하는 이유는 서버를 클러스터 모드(Node.js의 pm2 기준)로 실행하는 경우 각 인스턴스에 PubSub이 존재하게 된다. (서버를 여러 인스턴스로 실행하는 경우)

클라이언트에서 요청을 보낼 때 해당 인스턴스로 구독 이벤트가 발생이 되야 업데이트가 되는데 어떤 PubSub을 가진 인스턴스에게 요청을 보낼 지 모르기 때문에 이벤트 발생 감지를 불안정하게 할 수 있다.

그렇기 때문에 redis등을 사용해 단일 PubSub을 사용하면 해당 문제가 발생하지 않는다.

구독 취소 과정

그렇다면 다음으로는 구독을 취소하는 과정을 살펴보자!

st2.png

구독 취소 과정은 좀 더 간단하다.

  1. 클라이언트가 서버로 구독 취소 요청을 보낸다. (양방향 연결 해제)
  2. PubSub은 Event Bus의 이벤트 발생 감지를 취소한다.

이벤트 발생 과정

그렇다면 마지막으로 구독한 Subscription에 이벤트가 발생했을 경우 데이터를 받아오는 과정에 대해 살펴보자!

st3.png

다음은 이벤트가 발생하고 클라이언트에게 구독 중인 데이터를 전송하는 과정이다.

  1. 익명의 클라이언트가 서버로 Mutation 요청을 보낸다.
  2. 해당 Mutation에서 PubSub객체를 통해 Event Bus로 이벤트가 발생했다고 알려준다.
  3. Event Bus에서 이벤트 발생을 감지하고 있던 PubSub에게 이벤트 발생을 알려준다.
  4. PubSub은 서버에서 해당 구독 이벤트의 반환값을 받는다.
  5. 받은 반환값을 Client에게 전송해준다.

결론

이번 포스트에서는 Subscription이 어떤식으로 동작하는지 알아보았다. 간략하게 다시 정리하면

  1. Subscription은 GraphQL 작업 타입 중 하나로 WebSocket을 통한 실시간 양방향 통신 기능이다.
  2. Publish-Subscribe 의 구조로 이루어져 있어 퍼블리셔가 이벤트를 발생시키면 구독자는 해당 이벤트를 구독하여 데이터를 수신할 수 있다.
  3. PubSub객체는 구독 이벤트 발생 및 감지에 사용하며, 서버가 여러 인스턴스인 경우 단일 객체로 운영해야 한다.

정도 되는 것 같다. 이번에 GraphQL Subscription기능을 정말 많이 활용하면서 내부 구조 또한 알고 있으면 좋을 것 같아 정리해 봤는데 처음에는 엄청 어렵다고 생각했던 기능이 조금씩 이해할수록 재밌어졌던 것 같다. 앞으로도 실시간 통신을 사용할 일이 많을 것 같은데 좀 더 깊이있게 공부하고 싶다. (나중에는 redis를 통해 단일PubSub객체를 만드는 것 까지...)

본 포스트는 다음 문서를 참고해 작성했습니다.

https://dev.to/pmbanugo/an-introduction-to-graphql-subscriptions-50fd