ㅈ현 2022. 8. 24. 10:00

웹소캣은 기존 웹의 단방향 프로토콜인 http의 문제를 해결하기 위해 나오게 되었다.

 

http요청(Request)응답(Response) 구조를 가진 단방향(Simplex) 동기(Synchronous) 프로토콜이다.

 

또한 상태를 가지고 있지 않아(Stateless), 매 요청이 독립적으로 진행된다. (이 부분은 대게 쿠키, 세션등으로 서버에서 처리)

 

http는 서버에 특정 데이터를 요청하기 위한 목적으로 지금까지 잘 사용되어 왔다.

 

하지만 이러한 특징 때문에 http에게 실시간성을 기대하기는 어려웠다.

 

http는 실시간성을 개선시키기 위해 풀링, 롱풀링등 다양한 방법들을 사용해 왔지만 프로토콜의 근본적인 문제 때문에 실시간성은 해결되기 힘든 문제였다.

 

풀링 : 서버에 주기적으로 요청을 보내 데이터가 있는지 확인
롱풀링 : 서버에 요청을 보낸 후, 서버는 데이터가 있으면 그때 response를 해줌 (데이터가 많아지면 풀링이랑 동일해짐)

 

때문에 이러한 http의 단점을 극복하고자 전이중 소캣 통신인 웹소캣이 나오게 되었다.

 

웹소캣

https://en.wikipedia.org/wiki/WebSocket

웹소캣은 TCP/IP 모델 5계층 프로토콜로 TCP위에서 동작하게 된다.

 

웹소캣은 http, https와 동일한 80, 443 포트상에서 동작하도록 설계되었으며 http와 호환된다.

https://ko.wikipedia.org/wiki/웹소켓

 

웹소켓 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 웹소켓(WebSocket)은 하나의 TCP 접속에 전이중 통신 채널을 제공하는 컴퓨터 통신 프로토콜이다. 웹소켓 프로토콜은 2011년 IETF에 의해 RFC 6455로 표준화되었으며 웹

ko.wikipedia.org

 

 

이러한 웹소캣은 TCP와 유사하게 handshake 과정을 거치게 된다.

이 과정은 http를 이용하여 진행되게 되며, handshake 과정을 거친 후에는 두 호스트간 통신 채널이 수립된다.

 

웹소캣은 "ws", "wss" 로 프로토콜을 표현한다

ex) ws://localhost:8888

 

 

Sample

 

server.py

import tornado.websocket
import tornado.web
import tornado.ioloop

class SendWebSocket(tornado.websocket.WebSocketHandler):
    def open(self):
        print("Session Open")

    def on_close(self):
        print("Session Closed")

    def check_origin(self, origin):
        return True

    def on_message(self, message):
        print(message)
        self.write_message(message)


app = tornado.web.Application([(r"/ws", SendWebSocket)])

if __name__ == "__main__":
    app.listen(8888)
    tornado.ioloop.IOLoop.current().start()

 

App.tsx

import {useEffect} from "react";
import "./App.css";

function App() {
    useEffect(() => {
        var ws = new WebSocket("ws://127.0.0.1:8888/ws");

        ws.onopen = (e) => {
            console.log("open!")
            console.log(e)
            ws.send("hello!")
        }

        ws.onmessage = function (evt) {
            console.log(evt.data)
        };
    }, []);

    return (
        <div className="App">
            <div id="terminal"></div>
        </div>
    );
}

export default App;