[Note_Info_3-3] 네트워크 요청 11장 - 웹소켓
1. 웹소켓?
웹소켓: RFC 6455 명세서에 정의된 프로토콜. 서버와 브라우저 간의 연결을 유지한채로 통신하는 양방향 프로토콜이다. 채팅, 온라인게임, hts등 에서 활용된다.
let socket = new WebSocket("ws://javascript.info");
로 간단하게 생성 가능하다.
- 4가지 주요 이벤트: open(커넥션 생성 완료), message(메시지 수신), error, close
** socket.onopen = () => {}; 과 같이 socket 객체 on~프로퍼티에 각 이벤트의 핸들러를 달 수 있다.
- 2가지 주요 메서드: socket.send(data), socket.close();
2. 웹소켓 핸드셰이크
- socket 객체를 생성하는 것만으로도 즉시 연결이 시작된다.
- Request header 까보기.
- Origin – 클라이언트 오리진(예시에선 https://javascript.info)을 나타냅니다. 서버는 Origin 헤더를 보고 어떤 웹사이트와 소켓통신을 할지 결정하기 때문에 Origin 헤더는 웹소켓 통신에 중요한 역할을 합니다. 참고로 웹소켓 객체는 기본적으로 크로스 오리진(cross-origin) 요청을 지원합니다. 웹소켓 통신만을 위한 전용 헤더나 제약도 없습니다. 오래된 서버는 웹소켓 통신을 지원하지 못하기 때문에 웹소켓 통신은 호환성 문제도 없습니다.
- Connection: Upgrade – 클라이언트 측에서 프로토콜을 바꾸고 싶다는 신호를 보냈다는 것을 나타냅니다.
- Upgrade: websocket – 클라이언트측에서 요청한 프로토콜은 'websocket’이라는걸 의미합니다.
- Sec-WebSocket-Key – 보안을 위해 브라우저에서 생성한 키를 나타냅니다.
- Sec-WebSocket-Version – 웹소켓 프로토콜 버전이 명시됩니다. 예시에서 버전은 13입니다.
**바닐라 자바스크립트로 헤더를 설정하는 건 기본적으로 막혀있기 때문에 XMLHttpRequest나 fetch로 위 예시와 유사한 헤더를 가진 HTTP 요청을 만드는 것은 불가능 하다. **
- Respose header 까보기
3. Extensions와 Subprotocols헤더
이 헤더는 브라우저에서 데이터 압축(deflate)을 지원한다는 것을 의미합니다. Sec-WebSocket-Extensions은 브라우저에 의해 자동 생성되는데, 그 값엔 데이터 전송과 관련된 무언가나 웹소켓 프로토콜 기능 확장과 관련된 무언가가 여러 개 나열된다.
Sec-WebSocket-Protocol: soap, wamp – 이렇게 헤더가 설정되면 평범한 데이터가 아닌 SOAP나 WAMP(The WebSocket Application Messaging Protocol) 프로토콜을 준수하는 데이터를 전송하겠다는 것을 의미합니다.
4. 데이터 전송
-frame: 웹소켓 데이터 조각의 기본 단위.
-4가지 종류의 frame: text, binary data, ping/pong(커넥션 시작할때 자동으로 보내는 것), connection close(커넥션 종료할때 자동으로 보내는것)
-socket.send(body)를 호출할 때, body엔 string이나 Blob, ArrayBuffer등의 이진 데이터만 들어갈 수 있다. Blob은 고차원(high-level)의 이진 객체인데, <a>나 <img> 등의 태그와 바로 통합할 수 있어서 기본값으로 자주 쓴다.
5. 메시지 전송 빈도 제한
- socket.send()를 하면 network에 보내기 전 buffer에 쌓았다가 실제 네트워크 전송이 이루어 져야 buffer가 빈다. socket.bufferedAmount의 숫자로 buffer에 데이터가 비었는지 체크할 수 있다.
setInterval(() => {
if (socket.bufferedAmount == 0) {
socket.send(moreData());
}
}, 100);
- 위와같이 주기적으로 버퍼가 비었는지 체크해서 버퍼가 비었을때만 새로운 소켓메시지를 보내게 설정할 수있다.
6. 연결 종료
- socket.close()를 하면, socket은 connection close(커넥션 종료할때 자동으로 보내는것)을 send한다.
- 1000, 1006, 1001, 1009, 1011 등의 에러코드가 있다. 그 중 1000은 일반적인 폐쇄 1006은 연결이 끊어짐을 나타낸다.
- socket.close([code], [reason]) : 첫번째 인자에 code를 number로 적고, 두번째 인자 이유를 string으로 적는다.
// 커넥션을 종료하는 쪽
socket.close(1000, "Work complete");
// 종료메시지를 받는 쪽
socket.onclose = event => {
// event.code === 1000
// event.reason === "Work complete"
// event.wasClean === true (clean close)
};
7. connection state
- socket.readyState를 보면 연결 상태를 체크할 수 있다. XMLhttpRequest의 readyState와 비슷하다.
- 0: CONNECTING 1: OPEN 2: CLOSING 3: CLOSED
8. chat example
- https://github.com/websockets/ws 에는 무료로 테스트해볼 수 있는 웹소켓 서버가 열려있다.
<!-- message form -->
<form name="publish">
<input type="text" name="message">
<input type="submit" value="Send">
</form>
<!-- div with messages -->
<div id="messages"></div>
//socket 생성
let socket = new WebSocket("wss://javascript.info/article/websocket/chat/ws");
// form submit시 message input의 값을 send함.
document.forms.publish.onsubmit = function() {
let outgoingMessage = this.message.value;
socket.send(outgoingMessage);
return false;
};
// 메시지 수신하면 messages div 하위에 메시지를 text로 가진 div를 생성해서 붙임.
socket.onmessage = function(event) {
let message = event.data;
let messageElem = document.createElement('div');
messageElem.textContent = message;
document.getElementById('messages').prepend(messageElem);
}
요약:
- 웹소켓은 서버와 브라우저의 지속적인 연결을 위한 거의 모든 브라우저에서 지원하는 모던 웹 api다.
- 웹소켓을 통해 string과 binary data를 주고 받을 수 있다.
- 웹소켓은 CORS 제한이 없다.
*주요 메서드 2가지*
- open, close
*주요 이벤트 4가지*
- open message error close
**웹 소켓은 그 자체로 재연결, 인증 등 고차원적인 기능을 지원하지 않는다. 그래서 여러 클라이언트 라이브러리들을 가져다가 사용하거나, 자체적으로 커스텀해서 쓴다.**
**web소켓 서버와 http 서버를 따로 실행하고 단일 데이터베이스를 공유하는 방식으로 많이들 쓴다. https 요청은 https://bomsbro.com. websoket에 대한 요청은 wss://ws.bomsbro.com과 같이 하위도메인으로 많이들 사용한다. **
+ 웹소켓도 ssl 인증을 해야한다. 비인증 프로토콜은 ws 인증 프로토콜은 wss이다. 기본적으로 http와 https가 사용하는 포트와 동일 포트인 80과 443을 사용한다.
+mqtt 프로토콜: Messagbe Queueing Telemetry Protocol. pub-sub구조의 메시지 송신 프로토콜 tcp/ip 위에서 동작하지만 굉장히 가볍고, 많은 통신 제약들을 해결해준다. messenger가 이 프로토콜을 사용한다. RabbitMQ, Mosquitto 등의 라이브러리들이 존재한다.
+websocket과 mqtt 프로토콜의 연관성: mqtt는 websocket 프로토콜 위에서 돌아간다. 웹소켓 위에서 mqtt brocker가 mqtt packet을 전달하는 것이다.
- Mosquitto 2.0.14
- MQTT.fx 1.7.1
+ 관련 키워드: netty, mq, kafka, RabbitMQ, stomps, ..?
궁금한점:
1. http hanshake와 web socket handshake의 유사성
2. 같은 포트를 쓴다는 사실과 handshake 프로세스의 연관성?
3. Sec-WebSocket-Accept와 Sec-WebSocket-Key의 밀접한 관계. 브라우저의 보안 알고리즘?