웹 브라우저에서 서버와 클라이언트가 통신할 수 있는 다양한 방법이 존재한다. 그 방법 중 Polling, Long Polling, SSE, Web Socket에 대해 살펴보자!
사실 기존 블로그에서 정리를 했었는데, 다시 한 번 자세히 코드와 함께 정리해보려 한다.
Client가 평범한 http request를 서버로 계속 날려서 이벤트 내용을 전달받는 방식이다.
가장 쉬운 방법이지만, Client가 계속적으로 request를 날리기 때문에 Client가 많아지면 Server의 부담이 급증하게 된다. http request connection을 맺고 끊는 것 자체가 부담이 많은 방식이다. 또한 Client에서 실시간 정도의 빠른 응답을 기대하기도 어렵다.
HTTP Overhead
?
전송하는 데이터 양에 비해 헤더 정보의 양 증가로 인해 데이터량이나 처리 시간이 증가하는 현상을 말한다.
Server 측에서 접속을 열어두는 시간을 길게하는 방식이다.
응답을 실시간으로 받아야 하는 경우와 적은 수의 사용자가 동시에 사용하는 경우에 선택할 수 있다.
일반적인 TCP Connection과 비슷하며, Client와 Server간 연결된 연결 통로로 데이터를 보내는 방식이다. Server에서 Client로 이벤트를 전달할 때, 해당 요청을 끊지 않고 필요한 메세지만 보내기를 반복하는 형식이다.
Server와 Client 간 SSE 통신을 하기 위해서 처음에 Client에서 Server로 연결 요청을 보내야 한다. EventSource
는 SSE 연결 요청을 보내기 위해 Javascript가 제공하는 객체이며, SSE Client API는 EventSource 객체에 포함된다. EventSource는 text/event-stream
포맷으로 이벤트를 전송하는 HTTP 서버에 지속적으로 연결되고, 연결은 EventSource.close()
호출로 종료되기 전까지 지속된다.
EventSource.onopen
: 서버와 연결이 open 됐을 때 호출하는 이벤트 핸들러EventSource.onmessage
: 서버로부터 message를 수신했을 때 호출하는 이벤트 핸들러EventSource.onerror
: 에러가 발생하거나 EventSource 객체에서 error event가 감지되었을 때 호출하는 이벤트 핸들러기존 단방향 HTTP 프로토콜과 호환되어 양방향 통신을 제공하기 위해 개발된 프로토콜로, 한 번 연결이 수립되면 Client와 Server 모두 자유롭게 데이터를 보낼 수 있다.
HTTP를 이용해서 연결을 수립하며, 연결이 된 이후에도 연결을 할 때 사용했던 포트인 80과 443 포트를 사용한다. 추가로 방화벽을 열지 않아도 된다.
HTTP 규격인 CORS 적용이나 인증 등의 과정을 기존과 동일하게 가져갈 수 있으며, OSI 7 Layer의 4계층(network layer)의 TCP에 의존한다.
Handshake가 끝나면 HTTP 프로토콜을 websocket 프로토콜로 변환하여 통신한다.
Polling 작업을 위해
setInterval
을 사용하여 데이터를 요청할 수 있다.
const [rankList, setRankList] = useState("");
// API 데이터 호출 함수
const dataAPI = async () => {
const rankAPI = await instance.get(`/url/${id}`);
setRankList(rankAPI.data);
};
useEffect(() => {
let polling = setInterval(() => {
dataAPI();
}, 60000);
// 페이지에 벗어날 경우 polling X
return () => {
clearInterval(polling);
};
}, []);
const [ticket, setTicket] = useState({});
useEffect(() => {
const eventSource = new EventSource("http://localhost:3000/sse");
eventSource.onmessage = (event) => {
setTicket(JSON.parse(event.data));
};
return () => {
eventSource.close();
};
}, []);
return (
<div>
<p>{ticket.key}</p>
<p>{ticket.fields.summary}</p>
</div>
);
< 참조 : https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-Polling-Long-Polling-Server-Sent-Event-WebSocket-%EC%9A%94%EC%95%BD-%EC%A0%95%EB%A6%AC
https://warmth424.tistory.com/18
https://doozi0316.tistory.com/entry/WebSocket%EC%9D%B4%EB%9E%80-%EA%B0%9C%EB%85%90%EA%B3%BC-%EB%8F%99%EC%9E%91-%EA%B3%BC%EC%A0%95-socketio-Polling-Streaming
https://www.crocus.co.kr/m/1826 >