NestJS + GraphQL : PubSub

Outclass·2022년 8월 30일
0

NestJS+GraphQL+TypeORM 

목록 보기
15/16
post-custom-banner

1. PubSub이란?

  • Publish / Subscription
  • 서버에서 특정 이벤트 구독(Subscription)하고 있다가, 해당 이벤트가 발생(Publish)했을 시의 동작을 정의할 수 있는 기능이다.
  • 데이터 흐름의 추적은 실시간으로 이루어진다.
  • 여러 사용자가 하나의 이벤트를 구독할 수 있으며, 해당 이벤트가 발생하면 구독한 사용자들에게 동시에 이벤트가 전파된다.

단, 오늘 예제로 사용되는 graphql-subscriptions은 일종의 데모 버전으로 하나의 서버로만 운영할 수 있음, 대규모 서버를 구축할 시 redis등을 유료로 사용해야 함

2. 설치하기

npm i graphql-subscriptions

3. 구현하기

1) 웹소켓 사용하기

//app.module.ts
GraphQLModule.forRoot<ApolloDriverConfig>({
  driver: ApolloDriver,
  installSubscriptionHandlers: true,
}),
  • installSubscriptionHandlers: true : 웹소켓을 사용할 수 있게 해준다

2) PubSub 전역으로 설정하기

//common.module.ts
import { Global, Module } from '@nestjs/common';
import { PubSub } from 'graphql-subscriptions';
import { PUB_SUB } from './common.constants';

@Global()
@Module({
  //! 특정 클래스를 전역으로 사용 -> exports해줘야 함
  providers: [
    {
      provide: PUB_SUB,
      useValue: new PubSub(),
    },
  ],
  exports: [PUB_SUB],
})
export class CommonModule {}
  • common등의 모듈을 만들고, Global로 지정한다
  • Providers에 PubSub을 등록한다

3) Subscription

//orders.resolver.ts
@Subscription((returns) => Order)
pendingOrders() {
  return this.pubSub.asyncIterator(NEW_PENDING_ORDER);
}
  • @Subscription 데코레이터로 구독을 만든다
  • asyncIterator에서 NEW_PENDING_ORDER을 구독(subscription)한다
  • NEW_PENDING_ORDER 이름의 이벤트가 publish되면 구독하고 있던 resolver가 실행된다

4) Publish

//oderes.service.ts
async updateOrders () {
  ...
  await this.pubSub.publish(NEW_PENDING_ORDER, {
  	pendingOrders: { order, ownerId },
  });
  ...
}
  • publish의 첫번째 인자의 이름으로(NEW_PENDING_ORDER) 이벤트가 발생한다.
  • 두번째 인자로 이벤트 발생과 함께 payload가 전달된다.

5) Subscription filter, resolve

@Subscription((returns) => Order, {
  filter: (payload, variables, context) => {
    return payload.pendigOrders.ownerId === context.user.id;
  },
  resolve: ({ pendigOrders: { order } }) => `${order.id}님의 주문이 업데이트 되었습니다`,
})
pendingOrders() {
  return this.pubSub.asyncIterator(NEW_PENDING_ORDER);
}

filter

  • filter를 사용하면, 구독하고 있는 이벤트 중 특정 조건에 맞는 이벤트가 publish될때만 resolver가 작동한다
  • payload : publish될 때 전달되는 값이 담겨있다.
  • varialbes : subscription한 resolver가 요청할 때 전달되는 값이 담겨있다.
  • context : NestJS의 네트워크 통신시 생겨나는 컨텍스트에 접근할 수 있다(http, ws)
  • 조건에서 true를 반환해야 필터가 통과된다.

resolve

  • resolve를 통해 resolver가 리턴할 값을 정의할 수 있다.

6) PubSub으로 token에 접근하기

//app.module.ts
subscriptions: {
  'subscriptions-transport-ws': {
    onConnect: (connectionParams) => {
      const token = connectionParams[TOKEN_KEY];
      return { token };
    },
  },
},
  context: ({ req, connection }) => {
    return {
      token: req ? req.headers[TOKEN_KEY] : connection.context[TOKEN_KEY],
    };
  },
}),
  • PubSub은 http가 아닌 ws를 사용하기 때문에, context의 req가 아닌 connection에서 값을 받아온다.
profile
When you stop having big dreams that’s when you’ve died, despite not being buried yet.
post-custom-banner

0개의 댓글