@WebSocket 추천하지 않음: SSE를 사용한 GraphQL 구독

ietf에 HTTP/2 지원이 추가되지 않았기 때문에 웹소켓은 유행이 지난 기술입니다.서버에서 보내는 이벤트를 사용하면 GraphQL 구독의 실현을 간소화하고 전방 코드를 줄일 수 있으며 현대 전방 응용 프로그램을 작성할 때 성능과 유연성을 높일 수 있다.

가입
GraphQL 구독은 GraphQL 서버에서 GraphQL 클라이언트로 업데이트를 전송하는 메커니즘이다.구독 기능을 사용할 수 있습니다. 예를 들어 채팅방에 새로운 메시지가 나타나면 사용자 인터페이스를 자동으로 업데이트할 수 있습니다.다음은 작업 예입니다.
subscription Chat {
  messages(room: 1) {
    message {
      id
      author
      text
    }
  }
}

그물주머니수송
서버에서 클라이언트로 메시지를 전송하기 위해서는 둘 사이에 지속적인 연결이 필요하다.GraphQL 구독에서 가장 많이 사용되는 전송은 ApolloGraphQL over WebSockets Protocol 기반의 웹소켓을 사용하는 것이다.
나는 이러한 방법의 여러 가지 측면과 왜 우리가 그것을 반대하고 서버 이벤트 보내기 (SSE) 에 더 적합한 기술을 지원해야 한다고 생각하는지 토론하고 싶다.

WebSockets 기반GraphQL 프로토콜
프로토콜을 시작하려면 WebSocket 연결을 여는 것만으로는 충분하지 않습니다.클라이언트는 "connection init"메시지를 보내야 하고 서버는 "ack"로 메시지를 울려야 합니다.웹소켓은 TCP를 통해 작동하기 때문에 왜 메시지 수신을 확인해야 하는지 잘 모르겠습니다.
초기 메시지를 확인한 후 클라이언트는 작업 ID 옆에 GraphQL 작업을 보내야 합니다.클라이언트와 서버는 모든 조작의 ID를 기억해야 한다. 왜냐하면 모든 조작/구독은 하나의 웹소켓 연결을 통해 다중 전송을 하기 때문이다.이것은 서버와 클라이언트의 실현을 너무 복잡하게 한다.SSE가 멀티플렉싱 문제를 해결하기 때문에 이를 개선하는 방법을 살펴보겠습니다.
클라이언트가 구독을 취소하기로 결정하면 WebSocket 연결을 통해 '정지' 메시지를 보내야 합니다.완료 메시지를 보낸 서버에서 다시 확인합니다.마찬가지로 TCP를 계속 사용하기 때문에 왜 이렇게 해야 하는지 잘 모르겠습니다.

WebSocket의 멀티플렉싱
GraphQL의 경우 다중 복용은 여러 구독이 같은 연결을 사용하는 것을 의미한다.WebSockets를 통해 이루어진 상황에서 다중 복용은 자바스크립트를 사용하여 이루어진다.이 코드는 작성과 유지보수가 필요하다.그것은 전송이 필요하고, 모든 브라우저에서 실행되어야 한다.이상적인 상황에서, 우리는 개발을 간소화하기 위해 가능한 한 많은 코드를 삭제하고, 가능한 한 브라우저에서 자바스크립트를 실행할 수 있다.

EventSource/SSE를 통한 멀티플렉싱
서버에서 이벤트를 보내는 브라우저 API의 이름은 EventSource입니다.웹소켓은 양방향 통신을 허용하지만 서버에서 보내는 이벤트 (말 그대로) 는 서버가 이벤트 흐름을 클라이언트로 전송하는 것이지 양방향 전송이 아니다.다행히도 GraphQL 구독을 위해 클라이언트에서 서버로 메시지를 전송할 필요가 없습니다.모든 구독에 대한 이벤트Source를 열기만 하면 됩니다.이것은 클라이언트와 서버의 실현을 간소화시켰다.작업과 ID를 기억하기 위해 더 많은 사용자 정의 코드가 필요하지 않아서 메시지를 정확한 구독과 연결할 수 있습니다.멀티플렉싱은 클라이언트와 서버에서 자동으로 수행됩니다.

HTTP/2
ietf는 HTTP/2를 통해 WebSocket 지원을 추가하지 않기로 결정했습니다.이것은 모든 웹소켓 연결에 대해 브라우저가 서버에 대한 새로운 TCP 연결을 열어야 한다는 것을 의미한다. 왜냐하면 초기 악수는 HTTP/1.1을 기반으로 하기 때문이다.사용자가 사용하는 브라우저에 따라 호스트당 허용되는 TCP 연결 수는 2~8 사이로 평균 5로 변경됩니다.한 사용자가 같은 사이트에서 여러 개의 옵션을 열 수 있다는 것을 명심하십시오. 따라서 가능한 한 열린 연결을 유지해야 합니다.
서버에서 보내는 이벤트에 대해서는 상황이 달라집니다.HTTP/2와 함께 사용할 때 서버는 단일 TCP 연결을 통해 이벤트를 자동으로 보냅니다.즉, 여러 탭에서 동일한 호스트에 대해 100개 이상의 EventSources를 열 수 있으며 TCP 접속 하나만 사용할 수 있습니다.

구성 요소 기반 사용자 인터페이스
현재, 구성 요소를 기반으로 한 단일 페이지 응용 프로그램이 갈수록 유행하고 있다.React, Vue, Flatter 등 프레임워크에는 데이터를 얻고 데이터를 나타낼 수 있는 구성 요소의 개념이 있다.
영구화된 WebSocket 연결을 사용하는 것은 모든 구성 요소에 연결을 사용할 수 있도록 의존항 주입을 사용해야 한다는 것을 의미합니다.
다른 한편, EventSource API를 통해 구독에 필요한 코드를 간소화할 수 있습니다.다음은 React를 사용하는 Hooks API의 예입니다.
const SubscriptionComponent = () => {
    const [data,setData] = useState();
    useEffect(() => {
        // get's called only once when SubscriptionComponent is mounted
        const source = new EventSource("https://example.com/persisted/FooSubscription");
        source.onmessage = e => {
            setData(e.data);
        }
        return () => {
            // get's called when SubscriptionComponent is unmounted
            source.close();
        }
    },[])
    return (
        // re-renders once data updates
        <div>{data}</div>
    )
}
실현은 상당히 간단하다.구성 요소가 설치되면 EventSource를 시작합니다.새 메시지가 setState () 로 밀어 넣어 구성 요소를 다시 보여 줍니다.효과가 끝났을 때 return () => 함수를 사용하면 이벤트 원본을 정리하여 메모리 유출을 피할 수 있습니다.다중 복용을 실현하려면 추가 라이브러리가 필요하지 않습니다.

서버측 구현
클라이언트가 보기에 간단한 것은 서버에서 더욱 간단하다.WebSocket에 비해 서버에서 보내는 이벤트는 추가 의존항 없이 이루어질 수 있습니다.이것Example이 Golang으로 작성된 것을 보고 그것의 실현이 얼마나 간단한지 봐라.

경고
이렇게 많은 적극적인 면이 있는데, 무엇이 네가 이 점을 받아들이는 것을 방해했니?

Internet Explorer
먼저 브라우저의 93.8%가 EventSource API를 지원합니다.한편, 웹소켓 API는 97.41%를 기록했다.이는 IE가 SSE API를 지원하지 않기 때문입니다.이거 차단기야?아니오, 하지만 복잡성을 낮추려는 생각과는 모순됩니다.IE를 지원하려면 부족한 API에 polyfill을 추가해야 합니다.

HTTP/2
HTTP/2와 함께 사용할 때 EventSource API는 매우 의미가 있습니다. 그래야만 하나의 TCP 연결을 통해 모든 구독을 다중으로 전송할 수 있기 때문입니다.따라서 서버나 클라이언트가 HTTP/2를 지원하지 않으면 문제가 발생합니다.만약 고객이 HTTP/2를 사용할 수 있는지 확실하지 않다면, WebSocket을 계속 사용하고 싶을 수도 있습니다.

URL 길이 제한
EventSource를 시작하는 데 사용되는 비polyfill 브라우저 API에서는 유효 로드를 보낼 수 없습니다.즉, 작업과 URL의 질의 문자열에 있는 변수를 보내야 합니다.URL 길이 제한으로 인해 작업을 원래 형식으로 보낼 수 없습니다.이 문제를 해결하기 위해서는 지속적인 검색을 사용하는 것이 좋습니다.나는 이 개념에 대한 세부 사항을 더 알고 싶다면, 지구화 검색에 관한 또 다른 글을 썼다.

요약
서버가 보낸 이벤트와 EventSource 브라우저 API는 클라이언트와 서버의 실현을 크게 간소화시켰다.우리는 코드의 양을 줄일 수 있고 HTTP/2의 성능을 향상시킬 수 있으며 자원의 소모를 줄일 수 있다. 왜냐하면 우리가 실행하는 자바스크립트 코드가 더욱 적기 때문이다.
또한, 우리는 지속적인 검색을 사용해야 하기 때문에, 웹소켓에서 SSE로 이전해야 하지 않습니까?완전히 그렇지는 않다. 이것이 바로 신동도가 나타난 곳이다.

신동
우리는 이미 이전을 끝냈다.WunderGraph는 WebSocket을 사용하여GraphQL 서버를 가져오고 모든 구독을 서버에서 보내는 이벤트로 동적으로 변환합니다.
또한 GraphQL 작업을 영구화하고 원하는 모든 프런트엔드 프레임워크에 클라이언트를 생성합니다.
이것은 당신이 어떤 추가 작업을 하지 않아도 SSE의 모든 이익을 얻을 수 있다는 것을 의미한다.
부작용으로 GraphQL 서버는 더 이상 대중에게 공개되지 않기 때문에 더욱 안전해졌다.이것은 WunderGraph 뒤에 숨겨져 있으며, WunderGraph는 이전에 등록한 지속적인 데이터만 허용합니다.
Try us out!

그리고 하나 더.
WunderGraph의 조회 계획기가 구독을 다른 데이터 원본과 연결할 수 있도록 하는 것을 아십니까?
subscription RocketStatus {
  # rocketStatus is a subscription based on polling a REST API
  rocketStatus {
    speed
    altitude
    aboveCountryCode
    # country gets joined to the Response by querying a GraphQL API using the value aboveCountryCode
    country {
      name
      capital
      currency
    }
  }
}
이 기능은 아주 적은 설정을 통해 모든 종류의 다른 데이터 원본을 연결할 수 있습니다.
앞으로 GraphQL 연방에 대한 지원을 늘릴 계획입니다.이것은 WunderGraph 조회 계획기와 실행 엔진 덕분에 연방 GraphQL에 구독과 더 많은 기능을 제공할 수 있다는 것을 의미한다.
만약 이 기능에 관심이 있다면, 우리가 실현된 후에 당신에게 통지할 수 있도록 전자메일을 채팅방에 남겨 두십시오.

좋은 웹페이지 즐겨찾기