티스토리 뷰

들어가는 말

  • WebSocket 을 좀 봐두어야 할 시점이 되어 정리

WebSocket 이란

  • 하나의 TCP 커넥션으로 full duplex 통신을 제공하는 프로토콜
  • HTTP 와 호환되지만 동일하지는 않다고 함
  • 이후 WebSocket / WS 용어 혼용

WebSocket 의 필요성

  • 서버에서 발생한 이벤트를 클라이언트에 전달하기 위하여 사용
  • WebSocket 이전까지
    • 클라에서 클라 본인이 갱신 된 변경사항이 있는지 주기적으로 요청하여 확인
      • polling 방식
      • 꼭 필요하지 않은 상황에서도 통신이 발생 (클라 입장에서는 주기적으로 호출할 뿐이므로)
      • 구현 난이도는 쉽다고 생각
        • 클라나 서버에서 구현 자체는 쉬울수도 있음
        • 리소스 관리 (커넥션, 서버 자원) 측면에서는 골치 아파질수도
    • 클라가 길게 접속하도록 허용하며 변경 사항이 있을 경우 그 시점에서 응답
      • long polling 방식
      • (이 방법을 고려해본적이 없으므로 정확한 장단점을 이해하기 어려움)
      • Transfer-Encoding : chunked 로 지속적으로 커넥션을 유지
      • 클라쪽에서는 커넥션이 끊어지면 다시 요청
      • 폴링 방식을 개선하기 위해 나온것으로 기억하고 있으며, 특히 커넥션을 새로 맺는 과정 자체를 줄이기 위한것으로 보임
        • 클라이언트마다 커넥션이 살아 있는것은 동일
        • 추가로 응답을 기다리고 있는 여러 클라이언트에 동시에 응답을 처리하는 과정에서 부하가 생긴다는 말도 있음
    • WebSocket 에서는
      • 최초 HTTP 요청(정확히는 WebSocket 을 사용하기 위한 기반 요청)을 통해 WebSocket 커넥션 생성
      • 수립된 WebSocket 연결을 통해 full duplex 로 서버와 클라가 통신
      • 클라이언트마다 커넥션이 살아 있는 것은 동일
        • 역시나 이 방법도 L4 나 Haproxy 같은 reverse proxy 에서는 live connection 이 많아지므로 부하가 많아지지 않을까
    • SSE(Sever Sent Event) 에서는
      • WebSocket 키워드를 들어본 시점이 SSE를 들어본 시점보다 빠르므로 후기에 나온 기술이지 않을까 추정
        • 아님
        • 서로 목적이 다른 장단점이 있는 기술
        • 본 문서의 목적에 벗어나므로 SSE를 파보는건 다음으로
      • 차이점
        • WebSocket 은 양방향 통신을 지원하지만 SSE는 단방향 (Server -> Client) 을 지원
          • 클라에서 동작이 필요하지 않다면 SSE가 더 적합할 수도 있음
        • WebSocket 은 브라우저에서 지원하지 않을때 fallback 프로토콜을 별도로 구현해야하지만 SSE는 클라이언트 기술이므로 서버에서 고려 사항이 적다고 함
        • SSE는 maximum open connections limit 이 존재한다고 함 (그럼 WS는?)
  • HTTP 3.0 기반의 WebTransport 가 있지만 글 작성 시점 (2021.08.) 에서 많이 활성화 된 것으로 보이지는 않음 (못찾은걸수도)
  • 자세한 사항은 다음 글 및 아티클 참조

번외 - STOMP

중간정리

  • HTTP 프로토콜 기술 발전에 따라 서버와 클라간에 실시간 통신을 위하여 여러가지 기술들이 발전해 왔음
  • WS는 실시간성 양방향 바이너리 통신이 지원
  • SSE와 WS 는 선행, 후행기술이 아니며 성격이 다른 기술
  • 다음 진행 사항
    • spring 관점에서 websocket 파악
    • spring websocket 과 stomp

백각이 불여일행

  • https://spring.io/guides/gs/messaging-stomp-websocket/
    • 문서와 설명이 잘 되어있으므로 해당 가이드를 따라가 봄
  • 이후 특이사항 기록
    • 최초 spring initializr 로는 WebSocket 만 추가
    • 검증에 클라이언트 부분을 필요로 하는것으로 보이며 의존성 필요
    • @EnableWebSocket, @EnableWebSocketMessageBroker 무슨 차이일지
    • 딱히 특이사항은 없는듯 (차라리 리눅스에서 했으면 했지 윈도우에서는 개발하지 말자...)
  • connection 버튼 동작
  • 메시지 전송
    • 동시에 접속한 다른 커넥션에서도 잘 수신되는것을 확인
  • 일단 대충은 알겠는데 대충만 알겠음 -> 스프링 레퍼런스 문서 확인 필요

spring guide

HTTP와 WS의 차이

  • WS가 HTTP와 호환되고 HTTP 연결을 통해서 시작하지만, 두 프로토콜은 아키텍쳐와 목적이 다름
  • HTTP와 REST는 요청과 응답 동작을 근간으로 리소스들에 매핑된 여러개 URL, HTTP Method, HTTP Header 들에 기반으로 동작
  • WS 의 경우는 하나의 URL 을 통해 커넥션을 수립하며, 이후 TCP 연결을 기반으로 메시지들이 '비동기','이벤트드리븐','메시징기반' 으로 처리
  • WS 자체는 로우레벨 프로토콜이며 HTTP 와 다르게 메시지 자체에 의미가 부여되어 있지 않음 (REST 랑 비교해서도)
  • 별도의 상위(구체화)된 프로토콜을 사용할 수도 있지만 여기서는 STOMP를 사용

WebSocketHandler

WebSocket Handshake

  • registerWebSocketHandlers 에서 ws handshake 과정을 커스터마이징 할 수 있음 (before, after)
  • DefaultHandshakeHandler를 상속하는 방법도 가능
    • sub protocol 을 결정한다던가 인증에 사용할 수 있음
  • 그외에 WebSocketHandlerDecorator를 써서 WebSocketHandler의 추가적인 동작을 덧붙일수도 (로깅, 익셉션 핸들링)

Deployment

  • Spring WebSocket API는 Spring MVC와 쉽게 통합 가능
    • DispatcherServlet 에서 HTTP WebSocket handshake이나 그외 HTTP 요청 처리
  • The Java WebSocket API (JSR-356)은 두가지 배포(등록?) 메커니즘이 있음
    • TODO 이 부분은 정확하게 이해하지 못했으므로 기록후 재확인
    • 1) 스타트업 시점에서 서클릿3의 서블릿 컨테이너 클래스 패스 스캔을 통한 등록
    • 2) 서블릿 컨테이너 초기화 과정에서 registration API를 사용하는 방법
    • 하지만 두가지 방법 모두 DispatcherServlet 과 같은 WebSocket handshake 와 HTTP 요청을 청리하는 "front contrller" 역할을 하지는 못함
      • (앞서 DispatcherServlet 이 엄밀히는 두가지 모두 지원하지만 동시에는 안된다는 말인가? 아니면 명시적으로 서버를 분리하라는 소리인가?)
      • (그것도 아니라면 Spring WebSocket 과 Java WebSocket API JSR-356은 명백히 다른것을 지칭하는것이려나)
        • 여기도 구현체가 다른듯 과거 문서 확인 시 명시
        • Spring Framework 4 includes a new spring-websocket module with comprehensive WebSocket support. It is compatible with the Java WebSocket API standard (JSR-356) and also provides additional value-add as explained in the rest of the introduction.
  • 그 다음 고려사항으로 Servlet containers with JSR-356 support 에서는 ServletContainerInitializer (SCI) 이 어플리케이션 스타트업을 느리게 만들 수 있음
    • TODO 선택적으로 를 써서 web fragments (and SCI scanning)을 활성화하라고 함

Server Configuration

  • ServletServerContainerFactoryBean을 빈으로 등록해서 런타임 프로퍼티 등록 가능
    • WAS에 따라 다름
  • 클라이언트쪽 WebSocket 설정을 위해서는 ContainerProvider.getWebSocketContainer()를 사용하라고 함

Allowed Origins

  • 기본 방침은 to accept only same-origin requests
  • Cross Origin 을 위해서라면 별도 처리 필요
  • 정책상 3가지 방법 존재
    • Allow only same-origin requests (default)
    • Allow a specified list of origins
    • Allow all origins
  • 어떤 정책이냐에 따라서 IE 버전별로 지원이 되는 부분이 있고 지원되지 않는 부분이 있음
    • SockJS fallback 에 따라서 다른듯
  • 핸들러 등록 시점에서 .setAllowedOrigins("https://mydomain.com") 방법으로 가능

나가는말

  • 스프링 레퍼런스 문서에서 SockJS Fallback, STOMP 항목은 일단 봐보고 필요하다면 정리
    • STOMP은 정리가 필요할것 같음

레퍼런스

https://www.itfind.or.kr/publication/regular/weeklytrend/weekly/view.do?boardParam1=8034&boardParam2=8034
https://til-perfectacle.netlify.app/2018/11/18/http2-websocket-sse/
https://hamait.tistory.com/792
https://stackoverflow.com/questions/40988030/what-is-the-difference-between-websocket-and-stomp-protocols
https://velog.io/@gillog/Protocol-STOMP
https://spring.io/guides/gs/messaging-stomp-websocket
https://developer.mozilla.org/ko/docs/Web/API/WebSocket
https://www.baeldung.com/websockets-spring
https://velog.io/@koseungbin/WebSocket

https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket

'개발관련 > 미분류' 카테고리의 다른 글

기술 센싱 사이트  (0) 2021.05.06
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함