얼마전 실시간 통신을 구현하는 방법에 대해 간단하게 소개한적이 있는데요.
그 내용들을 바탕으로 아주 간단하게 샘플을 작성해보았습니다.
Polling
클라이언트 페이지에서 2초마다 한번씩 API를 호출합니다.
서버에서는 최초 요청시 healthCheck 함수를 실행합니다.
healCheck 함수는 10초 뒤에 메시지를 설정합니다.
매 2초마다 요청을 하다 10초 뒤에 요청에서 설정된 메시지를 리턴합니다.
클라에서는 메시지가 있는 응답이 오면 요청을 종료합니다.
서버에서 처리가 완료되었으나 클라의 요청이 아직 오지 않은 상황이면, 이미지의 빨간 부분처럼 데이터의 변경을 클라가 알아차리기까지의 딜레이가 발생 할수 있습니다.
샘플을 위해 요청을 종료처리 했지만, 서비스에 따라서 지속적으로 요청을 날려서 데이터를 받아오게 처리하면 됩니다.
샘플에서는 단순히 서버가 10초뒤에 메시지만 설정하는 형태로 구현이 되었지만.
실제로는 DB에 갔다오거나, 메시지큐를 확인하는 등의 처리를 하면 되지 않을까 합니다.
- Server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22let oneTimeFlag = false;
let message = "";
// API 요청이 들어오면 응답을 보내주고, 처음 요청시 healthCheack 함수를 실행합니다.
app.get("/xhr_polling", function (req, res) {
res.json({ msg: message, status: 200 });
healthCheck();
});
function healthCheck() {
// API가 최초 호출시 해당 함수가 1번만 실행되게 한다.
if (oneTimeFlag) {
return;
}
oneTimeFlag = true;
// 10초 뒤에 서버에 변경사항이 생긴다.
setTimeout(function () {
message = "Server update!!!!";
}, 10000);
} - Client
1
2
3
4
5
6
7
8
9
10
11
12
13
14let tryCnt = 0;
var polling = setInterval(function () {
$.ajax({
url: "/xhr_polling",
success: function (data) {
if (data.msg.length != 0) {
$("#server_status").text("UPDATE");
// 샘플에서는 서버에 변경된 데이터가 있으면 요청을 중단한다.
clearInterval(polling);
}
$("#log").append("<p>" + tryCnt++ + " : " + data.msg + "</p>");
}
});
}, 2000); // 2초에 한번씩 요청한다.
응답에 메시지가 있기전 까지는 빈 메시지를 출력하고, 2초 간격으로 호출합니다.
메시지가 있을때 메시지를 출력하고 호출을 중단합니다.
Long Polling
클라이언트에서 요청이 있을때 바로 응답을 하지 않고 데이터 변경이 있을때까지 대기하다 응답합니다.
샘플에서는 5초 후에 응답을 하게 구현을 했는데 이렇게 시간을 걸어서 동작하는 방식은 좀 안맞는거 같지만 우선 간단하게 구현해 보고자 해서 만들었습니다.
롱폴링을 이용한 채팅을 구현할땐 응답 대기열에 추가하고, 신규 메시지가 발생하면 그때 응답을 하는 형태로 구현하면 될거 같습니다.
- Server
1
2
3
4
5
6app.get("/xhr_long_polling", function (req, res) {
setTimeout(function () {
var message = loremIpsum();
res.json({ msg: message, status: 200 });
}, 5000);
}); - Client
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18let tryCnt = 0;
(function longPolling() {
$.ajax({
url: "/xhr_long_polling",
beforeSend: function (xhr, opts) {
// 샘플에서는 5번 까지만 요청하고 종료한다.
if (tryCnt > 4) {
xhr.abort();
}
},
success: function (data) {
$("#log").append("<p>" + tryCnt++ + " : " + data.msg + "</p>");
},
// 응답이 오거나 에러가 발생하면 complete 이벤트가 발생. 다시 longPolling 요청을 한다
complete: longPolling
});
})();
요청후 5초 동안 대기후 응답을 받고, 응답을 받자마자 다시 대기하는 모습을 볼 수 있었습니다.
샘플에서 사용된 코드는 여기서 확인 하실 수 있습니다.