네트워크

HTTP친구 웹소켓 (어떻게 생겨먹은 걸까?)

klom 2025. 10. 29. 14:13

WEB에는 대 프로토콜 HTTP가 있다. HTTP에 대해 간략히 복습하자면 HTTP는 비연결 지향 프로토콜이다. 클라이언트의 요청(Request)이 서버로 전송되고 응답(Response)이 완료되면 연결이 즉시 종료된다. 이러한 특성 때문에 요청 간의 상태가 유지되지 않으며, 한 번 전송된 메시지는 서버나 클라이언트 어느 쪽에서도 자동으로 저장되지 않는다. 하지만 모든 메시지가 즉시 연결이 종료되면 안될 수 있다. 예를 들어, 클라이언트가 보낸 메시지를 지속적으로 조회하거나,서버가 실시간으로 상태 변화를 전달해야 하는 상황이라면
HTTP의 비연결·비상태 특성만으로는 한계가 발생한다. 이러한 문제를 해결하기 위해 다양한 방식이 등장했다.
Long Polling, Server-Sent Events(SSE), 그리고 WebSocket이 대표적이다.그중에서도 WebSocket은 HTTP 위에서 핸드셰이크를 수행한 뒤 하나의 TCP 연결을 양방향 통신 채널로 전환하여 실시간 상호작용을 가능하게 만든 프로토콜이다.이번 장에서는 WebSocket이 왜 등장했는지, 그리고 HTTP와 어떤 점에서 근본적으로 다른지를 중심으로 살펴보자. 

Websocket의 탄생 배경

기술이나 프로토콜을 학습할때 왜 탄생했는지가 굉장히 중요합니다. 왜냐하면, 풀고 싶은 어떠한 것이 있다고 생각한다. 그런게 없다면 기술은 존재 의미가 없다고 생각합니다.(이 줄에서는 프로토콜도 기술이라 퉁 쳤습니다. 프로토콜 == 기술이라는 뜻은 아닙니다.)
그렇다면 어떤 이유때문에 websocket이 탄생하였을까? 바로 실시간 성 때문입니다. websocket이 만들어지기 전에도 실시간성이 아애 없었던은 아닙니다. 다만 그게 성능이 그리좋지 않았죠. 그러니까.. 실시간성이 다소 떨어졌다고 할 수 있습니다.
그 전에는 다음과 같은 방법으로 실시간성을 해결했다고 해요.
첫 번째, polling 방법입니다. 데이터는 서버에 있습니다. 그렇다면 클라이언트는 특정 데이터가 필요하다면, 데이터를 땡겨와서 계속해서 데이터를 세팅을 해줘야 합니다. 이렇게 되면 실시간 성은 보장 받을 수 있지만, 시스템 부하는 문제가 될수 있습니다.
왜냐하면, pollling이라는게 서버에 계속 요청해서 데이터를 땡겨오는 방식이기 때문입니다.

그래서 이것을 해결하고자 polling방식을 짧게 주는 방법, 길게 주는 방법, chunk단위로 쪼개서 사용하는 방법등 다양한 방법들이 나왔지만 이들 역시 근본적으로는 HTTP의 단방향 구조를 벗어나지 못했습니다. 즉, 서버가 먼저 데이터를 보낼 수 없고, 연결 유지 비용도 여전히 높았던 거죠.

이러한 문제점을 해결한것이 websocket입니다. websocket도 HTTP 위에서 시작하지만, 핸드셰이크 이후 TCP로 전환되어
클라이언트와 서버가 동등하게, 실시간으로 데이터를 주고받을 수 있는 구조를 만들었죠.

websocket의 구조는?

websocket도 http와 마찬가지로 tcp위에서 동작합니다. 하지만 이 둘은 다른 프로토콜에서 시작이 되었다고 생각이 들정도로 매우 다릅니다. 그 이유는 위 지문에서 언급한, 비 연결성에 있습니다. http는 단 반향 프로토콜입니다. 그래서 실시간성이 약하죠. 그래서 다양한 방법들이 모색이 되었지만 문제가 있었습니다. 그래서 나온것이 websocket으로 위에서 설명드렸습니다. websocket은 http와 달리 양 방향 프로토콜입니다. 그렇다면 http처럼 websocket도 직접 구현할 수 있지 않을까요? 모든 내용은 구현하기는 어렵지만 간략하게 구현은 가능하다고 합니다. 아무튼 http와 마찬가지로 이렇게 구현된 구현체를 websocket서버라고 부릅니다. 우리는 여기에 정의된 websocket을 사용하면 됩니다. 

이것을 알기전에 Websocket은 웹에서 동작하는 사실은 다들 알고 계실겁니다. 네 맞습니다. websocket은 http위에서 동작을 합니다.
근데 이상하죠. http는 무상태를 지향하는 프로토콜이고 websocket은 실시간성을 보장하는 프로토콜이니까요.. 어떻게 무상태를 지향하는 프로토콜 위에서 실시간성을 보장할 수 있을까요?

이것을 가능하게 해준것이 바로 upgrade라는 헤더 덕분이죠.
http/1.1에 탄생된 프로토콜로 http에서 다른 프로토콜로 변경을 시킬 수 있는 기능을 가졌죠. 그래서 http -> TLS/1.0, http -> h2c (http2 비암호화 모드) 등다양한 곳에서 이것이 활용이 되었습니다. 
즉, Upgrade는 HTTP를 네트워크 프로토콜 간 전환의 게이트웨이로 확장시킨 기술입니다.

좋습니다. 우리는 이제 upgrade 헤더를 통해 "http말고 다른 프로토콜로 바꿔줘"를 시전할 수 있습니다. 그러면 여기서 끝일까요?
그냥 upgrade헤더로 바꾸고 websocket을 사용하면 끝일까요? 일단 이 헤더의 역할은 끝났습니다. 이제 부터 웹은 웹 소켓으로 동작할 수 있게 되는거죠. 구현체 맞아요 구현체를 만들어야 해야합니다. 

101 Switching Protocols

upgrade의 역할은 문만 열어주면 되는겁니다. 그리고 나서 나머지는 웹소켓이 알아서 할겁니다.
본격적으로 websocket 구조에 알아봅시다.  그 다음은 무엇을 할까요?

대충 http에서 handshake가 진행이 되어지고 http해더가 사라집니다. 이제 연결은 여전히 같은 TCP 소켓 위에 유지되지만,
프로토콜은 WebSocket으로 전환되어 frame 단위 데이터가 오가게 됩니다.
즉,HTTP는 연결을 여는 데만 사용되고, 실제 데이터 교환은 WebSocket이 담당합니다.

그런데 의문이 듭니다. 왜 하필 frame일까요? http는 응용 그러니까 메시지 아니면 websocket도 응용 그러니까 메시지...가 되던가
tcp는 세그먼트로 동작하니 세그먼트 혹은 패킷으로 생각할 수 있는데 갑자기 frame?! frame같은 경우는 2계층입니다. 일단 진정하고 생각해봅시다. 일단 여기서 frame 아쉽게도 2계층 이더넷 frame과는 다르다고 합니다.
그러면 뭘까요?

WebSocket의 “frame”은 L7 메시지 경계를 위한 자체 컨테이너다. TCP의 바이트 스트림 위에 메시지 경계, 타입(Opcode), 제어(Ping/Pong/Close), 확장성을 싣기 위해 프레임 형식을 정의한 것이다. L2의 이더넷 프레임과는 전혀 다른 개념이다.

그러니까 여기서 frame은 응용 계층의 신호 단위인 메시지를 잘게 나눈말이라고 합니다.
그리고나서 frame을 전송을 시키면 됩니다. 이러한 구조는 HTTP의 스트리밍(chunked transfer) 방식에서 착안된 아이디어로,
데이터를 일정 단위로 구분하여 스트림 위에서 연속적으로 전송하는 개념을 양방향·실시간 통신 환경으로 확장한 결과라고 볼 수 있습니다.

webSocket은 종료 시점에 Close Frame이라는 “프로토콜 레벨 신호”만 추가될 뿐, 실제로 연결을 닫는 동작은 HTTP와 동일하게 TCP의 4-way handshake 로 이루어진다고 합니다.

마무리

현재 websocket을 통해 어느정도 실시간성을 보장할 수 있었습니다. 그렇다고 해서 이게 real time은 아닙니다.
실시간성을 보장하기 위해 http polling방식을 여러 시각으로 만들고 그걸 chunk단위로 발송을 시키는 식으로 실시간성을 발전시켜왔습니다. 그러다 websocket이라는것을 통해 조금더 real time에 가까워졌다고 생각합니다. 앞으로 어떤 기술이 실 시간으로 만들 수 있을까요? 기대가 되는군요. 그리고 이 글은 websocket의 모든 내용은 담고 있지는 않습니다. 구조에 대해 설명한 글입니다. 



출처
https://inpa.tistory.com/entry/WEB-%F0%9F%8C%90-%EC%9B%B9-%EC%86%8C%EC%BC%93-Socket-%EC%97%AD%EC%82%AC%EB%B6%80%ED%84%B0-%EC%A0%95%EB%A6%AC#%EC%9B%B9_%EC%86%8C%EC%BC%93_%EC%9D%B4%EB%9E%80?      
https://j1mmyson.github.io/posts/upgrade/