소켓통신
쌍방이며 연결 상태를 유지하는 stateful 통신 방식
장기연결 소켓통신 종류
① WebSocket (네가 아는 것)
- HTTP → Upgrade → TCP 위에서 연결 유지
- 브라우저/서버 친화적
- 채팅, 알림, 대시보드
② TCP 소켓 (Persistent TCP)
- HTTP 없음
- 서버 ↔ 클라이언트가 직접 TCP 연결 유지
- 메시지 포맷은 직접 정의
- POS / 단말 / IoT 쪽에서 제일 흔함
- 특징:
- 연결 유지
- keep-alive / heartbeat 직접 구현
- framing(메시지 경계) 직접 관리
③ gRPC (HTTP/2 기반 장기 연결)
- 내부 서비스 통신에서 많이 씀
- 스트리밍 RPC 지원
- 연결은 계속 유지됨
④ MQTT (브로커 기반)
- IoT 표준
- publish / subscribe
- 항상 연결 유지
⑤ SSE (Server-Sent Events)
- HTTP지만 연결 유지
- 서버 → 클라이언트 단방향
HTTP/Socket통신 어떻게 결정되는가??
- TCP는 메시지를 모른다. OS에게 소켓은 그냥 바이트 스트림을 받아드리는 창구이다.
- Socket이 지속적으로 열려있을지 바로, 열고 닫을지는 Application에서 OS 함수호출을 통해서 결정한다.
handleRequest()
sendResponse()
socket.close()
onConnect()
while (connected) {
readMessage()
}
HTTP와 무엇이 다른가?
메세지 경계처리 : HTTP Protocol VS 커스텀정의
HTTP는 메시지 형식이 표준으로 완전히 정의되어있어 메세지 경계 분리를 서버 프레임워크(서블릿 컨테이너 Tomcat)가 책임진다
따라서, 애플리케이션이 바이트스트림과 HTTP의 세부를 몰라도 된다
- 시작 라인
- 헤더
- 빈 줄
- 바디
- Content-Length / Transfer-Encoding
소켓 통신은 메세지 형식이 정해져있지않아서 개발자가 설계한 애플리케이션이 경계를 책임진다. 애플리케이션이 바이트 스트림을 세부적으로 다루어야한다.
- 내가 설계
- 내가 파싱
- 내가 예외 처리
- 연결상태관리 : StateFul-Stateless가 다르다
서버 메모리 관점: 세션(Session) vs 커넥션(Connection)
- HTTP (Stateless 지향): 서버는 요청이 끝남과 동시에 해당 스레드와 메모리를 비웁니다.
- Socket (Stateful): 서버 메모리에 SocketChannel 객체와 해당 기기의 정보가 계속 살아있어야 합니다. 2만 개 매장에서 연결되어 있다면 서버 힙(Heap) 메모리에는 항시 2만 개의 객체가 상주합니다.
- 연장선: 메모리 누수(Leak)가 발생하면 서버가 즉시 뻗습니다. 그래서 Netty 같은 프레임워크는 참조 카운팅(ReferenceCounted)을 통해 메모리를 극도로 관리합니다.
장애/끊김 감지 방식: "수동적" vs "능동적"
- HTTP: 클라이언트가 요청을 안 보내면 서버는 클라이언트가 살았는지 죽었는지 알 방법이 없고, 알 필요도 없습니다.
- Socket: 연결이 끊긴 상태를 감지하지못하면, 그 장비를 위한 SocketChannel 객체와 각종 버퍼 그리고 OS에는 FD라는 소켓이 낭비되어 메모리가 비효율적으로 사용됨.
메시지 처리 방식: "완성형" vs "진행형"
- HTTP (Tomcat): HttpServletRequest라는 객체가 내 손에 들어왔을 때는 이미 모든 바이트 조립이 끝난 상태입니다.
- Socket (Netty): 개발자는 ByteBuf를 보면서 "여기까지가 주문 번호고, 여기서부터는 메뉴 이름이구나"를 직접 판단.
스케일링(Scaling) 방식: "L4/L7 로드밸런싱"의 차이
- HTTP: 아무 서버에나 요청을 던져도 됩니다(Stateless). 로드밸런서가 그냥 남는 서버에 배분하면 끝입니다.
- Socket: 한 번 맺어진 연결은 특정 서버에 귀속됩니다. 그러므로 L4 스위치(장비)나 F5, 혹은 클라우드의 NLB(Network Load Balancer)는 연결을 고유한 키값으로 저장하고 동일한 서버로 지속적을 보내줌.
- 연장선: 서버를 재시작하거나 늘릴(Scale-out) 때, 기존에 연결된 2만 개의 소켓을 어떻게 안전하게 끊고 새 서버로 유도할 것인지(Graceful Shutdown), 그리고 특정 서버에만 연결이 쏠리지 않게 어떻게 배분할 것인지(Sticky Session/Connection)가 설계의 핵심입니다.
- 논리적 상태 (Session): 장비 식별자, 현재 진행 중인 주문 번호, 장바구니 정보 등을 redis같은 캐쉬에 담아서
- 연결 끊김: L4 로드밸런서가 연결을 끊거나, 서버 점검으로 소켓이 닫힙니다.
- 재접속: 클라이언트(키오스크)가 다시 접속합니다. 이번에는 L4가 서버 B로 연결해 줍니다.
- 인증 및 조회: 클라이언트가 "나 1004번 매장이야"라고 말하며 접속합니다.
- 세션 복구: 서버 B는 자신의 메모리가 아닌 Redis를 뒤집니다.
- 재개: 서버 B는 그 정보를 바탕으로 클라이언트에게 "500번 주문 이어서 하자"라고 응답합니다.
'개발기술 > 통신 인터페이스, 프로토콜' 카테고리의 다른 글
| Message Broker : Kafka (0) | 2025.11.27 |
|---|---|
| MessageBroker : RabbitMQ, (0) | 2025.09.22 |
| 응용계층 : HTTP와 그 외 (0) | 2025.08.22 |
| RabbitMQ : Java Client 통신구조 (1) | 2025.07.07 |
| 전송계층 : TCP와 UDP (0) | 2025.04.30 |