이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.
공부 › 네트워크 › HTTP
폴링·SSE·WebSocket
서버에서 생긴 일을 브라우저에 알리는 네 가지 방법
HTTP는 클라이언트가 물어야 서버가 답하는 구조라서, 서버에 새 알림이 생겨도 먼저 말을 걸 수 없습니다. 주기적으로 물어보거나(폴링), 대답을 미뤄 두거나(롱 폴링), 연결을 열어 두고 흘려보내거나(SSE), 아예 양방향 통로로 바꾸는(WebSocket) 방법이 있습니다.
문서·표준 대조 · HTML 표준, WebSocket 표준(RFC 6455), 스프링 문서
이 실습에 나오는 개념
- SSE(Server-Sent Events)와 폴링
- 폴링은 클라이언트가 일정 간격으로 서버에 새 데이터가 있는지 반복해 묻는 방식이다. SSE는 하나의 HTTP 연결을 열어 두고 서버가 클라이언트 쪽으로 이벤트를 계속 보내는 방식으로, 서버에서 클라이언트로의 한 방향 전송만 가능하다. 알림처럼 서버가 보내기만 하면 되는 경우 WebSocket보다 단순하다.
- WebSocket
- 클라이언트와 서버가 하나의 연결을 유지한 채 양쪽에서 자유롭게 메시지를 주고받을 수 있는 통신 규약이다. HTTP는 클라이언트가 요청해야 서버가 응답할 수 있지만, WebSocket은 서버가 먼저 데이터를 보낼 수 있어 채팅이나 실시간 알림에 쓰인다.
- HTTP와 무상태(Stateless)
- HTTP는 클라이언트가 요청을 보내면 서버가 응답하는 방식의 통신 규약이다. 무상태라는 것은 서버가 이전 요청의 내용을 기억하지 않아 각 요청이 그 자체로 처리에 필요한 정보를 모두 담고 있어야 한다는 뜻이다. 서버가 상태를 기억하지 않으므로 어느 서버가 요청을 받아도 되어 서버를 늘리기 쉽다. 로그인 상태처럼 이어져야 하는 정보는 쿠키, 세션, 토큰으로 유지한다.
이렇게 바꿔 보세요
- 처음 설정으로 — 5초 간격 폴링. 요청 6번 가운데 절반이 "새 소식 없음"으로 끝납니다.
- 폴링 간격을 1초로 — 지연은 줄지만 요청이 30번으로 늘어납니다.
- 롱 폴링 — 소식이 생기는 순간 응답합니다. 요청 수는 알림 수와 비슷합니다.
- SSE — 연결 하나로 서버가 생기는 대로 보냅니다.
- 양방향이 필요하면 — 채팅처럼 클라이언트도 자주 보낸다면 WebSocket이 맞습니다.
- SSE인데 클라이언트도 자주 보내면 — 보내는 쪽은 매번 별도의 HTTP 요청이 됩니다.
처음 설정으로 실행하면
- 브라우저가 5초마다 "새 알림 있나요?"라고 요청합니다. 서버는 그 시점까지 쌓인 알림을 주거나, 없으면 빈 응답을 줍니다.
- 5초: 요청을 보냈습니다. 그 사이 생긴 알림 1건을 받았습니다. 알림은 3.7초에 생겼지만 다음 요청 때까지 기다려야 했습니다.
- 10초: 요청을 보냈습니다. 새 알림이 없어 빈 응답을 받았습니다.
- 15초: 요청을 보냈습니다. 그 사이 생긴 알림 1건을 받았습니다. 알림은 13.7초에 생겼지만 다음 요청 때까지 기다려야 했습니다.
- 20초: 요청을 보냈습니다. 새 알림이 없어 빈 응답을 받았습니다.
- 25초: 요청을 보냈습니다. 그 사이 생긴 알림 1건을 받았습니다. 알림은 23.7초에 생겼지만 다음 요청 때까지 기다려야 했습니다.
- 30초: 요청을 보냈습니다. 새 알림이 없어 빈 응답을 받았습니다.
- 30초 동안 요청 6번 중 3번이 빈손으로 끝났습니다.
실행 결과
- 폴링은 구현이 가장 단순합니다. 하지만 간격이 길면 알림이 늦고, 짧으면 소득 없는 요청이 서버에 쌓입니다. 사용자가 많으면 그 요청만으로 부하가 됩니다.
코드
// 브라우저
setInterval(async () => {
const res = await fetch("/notifications?after=" + lastId);
show(await res.json()); // 없으면 빈 배열
}, 5000);
이 모형의 전제
30초 구간에 알림이 고르게 생긴다고 가정했습니다. 전달 지연에서 네트워크 왕복 시간은 무시했습니다. 클라이언트가 보내는 메시지는 30초에 10건으로 고정했습니다. 롱 폴링의 제한 시간은 30초로 두었습니다. 네 방식의 동작은 HTML 표준(EventSource), WebSocket 표준(RFC 6455), 스프링 문서의 설명을 따랐습니다.
앞 실습: CORS · 다음 실습: TLS 핸드셰이크