본 포스팅은 패스트캠퍼스 환급 챌린지 참여를 위해 작성하였습니다.




패스트캠퍼스의 '9개 도메인 프로젝트로 끝내는 백엔드 웹 개발 (Java/Spring) 초격차 패키지 Online' 강의 수강 42일차!
오늘은 Websocket을 활용한 실시간 메시징 도메인 서버 개발 강의의 웹소켓 이론에 대한 학습을 진행하였다.
(새롭게 시작할 토이 프로젝트에서 웹소켓을 사용하게 될 것 같아서 갑작스럽게 수강하는 강의를 바꾸게 되었다.
기존에 수강 중이던 redis 강의는 추후에 꼭 완강하도록 해야겠다,,😅)
웹소켓
: TCP 기반의 연결을 통해 실시간 양방향 통신을 가능하게 해주는 통신 프로토콜
하나의 커넥션을 이용하여 실시간으로 효율적인 양방향 통신이 가능하다는 장점이 있다. (전이중 통신)
하지만 비교적 최신 기술이기 때문에 브라우저의 호환성이 떨어지고, stateful한 특징에 맞춰 연결의 상태에 따른 여러가지 상황들을 구현시 신경써야 하는 단점이 있다.
웹소켓은 실시간성이 중요한 채팅, 인터넷 게임, 주식거래 사이트, 협업 툴 등의 서비스에 주로 사용된다.
웹소켓과 http의 비교
- http는 서버로부터 데이터를 받기 위해서 반드시 클라이언트의 요청이 있어야 한다.
한 번의 요청과 응답을 주고 받기 위해서는 3-way handshake 과정을 거쳐야 하기 때문에, 이로 인한 오버헤드가 발생할 수 있다.
- 서버와 연결을 맺기 위한 최초의 handshake 과정 이후에는 클라이언트와 서버가 각자 원하는 시점에 원하는 데이터를 보낼 수 있다. 그렇기에, handshake로 인한 불필요한 오버헤드가 발생하지 않는다.
웹소켓 이전의 실시간 통신 방식
- Polling
: 서버로부터 원하는 데이터를 얻어오기 위해 일정한 간격으로 서버에 계속 요청을 보내는 방법
서버에 변경사항이 없는 경우에도 계속해서 요청을 보내는 상황이 발생할 수 있기 때문에 불필요한 트래픽 낭비가 많이 생긴다.
- Long Polling
: 한번의 요청을 보내고 서버에서 보내줄 데이터가 없다면, 그 데이터를 보낼 수 있는 상황이 될 때까지 연결을 끊지 않고 유지하는 방식
해당 요청에 대해 응답을 받으면, 클라이언트에서는 해당 데이터를 처리한 후에 바로 다시 서버로 요청을 보내서 다음 데이터를 대기한다.
폴링 방식보다는 불필요한 트래픽이 줄어들지만, 많은 요청을 보내야 하는 문제는 해결되지 않는다.
- 스트리밍
: 클라이언트에서 서버로 요청을 보내고 나면, 이에 대한 연결을 끊지 않은 상태로 서버에서 데이터를 보낼 수 있을 때마다 몇 번이고 응답을 내려주는 방식
빈번한 요청이라는 문제는 해결할 수 있지만, 클라이언트에서 서버로 데이터를 전송할 수 없다는 문제가 있다.
웹소켓은 하나의 연결을 이용해서 양방향 통신이 가능하기에 위의 문제들을 해결할 수 있다.
웹소켓 핸드쉐이크
: 최초의 요청은 http 프로토콜을 이용하여 이루어진다. get 메서드를 이용해 웹소켓 프로토콜로의 업그레이드 요청을 보냄.
서버에서는 이에 대한 응답으로 200(일반적인 성공에 대한 응답)이 아닌, 100을 내려준다.
위 과정 이후부터는 웹소켓 프로토콜을 이용하여 서버와 연결을 맺고 데이터를 주고 받을 수 있게 된다.
웹소켓 프로토콜에서 사용하는 가장 작은 데이터 단위인 'Frame' 형식을 사용한다.
웹소켓 프로토콜상의 데이터 전송은 일련의 프레임을 사용한다.
프레임은 비트 단위로 세부적인 구조를 가지고 있으며, 크기 헤더와 페이로드로 구분된다.
| 0번 비트 | FIN | 메시지의 마지막 프레임 여부 (1이면 마지막) |
| 1~3번 비트 | RSV1~RSV3 | 웹소켓 확장용 필드. 특별한 확장 없으면 기본값은 0 |
| 4~7번 비트 | Opcode | 전송 데이터의 종류 (예: 텍스트, 바이너리 등) |
| 8번 비트 | Mask | 마스킹 여부. 클라이언트 → 서버 전송 시 항상 1 |
| 9~15번 비트 | Payload Length | 페이로드 데이터 길이 표현 |
- 0 ~ 125: 최초의 7비트를 이용해 직접 길이 표현
- 126: 최초의 7비트를 126으로 고정, 그 이후에 2 바이트를 사용하여 16비트 unsigned int로 길이 표현
- 127: 최초의 7비트를 127으로 고정, 그 이후에 8바이트를 사용하여 64비트 unsigned int로 길이 표현
이후, mask 비트가 1일 경우에는 길이 필드 뒤에 4바이트 마스킹 키가 추가되고, 그 뒤에 실제 페이로드 데이터가 전송된다.
웹소켓 프로토콜은 어플리케이션 레벨의 프로토콜이 아니기 때문에 주고받는 메세지 성격에 대한 충분한 정보가 없기 때문에 프레임워크나 컨테이너가 메세지를 어떻게 처리해야 할지 알 수가 없다. 그렇기 때문에 웹소켓 프로토콜을 위해 작동하는 서브 프로토콜 중 하나인 stomp를 사용한다.
stomp는 클라이언트와 서버가 전송할 메세지의 유형, 형식, 내용 등을 정의한다.
전에 웹소켓을 이용한 프로젝트를 진행하려다가 사전 지식의 벽에 가로막혀 도전하지 못했던 기억이 난다.
아직 정확히 이해가 되지 않는 부분도 있지만, 네트워크 공부를 병행하면서 진행하면 될 것 같다!
http 이외의 프로토콜을 사용하는 것은 처음이라 기대된다.