WebSocket을 통한 GraphQL

This article was published on 2020-09-15 by @ The Guild Blog



WebSocket을 통한 GraphQL



A couple of years ago, while I was still working at Apollo, Lee Byron, Rob Zhu, Dotan simha and I worked on the GraphQL Subscriptions spec and the reference implementation.

During that work, we created and merged the reference implementation into graphql-js and created two supporting libraries: graphql-subscriptions and subscriptions-transport-ws. Here is a talk with deep dive into all the details.

Since leaving Apollo, not a lot of work has been gone into those libraries.
That's why I was so thrilled that Denis decided to pick up that important work and create a new library for the WebSocket Protocol.

We will support his work of maintaining the library and standardizing it with the GraphQL over HTTP working group.
This is a part of a lot of exciting work coming up about GraphQL and real-time, so follow us for new things in this space!

Denis will take it away from here!



소개



웹 개발 여정 중 어느 시점에서 실시간 구성 요소를 추가해야 하는 문제에 직면했을 수 있습니다. 브라우저에서 실시간의 동의어는 WebSocket API입니다. This is how MDN's describes it :

The WebSocket API is an advanced technology that makes it possible to open a two-way interactive communication session between the user's browser and a server. With this API, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.



Google Chrome은 WebSocket 프로토콜을 지원하는 최초의 브라우저로 2009년에 지원을 추가했습니다. 2011년에 공식적으로 표준화되기 2년 전입니다. 전이중 서버-클라이언트 통신에 대한 요구가 높아짐에 따라 다른 브라우저도 그 뒤를 따랐습니다.

현재 모든 주요 브라우저는 WebSocket 프로토콜을 지원합니다(Can I Use table 참조).

웹소켓 ❤️ GraphQL



자, 그렇다면 WebSocket을 사용하여 GraphQL subscription operation에 대한 지원을 추가하려면 어떻게 해야 합니까? 기본 Google 검색을 수행하면 subscriptions-transport-ws 이라는 단일 솔루션에 직면하게 됩니다. 리포지토리를 살펴보고, 최근 댓글을 확인하고, 문제를 읽고, 공개 PR을 하다 보면 수많은 버그와 보안에 미치는 영향을 알아차릴 수 있을 것입니다. A summary can be found here .

저자들은 훌륭한 일을 해냈지만 불행히도 다른 프로젝트와 요구 사항으로 인해 이 잘 수행되었지만 필요한 아이디어를 유지하고 육성하는 데 필요한 시간이 단축되었습니다. 그러나 그것은 정말로 저에게 그들의 유산을 계승하고 그것을 활성화하도록 영감을 주었습니다! 직접 GraphQL을 사용하여 다양한 WebSocket 문제에 직면한 저는 처음부터 새 라이브러리를 작성하기 시작했습니다.

더 이상 고민하지 않고 겸손하게 소개합니다 graphql-ws . Queries , MutationsSubscriptions 3가지 GraphQL 작업을 모두 완벽하게 지원하는 new, security first GraphQL over WebSocket Protocol의 일관성 있고 완전한 기능, 제로 종속성, 플러그 앤 플레이, 지연, 단순, 서버 및 클라이언트 구현 . 이 프로토콜은 재단GraphQL over HTTP work group의 도움으로 표준화되고 GraphQL의 일부가 되는 것을 목표로 합니다.

라이브러리는 TypeScript로 작성되었으며 전체 구현은 형식이 지정되고 주석 처리된 코드가 ~1000줄에 불과합니다. 최신 JavaScript 기본 요소와 잘 확립된 WebSocket의 존재를 활용합니다.

시작하려면 어떻게 해야 하나요?



물어봐주셔서 기쁩니다! 방법은 다음과 같습니다.

설치




$ yarn add graphql-ws


GraphQL 스키마 생성




import { buildSchema } from 'graphql'

// Construct a schema, using GraphQL schema language
const schema = buildSchema(`
  type Query {
    hello: String
  }
  type Subscription {
    greetings: String
  }
`)

// The roots provide resolvers for each GraphQL operation
const roots = {
  query: {
    hello: () => 'Hello World!'
  },
  subscription: {
    greetings: async function* sayHiIn5Languages() {
      for (const hi of ['Hi', 'Bonjour', 'Hola', 'Ciao', 'Zdravo']) {
        yield { greetings: hi }
      }
    }
  }
}


서버 시작




첨부ws



import ws from 'ws' // yarn add ws
import { useServer } from 'graphql-ws/lib/use/ws'

const server = new ws.Server({
  port: 4000,
  path: '/graphql'
})

useServer(
  // from the previous step
  { schema, roots },
  server
)

console.log('Listening to port 4000')




첨부uWebSockets.js



import uWS from 'uWebSockets.js' // yarn add uWebSockets.js@uNetworking/uWebSockets.js#<tag>
import { makeBehavior } from 'graphql-ws/lib/use/uWebSockets'

uWS
  .App()
  .ws(
    '/graphql',
    makeBehavior(
      // from the previous step
      { schema, roots }
    )
  )
  .listen(4000, (listenSocket) => {
    if (listenSocket) {
      console.log('Listening to port 4000')
    }
  })




첨부fastify-websocket



import Fastify from 'fastify' // yarn add fastify
import fastifyWebsocket from 'fastify-websocket' // yarn add fastify-websocket
import { makeHandler } from 'graphql-ws/lib/use/fastify-websocket'

const fastify = Fastify()
fastify.register(fastifyWebsocket)

fastify.get(
  '/graphql',
  { websocket: true },
  makeHandler(
    // from the previous step
    { schema, roots }
  )
)

fastify.listen(4000, (err) => {
  if (err) {
    fastify.log.error(err)
    return process.exit(1)
  }
  console.log('Listening to port 4000')
})


클라이언트 사용




import { createClient } from 'graphql-ws'

const client = createClient({
  url: 'ws://welcomer.com:4000/graphql'
})

// query
;(async () => {
  const result = await new Promise((resolve, reject) => {
    let result
    client.subscribe(
      {
        query: '{ hello }'
      },
      {
        next: (data) => (result = data),
        error: reject,
        complete: () => resolve(result)
      }
    )
  })

  expect(result).toEqual({ hello: 'Hello World!' })
})()

// subscription
;(async () => {
  const onNext = () => {
    /* handle incoming values */
  }

  let unsubscribe = () => {
    /* complete the subscription */
  }

  await new Promise((resolve, reject) => {
    unsubscribe = client.subscribe(
      {
        query: 'subscription { greetings }'
      },
      {
        next: onNext,
        error: reject,
        complete: resolve
      }
    )
  })

  expect(onNext).toBeCalledTimes(5) // we say "Hi" in 5 languages
})()


더 알아보시겠습니까?



바닐라 사용의 경우 일부 Getting Started 또는 RecepiesRelay 을 사용하여 Apollo Client 에 대한 리포지토리를 빠르게 확인하십시오. 문제를 열거나, 코드에 기여하거나, 단순히 문서를 개선하는 것은 언제나 환영입니다!

저는 @enisdenjo이고 언제든지 GraphQL Slack workspace에서 이 주제에 대해 저와 채팅할 수 있습니다.

읽어주셔서 감사합니다. 행복한 코딩을 하세요! 👋

좋은 웹페이지 즐겨찾기