티스토리 뷰
📲 Socket
Socket이란?
서버와 클라이언트의 IP 주소, 포트 번호, 연결 상태 등을 기록해놓은 하나의 파일이다.
소켓은 프로세스 간 통신을 위한 인터페이스로, 네트워크 상에서 데이터를 주고받기 위한 소프트웨어 객체입니다. 각 클라이언트와 서버가 소켓을 통해 데이터를 송수신하며, 각 클라이언트는 고유한 소켓 객체를 생성하여 서버와 연결을 유지합니다.
소켓은 프로세스 간 통신에 사용되는 양쪽 endpoint이다.
📞 소켓을 설명하는 비유: 전화 통화
전화기
전화기(소켓)는 통신을 위한 도구입니다. 두 사람이 전화 통화를 하려면 서로 전화기를 가지고 있어야 하듯이, 소켓도 통신을 위해서 필요한 도구입니다. 각 전화기에는 고유의 번호(IP 주소 + 포트 번호)가 있어, 다른 사람과 통화하려면 이 번호를 알아야 합니다.
전화선
전화선(TCP/IP)은 통신이 이루어지는 경로입니다. 전화기와 전화기 사이를 연결해주는 물리적 매체가 전화선이라면, 소켓과 소켓을 연결하는 네트워크 통신 경로가 TCP/IP입니다.
전화번호
전화번호는 IP 주소 + 포트 번호를 의미합니다. 전화번호가 각 집과 연결되는 것처럼, 서버의 IP 주소와 포트 번호는 클라이언트가 서버와 연결하기 위한 고유 주소입니다. 예를 들어, 인터넷에 연결된 웹 서버는 보통 IP 주소 192.168.1.1과 포트 80을 통해 통신합니다.
통화 (연결)
통화는 서버와 클라이언트 간의 연결을 의미합니다. 클라이언트는 전화번호를 알고 서버에 전화를 걸듯이, 클라이언트가 서버의 IP 주소와 포트 번호를 알고 연결을 시도합니다. 서버는 연결 요청을 받으면, 전화(소켓)를 받듯이 소켓 객체를 생성하여 응답합니다.
통화 종료
전화가 끝나면 전화를 끊는 것처럼, 소켓 통신도 데이터를 다 주고 받은 후 연결을 종료합니다.
⚠️ TCP/IP Socket과 Web Socket은 다르다!!
🪟 웹소켓 통신이 필요한 이유
실시간 서비스, 예를 들어 MTS같은 서비스는 매초마다 서버로 부터 응답을 받아야한다. 이때 마다 HTTP통신으로 1초마다 서버에 요청을 보내서 받는 것은 매우 귀찮으므로 이에 해결책으로 대표적 2가지 방법이 있다.
HTTP 1.1 이하에서는 클라이언트의 요청없이는 서버에서 메시지를 못보낸다.
Pooling
클라이언트가 서버에 주기적으로 요청을 보내는 것.
- 요청 보내는 주기 만큼 지연생김.
- 불필요한 요청도 그냥 보내짐 주기에 따라서 보내지기에.
Long Pooling
미리 클라이언트가 요청을 보내놓고 요청을 가지고 있는 서버 단에서 업데이트가 생기면 다시 요청을 반환해주는 방식이다. Pooling의 단점을 개선했다.
- 하지만 서버단의 부담이 커짐
- 여러 클라이언트와 연결을 유지해야되기에 문제가 생긴다.
- HTTP에서 요청과 응답에 ㅗ함되는 헤더 정보의 양도 매번 부담
🗽Web Socket
대표적으로 많이 사용하는 방식이다. HTTP 1.1 이하에서는 단방향 통신만 가능하지만, WebSocket에서는 양방향 통신이 가능하다
HTTP보다 헤더가 작고 오버헤드가 적기떄문에 효율적인 통신이 가능하다. 이 통신은 한쪽이 다른쪽에게 통신을 종료하자고 할 때까지 지속됩니다.
비정상적인 종료를 감지하는 법
- 지정된 시간동안 메시지가 없을시 확인 패킷을 보낸다.
- ping pong 프레임을 주기로 주고 받아서 연결 확인
이처럼 웹소켓은 하나의 연결을 끝까지 유지하고 그 과정에서 작은 자원을 소모해서 Long Pooling만큼 서버에 부하를 주지도 않는다.
🤝 Web Socket 핸드쉐이크
클라이언트 -> 서버
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
서버 -> 클라이언트
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
👉 핸드셰이크가 성공하면 WebSocket 연결이 유지되며, 이후부터는 WebSocket 프레임을 사용하여 양방향 실시간 통신 가능!
101 Switching
🆚 TCP/UDP socket VS Web Socket
둘의 계층이 다릅니다. OSI 7계층에서 TCP/UDP는 4계층에 속하고 Web Socket은 7계층인 애플리케이션 계층에 속합니다.
websocket은 TCP 소캣을 기반으로 작동한다. 그러기에 데이터의 순서와 신뢰성이 보장된다는 것이다.
⚠️ Web Socket의 한계
- 로드 밸런서가 있는 서버의 경우 조심하자
- 메시지크기의 제약
- 대용량의 데이터는 분할해서 전달
- Web Socket의 기본 프로토콜인 WS는 통신이 암호화되어 있지않습니다.
- 그렇기에 SSL/TLS 인증서를 발급 받은뒤 이를 사용하여 WSS를 설정해야 된다.
- 또한 클라이언트가 결국 많아지면 연결해야되는 TCP 연결이 많아져서 서버에 부담이 가고, 네트워크 대역폭,CPU의 사용량이 높아진다.
⚠️로드 밸런싱 문제
HTTP 요청은 짧은 요청-응답 방식이므로, 로드 밸런서는 매 요청마다 적절한 서버로 트래픽을 분배할 수 있음.
하지만 WebSocket은 연결을 계속 유지하는 특성 때문에, 로드 밸런서가 연결을 임의로 다른 서버로 옮길 수 없음.
그래서 메시지 브로커를 사용해서 해결해야함.
📕 Web Socket의 대안 : Server-sent Events (SSE)
가볍게 보자면 클라이언트가 서버에 요청을 하는 구조가 아니라 서버가 매초마다 응답을 해주는 단방향 통신이다.
예를 들어서 실시간으로 소식이 올라오는 SNS페이지나, 주식 거래 서비스는 서버에서 응답을 지속적으로 보내주면 된다.
클라이언트가 SSE로 통신하자고 요청을 보내면 알겠다고 서버가 수신한다.
이후 서버가 메세지를 보내고 클라이언트는 메시지를 받아서 작업을 수행한다. 이 연결은 유지되며 만약에 연결이 끊어지면 클라이언트가 자동으로 재연결을 요청한다.
HTTP만을 통해서 이뤄지고 복잡한 코딩이나 설정이 필요없다.
그리고 서버에서만 메세지를 보내기 때문에 로드밸런싱 과정에서도 문제가 없다.
🤝 SSE handShake
클라이언트 -> 서버
GET /stocks/stream HTTP/1.1
Host: example.com
Accept: text/event-stream
Connection: keep-alive
서버 -> 클라이언트
HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
data: {"price": 105.3, "symbol": "AAPL"}
data: {"price": 106.1, "symbol": "AAPL"}
data: {"price": 107.8, "symbol": "AAPL"}
핸드 쉐이킹 과정후 하나의 TCP연결을 계속 유지하기에 서버 부담이 적다. 또한 서버의 첫번째 이후 HTTP 헤더가 필요없다. 클라이언트 측에서 javaScript의 Event Source 객체를 사용해서 반응하면 된다.
연결이 비정상적으로 끊어졌을경우 EventSource 객체에서 재연결 응답 요청을 보낸다. 이때 Last-Event-ID 필드를 통해서 언제 마지막으로 끊겼는지 보내줌.
- HTTP기반이기에 방화벽에도 친화적. 원래 열려있는 80번이나 443번 포트를 그대로 사용하기에 WebSocket처럼 따로 포트 설정 안해줘도 된다.
- Chrome에서는 최대 6개의 SSE 연결만 유지 가능.HTTP2로는 100개가 기본
🤔 초당 1000개 이상의 주가 업데이트에서 WebSocket이 더 적합한 이유
즉 이 부분은 트래픽이 많을 경우
사실 이 부분은 여러가지 의견이 있을 것 같기도하다. 개인적인 생각으론 두 가지 측면에서 WebSocket이 더 적합하다고 생각합니다. (틀릴수도 있어용)
1. 데이터 전송
SSE는 단순한 문자열(텍스트)만 전송 가능
WebSocket은 바이너리 데이터(이미지, 동영상, JSON 등)를 효율적으로 전송 가능
실제로 SSE는 한번 연결후 HTTP 헤더없이 메시지만으로도 통신이 가능하여 오버헤드가 상대적으로 WebSocket보다는 적습니다. 하지만
- 이미지, 동영상 같은 바이너리 데이터를 전송할 수 없음.
- JSON도 문자열로 변환해야 하므로 오버헤드가 발생할 수 있음.
- 데이터 크기가 커지면 문자열 인코딩으로 인해 비효율적일 수 있음.
전송 방식 | 텍스트 (JSON, Base64) | 바이너리 (Raw Data) |
---|---|---|
데이터 크기 | 인코딩 오버헤드로 증가 (최대 33%) | 원본 크기 유지 |
처리 속도 | 인코딩/디코딩 필요 (CPU 부담) | 바로 사용 가능 (빠름) |
대용량 파일 (이미지, 영상) | Base64 변환 시 33% 크기 증가 | 그대로 전송 가능 |
숫자 데이터 (정수, 실수) | 텍스트 변환 시 크기 증가 | 4~8바이트로 압축 가능 |
이러한 이유로 WebSocket이 실무 상황에선 유리하다고 생각합니다
물론 케이스에 따라서 단순한 텍스트만 보내주는 경우에는 SSE가 더 적합할 것입니다.
2. HTTP 부하
SSE는 클라이언트당 1개의 TCP 연결을 유지하지만, 클라이언트가 요청을 보낼 때마다 새로운 HTTP 요청을 만들어야 함.
WebSocket은 한 개의 TCP 연결 내에서 양방향 통신이 가능하므로, 새로운 HTTP 요청을 만들 필요가 없음.
즉 WebSokcet은 클라이언트의 요청 처리를 새로운 HTTP 연결 생성없이 처리가 가능하기 때문입니다.
'개발적 감자 > [WEB]' 카테고리의 다른 글
HTTP 0.9 1.0 1.1 2.0 정리 (0) | 2025.04.03 |
---|
- Total
- Today
- Yesterday
- sw expert academy
- 괄호 회전하기
- 오블완
- 토마토
- 메뉴 리뉴얼
- Comparable
- 고정소수점
- Call-by-Value
- 다단계 칫솔 판매
- 순열
- 백준
- 티스토리챌린지
- 구현
- 운영 체제
- 자바
- java
- Comparator
- 도둑질
- 부동소수점
- 베스트 앨범
- swea
- 컴퓨터 구조
- 요세푸스
- 표 편집
- 기능 개발
- 코테
- 프로그래머스
- 조합
- 데이터
- 컴퓨터구조
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |