2023. 2. 7. 16:58ㆍ기술 창고
이전에 라이어게임 프로젝트를 진행하면서 해보고 싶었던 게임 개발을 어느 정도 체험할 수 있었다.
게임을 본격적으로 만들기 위해서는 애초에 Java는 그리 적합한 언어는 아니었지만 내가 가장 잘 다룰 수 있었던 언어가 Java 였고, 이러한 Java 로도 만들 수 있지 않을까 해서 만들게 되었었다.
게임은 실시간으로 유저끼리 대면하여 이루어지도록 구현해야했기에 동기 방식이 아닌 비동기 방식의 기능 구현은 당연했으며, 이를 Spring / Java 에서 녹이기 위해서는 WebSocket 이라는 기술을 사용해야 했다.
결과적으로 완성은 했지만 정확히 WebSocket에 대한 내용을 완벽히 파악하지 않고 사용했다는 느낌이 있기 때문에 정리하고자 한다.
WebSocket
웹 소켓은 클라이언트와 서버 간의 데이터(메시지) 교환을 위한 프로토콜이다.
서버와 클라이언트 간에 만들어진 Socket Connection을 유지해서 언제든 양방향 통신 혹은 데이터 통신이 가능하도록 한다.
WebSocket 특징
(1) 양방향 통신 (Full Duplex)
데이터(메시지)를 에 대한 송신/수신 을 동시에 처리할 수 있는 통신 기법이다.
기본적인 HTTP 는 클라이언트가 서버에 요청을 보내고 그에 대한 응답을 서버에서 보내주는 단방향 통신이지만, WebSocket은 양방향 통신으로서 동작한다.
따라서 비동기 방식이다.
(2) 실시간 네트워킹 (Real Time Networking)
양방향 통신이자 비동기 방식의 특성을 가지고 있어 웹 환경에서 연속된 데이터를 실시간으로 빠르게 노출하고 업데이트 할 수 있다.
(3) Stateful Protocol
클라이언트와 서버가 한 번 연결이 되면 계속 같은 라인을 사용해서 통신하기 때문에 기존의 HTTP 사용시 필요없이 발생되던 HTTP 와 TCP 연결 트래픽을 피할 수 있다.
(4) Header의 크기가 작다.
Header 가 상당히 작아 overhead가 적다.
WebSocket 동작 방식
WebSocket 동작 방식은 크게 세 가지로 분류할 수 있다.
- RED BOX - Opening HandShake (초기 연결 요청 핸드셰이크)
- YELLOW BOX - Data Transfer (웹 소켓 데이터 변환)
- PURPLE BOX - Closing HandShake (연결 끊기 핸드셰이크)
Opening HandShake / Closing HandShake
기본적으로 HandShake 는 TCP 방식의 통신 과정이다.
클라이언트와 서버 간의 요청과 응답으로 연결을 수립하거나 연결을 끊는 것이다.
초기에 접속 요청은 HTTP 요청을 통해 진행한 뒤에 이후 WebSocket 프로토콜로 변경된다. (WS)
<WebSocket 요청 헤더>
GET /chat HTTP/1.1
Host: localhost:8080
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://localhost:9000
(1) GET /chat HTTP/1.1
WebSocket 통신 요청 시, HTTP 버전은 1.1 이상, GET 방식, /chat url로 요청한다는 의미이다.
(2) Host: localhost:8080
요청을 보내는 호스트 url
(3) Upgrade: websocket
프로토콜을 WebSocket 프로토콜로 전환하기 위한 헤더.
WebSocket 요청 시에는 반드시 websocket 이라는 값을 가지고 있고, 이와 다른 값이거나 없으면 cross-protocol attack이라고 간주하고 WebSocket 연결을 중단시킨다.
(4) Connection: Upgrade
현재의 전송이 완료된 이후 네트워크 접속을 유지할 것인가에 대한 정보.
WebSocket 요청 시에는 반드시 Upgrade 라는 값을 가진다.
마찬가지로 Upgrade 라는 값이 없거나 다른 값이 존재한다면 WebSocket 연결을 중단시킨다.
(5) Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
유효한 요청인지 검증하기위한 키 값
(6) Sec-WebSocket-Protocol: chat, superchat
사용하려고 하는 하나 이상의 WebSocket 프로토콜을 지정.
필요한 경우에만 사용한다.
(7) Sec-WebSocket-Version: 13
WebSocket 프로토콜 버전
(8) Origin: http://localhost:9000
CORS 정책으로 만들어진 헤더.
Cross-Site Websocket Hijacking과 같은 공격을 피하기 위함.
http://localhost:9000 주소와 호스트 주소가 CORS 정책에 허용이 되어있지 않다면 이슈 발생.
<WebSocket 응답 헤더>
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
(1) HTTP/1.1 101 Switching Protocols
HTTP 에서 WS (WebSocket)으로 정상적으로 전환되었다는 응답.
101이 정상적으로 완료되었다는 의미이다.
(2) Upgrade: websocket
WebSocket 으로 전환 명시.
(3) Connection: Upgrade
WebSocket 으로 연결 완료 후 네트워크 연결 유지,
(4) Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
요청 헤더의 Sec-WebSocket-Key에 유니크 아이디를 더해서 SHA-1로 해싱한 후 base64로 인코딩한 결과이다.
웹 소켓 연결이 개시되었음을 알린다.
(5) Sec-WebSocket-Protocol: chat
사용하려고 하는 WebSocket 프로토콜을 chat url에 지정.
Data Transfer
Opening HandShake 를 통해 연결 요청이 완료되고나면 Data Transfer가 진행이 된다.
데이터를 메시지 단위로 변환하여 전달한다.
또한, 프로토콜도 ws로 변경된다.
메시지에 포함될 수 있는 교환 가능한 메시지 데이터는 텍스트와 바이너리 뿐이다.
# 메시지 : 여러 프레임이 모여 구성되는 하나의 논리적인 메시지 단위
WebSocket 이 나오기 이전에 양방향 통신과 실시간 네트워킹을 가능하게 했던 방법들이 있다.
Polling
일정한 주기로 서버에 요청을 보내는 방식이다.
setTimeout, setInterval 등으로 일정 주기마다 서버에 요청을 보낸다.
불필요한 요청과 커넥션을 생성하기 때문에 서버에 부담이 된다.
요청주기가 짧을 수록 부하가 커진다.
사실상 일정 주기마다 클라이언트 쪽에서 요청을 보내는 것이기 때문에 실시간이라고 보기에 민망하다.
WebSocket 통신이 아닌 HTTP 통신을 그대로 사용하는 것이기 때문에 헤더가 크다.
따라서 overhead가 발생한다.
Long Polling
Polling 과 마찬가지로 일정 주기마다 요청을 보내지만 서버가 응답을 바로 보내지 않는다.
요청을 보내고 서버가 응답을 바로 보내지 않지만 특정 이벤트가 발생했을 때 응답을 전달한다.
응답이 전달되면 다시 클라이언트가 요청한다.
Polling과 다르게 불필요한 요청을 보내지 않기 때문에 Polling 보다 좋아보이지만, 동시 다발적인 요청과 응답이 생기면 마찬가지로 부하가 발생한다.
HTTP 통신을 그대로 사용하기 때문에 Header도 크다.
Streaming
클라이언트가 요청을 보내고 특정 이벤트가 발생하면 응답을 전달해주지만 응답을 완료시키지 않고 계속 연결을 유지시키는 방식이다.
Long Polling 방식에 비해 다시 요청을 보내는 작업을 하지 않아도 되어 효율적이라고 볼 수 있으나 연결이 지속되기 때문에 연결 시간이 길어질 수록 연결 유효성 관리의 부담이 발생한다.
마찬가지로 HTTP 통신을 그대로 사용하기 때문에 Header가 크다.
WebSocket은 HTML5 기술이기 때문에 오래된 버전의 브라우저는 지원하지 않는다.이를 해결하기 위해 Socket.io 나 SockJS 라이브러리들이 존재한다.
해당 라이브러리들은 WebSocket 을 이용할 수 없는 브라우저 환경에서 양방향 통신을 가능하게 하기 위해 위에서 말한 Polling, Long Polling 과 같은 통신 방식으로 대체하여 유사 양방향 통신을 가능하게 한다.
[도움받은 출처]
https://duckdevelope.tistory.com/19
https://velog.io/@codingbotpark/Web-Socket-%EC%9D%B4%EB%9E%80
'기술 창고' 카테고리의 다른 글
Oauth2 구글 로그인 인증 (클라이언트 ID 발급) (0) | 2023.09.18 |
---|---|
WebRTC (Web Real-Time Communication) (0) | 2023.02.08 |