이번 주 CS스터디의 주제는
Web Socket
이었습니다.
프로젝트에도 채팅 기능이 도입될거라 간단하게 조사해봤습니다.
웹 소켓은
실시간
으로 메시지를 교환하는 프로토콜입니다!
채팅이나 주가를 갱신하는 등의 실시간으로 동작해야 하는 기능에 많이 쓰입니다.
웹 소켓말고 다른 방식으로 위의 기능을 구현할 수는 없을까요?
주기적으로 서버에 데이터를 요청해서 갱신하는 Polling 방식이 있습니다.
(Long Polling 방식은 결국 요청이 잦아지면 Polling과 유사해지니 이번 설명에서는 생략하겠습니다.)
Polling 방식은 일정 시간마다 요청을 보내니 메세지가 갱신된 상황이 아니면 불필요한 요청을 보내게 됩니다. 요청마다 TCP 연결 및 해제를 해야하고, HTTP 헤더의 크기도 큰 단점이 있습니다. 또한 가장 큰 단점은
실시간
이라 보기엔 어렵다는 것입니다!
웹소켓의 경우 한 번의 TCP 연결로 지속적인 양방향 통신이 가능합니다. 텍스트 프레임과 이진 데이터 프레임이 전송 가능하고, HTTP로 통신하는 Polling 방식보다 가볍습니다. 또한 가장 큰 장점은
실시간
통신이라는 것이죠!
가볍게 RFC 6455의 예시를 살펴보죠!
아래와 같이 웹소켓을 생성하면, 주석과 같은 요청을 보내게 됩니다.
웹 소켓을 연결할 때는 Opening Handshake에서 GET으로 웹 소켓 업그레이드 요청을 보냅니다.
Sec-WebSocket-Key
를 서버에 전달합니다.
서버가 웹 소켓을 지원한다면 101 상태 코드를 반환합니다. 또한
Sec-WebSocket-Key
값에 고정된 GUID 문자열을 추가하고 해싱을 한다음 base64로 인코딩하여Sec-WebSocket-Accept
의 값으로 반환합니다. 이 값을 통해 브라우저는 웹 소켓 지원 여부를 확인할 수 있습니다.
실제 구현에서의 선택지는 2가지입니다. Web Socket API는 표준 기술이며 빠르게 동작하고 적은 데이터를 이용한다는 장점이 있습니다. 하지만 이벤트가
close, error, message, open
밖에 없고, 메서드도close, send
밖에 없습니다. 또한 HTML5를 지원하는 브라우저 위에서만 동작한다는 단점도 존재합니다.
요즘은 Socket.io로 많이 구현하는 것 같습니다.
Socket.io는 Fallback을 지원하여 HTML5를 지원하지 않는 브라우저와도 호환이 가능합니다.
일부 클라이언트에게만 데이터를 전송하는브로드 캐스팅
이 가능합니다.네임 스페이스
를 통해 각각의 네임 스페이스 별로 별도의 이벤트와 데이터를 처리할 수 있고,룸
을 통해 사용자를 그룹화할 수도 있습니다. 또한 클라이언트의 비정상적인 연결 종료가 발생하면 자동으로 재연결을 한다는 장점도 존재합니다.
사용자의 연결이 비정상적으로 끊겼을 때 어떻게 대처할 수 있을까요?
새로운 소켓으로 연결을 하게 된다면 기존의 대화 내용이 사라지게 되니 개선이 필요하다고 가정해봅시다!