부스트캠프

GraphQL: Subscription을 통한 실시간 통신 ⚡

o늘do 2020. 12. 13. 23:47

 

바쁘신 분들을 위한 3줄 요약!

  • 위치공유, 채팅, 오더알람 같은 실시간 통신을 구현하기 위해 GraphQL Subscription 사용
  • Subscription 이란 특정 이벤트가 발생시 서버에서 클라이언트로 데이터를 전송해주는 기술
  • GraphQL SubscriptionwithFilter 기능을 사용하여 특정 구독자에게만 데이터를 전송

GraphQL Subscription 이란 ❓

저희의 핵심 기능인 실시간 위치공유, 채팅, 오더 알림을 구현하기 위해 GraphQL Subscription을 사용했습니다. Subscription 은 GraphQL의 한 기능으로 특정한 이벤트가 발생했을 때에 서버에서 클라이언트로 데이터를 보낼 수 있게 해줍니다.

 

GraphQL Subscription을 사용한 이유❗

저희 프로젝트에는 오더 알림이라는 기능이 있습니다. 사용자가 드라이버를 호출하기 위해 탐색버튼을 클릭하면 드라이버는 새로운 오더 알림을 받게 됩니다. 즉 사용자의 드라이버 호출이라는 특정 이벤트에 의해서 드라이버는 서버에서 새로운 오더에 대한 데이터를 받게 되는 겁니다.

 

하지만 모든 드라이버가 알람을 받지 않습니다. 오더를 호출한 사용자를 기준으로 10km 안에 있는 드라이버만 알람을 받게 됩니다. 이를 위해 저희는 Subscription withFilter 을 통해 특정 드라이버에게만 새로운 오더 알람을 띄워 주도록 구현했습니다.

 

그럼 어떻게 GraphQL Subscription 을 구현할까 ❓

GraphQL Subscription은 WebSocket을 기반으로 구현되어 있습니다. 클라이언트에서 서버로 요청을 보낸 후 응답을 받고 연결을 종료하는 HTTP 요청과 달리 GraphQL Subscription 에서는 서버가 구독중인 클라이언트와 지속적인 연결을 유지합니다.

 

저희 서비스로 예를 들면 클라이언트에 해당하는 드라이버는 아래 코드와 같이 오더생성 이라는 관심있는 이벤트를 명시한(SUB_NEW_ORDER) 구독쿼리를 서버에 전송하여 서버와 지속적인 연결을 형성합니다. 드라이버에 해당하는 클라이언트가 오더생성 이라는 관심있는 이벤트를 구독(Subscribe)하게 되는것이죠!

 

이렇게 되면 서버에 새로운 오더에 대한 요청이 왔을때 이를 구독하고 있는 드라이버에게 오더 데이터를 전송하고 오더 데이터를 활용하여 드라이버 화면에 오더알림 팝업창을 띄워 줄 수 있게 되는 것이죠!

useSubscription<SubNewOrder>(**SUB_NEW_ORDER**); // **나 오더 생성 이벤트 구독할거야!!**

자세한 코드가 궁금하시다면 여기❗️를 클릭해주세요 😊

 

다음은 서버 쪽입니다. 특정 이벤트를 구독하고, 이벤트가 발생했을 때에 알림을 주기 위해 필요한 PubSub 이라는 녀석이 존재합니다. PubSub은 Apollo Server에서 제공하는 클래스인데 특정 이벤트의 발생을 알리고(Publish) 이벤트를 감지하여(AsyncIterator) 이를 구독하고 있는 클라이언트에게 데이터를 전송할 수 있는 유용한 API를 제공합니다.

 

이를 통해 저희는 사용자가 오더를 생성했을 때 특정 오더 데이터를 발행(Publish)할 수 있고 이 이벤트를 감지하여 구독하고 있는 드라이버에게 알림을 줄 수 있게 되는 것이죠!

**// 오더가 생성 됐어요!!!**
pubsub.publish(CREATE_NEW_ORDER, {
        subNewOrder: { newOrder: createdOrder },
      });

**// 알겠어요 구독하고 있는 클라이언트에게 오더데이터 알려줄게요!!!**
pubsub.asyncIterator(CREATE_NEW_ORDER),

자세한 코드가 궁금하시다면 **여기❗️**를 클릭해주세요 😊

이를 그림으로 보면 다음과 같습니다!

 

하지만 제주도에 있는 사용자가 드라이버를 호출 했을 때 서울에 있는 드라이버에게 요청이 가면 안 되겠죠? 이를 해결하기 위해 저희는 Subscription withFilter 을 활용했습니다. 말 그대로 특정 이벤트를 구독하고 있는 모든 사용자에게 알림을 주는 것이 아닌 특정 조건을 만족하는 사용자에게만 알림을 주는 것이죠.

 

저희는 오더가 생성되었을 경우 사용자의 위치 기준 10KM 이내에 있는 드라이버에게만 새로운 오더에 대한 알림을 주도록 구현했습니다!

   subscribe: withFilter(
        (_, __, { pubsub }) => pubsub.asyncIterator(CREATE_NEW_ORDER), **//이벤트 감지!!**
        (payload, variables) => {
          return ( **// 특정 거리이내에 드라이버에게만 새로운 오더알림!!!**
            calcLocationDistance(newOrderStartingPoint, driverLocation) <= ORDER.POSSIBLE_DISTANCE
          );
        },

자세한 코드가 궁금하시다면 **여기❗️**를 클릭해주세요 😊

 

 

결론

PubSub(발행/구독) 모델을 이해하고 GraphQL Subscription을 활용해보니 서버에서 발생하는 이벤트를 클라이언트에서 효과적으로 인지할 수 있었습니다. 또한 오더 알림, 위치공유, 채팅 기능들은 특정 사용자와 통신을 하므로 이를 해결하기 위해 Subscription withFilter 이라는 유용한 기능도 적용해 볼 수 있었습니다. 프로젝트를 하면서 GraphQL Subscription 덕분에 실시간 통신이 핵심인 기능들을 비교적 쉽게 구현할 수 있었던 거 같습니다.!

'부스트캠프' 카테고리의 다른 글

웹팩 설정하기  (0) 2020.12.14
Mongoose 에 TypeScript 적용하기  (0) 2020.11.27
TCP/IP, 3-way HandShaking, DNS  (0) 2020.09.05
Day4(해쉬와 단위테스트)  (0) 2020.08.29
링크드 리스트  (0) 2020.08.27