-
실시간 시스템 구현을 위한 WebSocket의 이해Web 2021. 10. 22. 17:14
WebSocket에 대해 깊이있게 이해하기 위해 Spring 공식 문서를 보면서 다시 공부해봤다.
이번 글에서는 Raw 웹소켓 상호작용을 포함하는 웹소켓 메시징 방식에 대해 알아본다. 다음 글에서는 WebSocket 스택이 지원되지 않는 브라우저에서도 에뮬레이션을 지원하는 SockJS, Pub/Sub 모델 기반의 하위 프로토콜인 STOMP에 대해 다루고자 한다.Introduction to WebSocket
웹 소켓 프로토콜은 단일 TCP 연결을 통해 클라이언트-서버 간 양방향 통신 채널의 설정을 제공한다. HTTP와는 다른 프로토콜이지만 HTTP 위에서 작동할 수 있도록 설계되어 Port 80과 443을 사용하고 기존의 방화벽 규칙을 사용할 수 있다.
WebSocket 상호 작용은
HTTP Upgrade
헤더를 사용해서 업그레이드하는데, 이 프로토콜로 전환하는 HTTP 요청으로 WebSocket 통신이 시작된다.GET /spring-websocket-portfolio/portfolio HTTP/1.1 Host: localhost:8080 Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg== Sec-WebSocket-Protocol: v10.stomp, v11.stomp Sec-WebSocket-Version: 13 Origin: http://localhost:8080
Upgrade: websocket
→ WebSocket을 사용한다Connection: Upgrade
→ Upgrade 커넥션을 사용한다
해당 요청에 대해 일반적인 200 상태코드를 반환하는 대신, (WebSocket을 지원하는) 서버는 다음과 같은 출력을 반환한다.
HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0= Sec-WebSocket-Protocol: v10.stomp
- HTTP/1.1 101 Switching Protocols → 프로토콜을 변경한다
위의 핸드셰이크가 성공한 후, HTTP 업그레이드 요청의 기반이 되는 TCP 소켓은 클라이언트-서버 간 메시지 통신을 할 수 있도록 계속 열려있다.
WebSocket의 구체적인 작동방식에 대해서는 아래의 원문, 참고자료를 공부하자 ❗
웹소켓 서버가 NginX와 같은 웹 서버 뒤에서 실행되는 경우, 웹소켓 업그레이드 요청이 프록시 서버를 넘어 웹소켓을 실제 지원하는 서버까지 전달하도록 구성해야 한다. 마찬가지로 애플리케이션이 클라우드 환경에서 실행될 경우 WebSocket 지원과 관련된 지침 또한 참고해야 할 것이다.
HTTP 🆚 WebSocket ❓
웹소켓에 대해 이해했다면 "웹소켓, HTTP 통신이 정확이 어떻게 다른데??"라는 고민이 생긴다.
기본적으로 웹소켓은 HTTP와 호환되도록 설계되었고 HTTP 요청으로 핸드셰이킹이 발생하지만, 두 프로토콜은 매우 다른 아키텍처와 애플리케이션 결과물을 만든다.
HTTP와 REST에서 애플리케이션은 End-Point에 해당하는 URL 수만큼 모델링된다. 또한 애플리케이션과의 상호작용을 위해 클라이언트는 Request-Response 방식의 URL에 액세스한다. 서버는 HTTP URL와 메서드, 헤더에 따라 Request를 적절한 핸들러로 라우팅한다.
하지만 웹소켓에선 일반적으로 초기 연결 수립을 위한 하나의 URL만 있다. 이후 모든 애플리케이션 메시지는 해당 TCP 연결 위에서 흐른다. 이는 HTTP 통신과 구분되는 완전한 비동기 이벤트 기반 메시징 아키텍처(Asynchronous, Event-Driven Messaging Architecture)를 나타낸다.
웹소켓은 Low-level의 통신 프로토콜이며, HTTP와는 다르게 메시지 내용에 대해 규정하지 않는다. 즉, 클라이언트와 서버가 메시지 형식에 대해 합의하지 않는 이상 메시지 자체를 라우팅하거나 처리할 수 있는 방법이 없다는 걸 의미한다.
웹소켓 클라이언트와 서버는 HTTP 핸드셰이크 요청에서
Sec-WebSocket-Protocol
헤더와 같은 조금 더 고차원의 메시징 프로토콜 사용을 협의할 수 있다. 그게 없을 경우에는 고유한 컨벤션을 정의하는 과정이 필요할 것 이다.When to Use WebSockets
웹소켓은 실시간 시스템을 더욱 dynamic하고 interactive하게 만드는 하나의 방식이다. 하지만 많은 경우에서 꼭! 웹소켓을 사용하는 것만이 정답은 아니며, Ajax + HTTP streaming / Long polling을 사용하는 게 더 적합한 상황도 있다.
스프링 공식 문서에서 소개하기를, 뉴스/메일/소셜 피드 같은 경우에는 동적인 업데이트를 요구하지만 엄격한 실시간성 보다는 큰 분단위의 업데이트가 더 적합할 수 있다. 반면 Notion과 같은 협업이나 게임, 금융 애플리케이션 같은 경우는 실시간 시스템의 성격을 더 강하게 띤다.
대기 시간뿐만이 아니라, 네트워크 장애 모니터링 시스템과 같이 메시지의 양이 적은 시스템의 경우에도 HTTP Streaming과 폴링이 더 적합할 수 있다.
즉, 웹소켓이 가장 적절하게 활용될 수 있는 시스템은 짧은 지연시간+높은 빈도수+많은 양의 데이터가 실시간으로 오가는 시스템이다.
WebSocket의 내부 Raw API 구현에 대해서는 아래의 링크를 참조하자.
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#websocket-server
정리
WebSocket은 클라이언트-서버 간 실시간 양방향 통신을 위해 사용되는 프로토콜이다.
초기 커넥션 수립 시 HTTP를 이용하며, 해당 TCP 커넥션을 통신을 위해 사용한다.
실시간 통신을 위해서는 HTTP stream, Polling 방식도 있으나 WebSocket이 실시간 시스템 + 높은 트래픽을 가진 애플리케이션에 적용하기에 적합한 기술이다.'Web' 카테고리의 다른 글
JWT(Json Web Token) - 비대칭키 기반 토큰 인증 방식 (405) 2021.11.04 화상 미팅을 간단하게 구현할 수 있는 Kurento와 Openvidu 프레임워크 (420) 2021.11.04 동적 웹 페이지를 구현하기 위한 JSP와 Servlet (420) 2021.10.10 GET Method는 URL을 256자 이하로 제한하지 않는다 (402) 2021.09.18 자주 사용하는 HTTP Status Code (1) 2021.07.27