π λ€μ΄κ°λ©°
μ΄λ² ν¬μ€ν μ μΉ μμΌ(Web Scoket)μ λν ν¬μ€ν μ νλ €κ³ ν©λλ€.
μ΄ κΈμ μ½μΌμλ λΆλ€μ μλ§ μΉ μμΌμ΄ 무μμΈμ§ μ λλ μκ³ μμ κ²μ΄λΌκ³ μκ°ν©λλ€.
λ§μ΅λλ€. μ€μκ° ν΅μ μ΄ νμν λ μ κ·Ήμ μΌλ‘ μ¬μ©λλ κΈ°μ μ λλ€.
κ·ΈλΌ μ μ€μκ° ν΅μ μ ν λ μΉ μμΌμ μ¬μ©νλμ§, κΈ°μ‘΄μλ μ΄λ€ λ°©μμ μ¬μ©νκ³ , μ΄λ€ λ¬Έμ λ₯Ό ν΄κ²°ν΄ μ£Όλμ§, μ΄λ»κ² λμνλμ§ λ±λ± μμλ³΄κ² μ΅λλ€.
μΉ μμΌμ λ±μ₯ λ°°κ²½
μ΄κΈ°μ μΈν°λ· ν΅μ λ°©μμ μ£Όλ‘ HTTPλ₯Ό μ΄μ©ν ν΄λΌμ΄μΈνΈ(μμ²) - μλ²(μλ΅) λͺ¨λΈμ ν΅ν΄ μ§νλμμ΅λλ€.
μ¦, ν΄λΌμ΄μΈνΈκ° μλ²μ μμ²(Request)μ 보λ΄κ³ , μλ²κ° μ΄μ μλ΅(Response)νλ λ°μ΄μ€ ν΅μ λ°©μμ λ°λ¦ λλ€.
μ΄ λ°©μμ΄ νμ΄μ§λ₯Ό μμ²νλ λ±μ κ°λ¨ν μμ μλ ν¨κ³Όμ μ λλ€.
νμ§λ§, μ€μκ°μΌλ‘ λ°μ΄ν°λ₯Ό μ£Όκ³ λ°λ λ°μ νκ³μ μ΄ λ°μνκ² λ©λλ€.
ν΄λΌμ΄μΈνΈκ° μλ²μκ² μμ²νμ§ μλ μ΄μ μλ²λ ν΄λΌμ΄μΈνΈμκ² λ¨Όμ λ°μ΄ν°λ₯Ό λ³΄λΌ μ μμ΅λλ€.
μ΄ νΉμ§μΌλ‘ μ€μκ° λ°μ΄ν°λ₯Ό μ£Όκ³ λ°λ μν©μ ꡬννκΈ° μν΄μ,
ν΄λΌμ΄μΈνΈλ νμ μλ‘μ΄ λ°μ΄ν°κ° μλμ§ νμΈμ νκΈ° μν΄ μλ²μ μ§μμ μΌλ‘ μμ²μ λ³΄λΌ μλ°μ μμ΅λλ€.
μ΄λ κ² λλ©΄ νΈλν½μ λΆνμνκ² μ¦κ°μν€κ³ , μ΄λ‘ μΈν΄ μλ²μ λΉμ©μ΄ μ¦κ°λ λΏλλ¬ μμ²κ³Ό μλ΅μ¬μ΄μ μ§μ°μκ°μ΄ μκΈ° λλ¬Έμ μ€μκ° ν΅μ μ ν¨μ¨μ±μ μ νμν¬ μ μμ΅λλ€.
μΉ μμΌ μ΄μ μ ν΅μ λ°©μ
μ‘°κΈ λ μμΈν μμλ³΄κ² μ΅λλ€.
μΉ μμΌμ΄ λ±μ₯ νκΈ° μ μ£Όλ‘ μ¬μ©λλ HTTP νλ‘ν μ½μ κΈ°λ°μΌλ‘ ν μ€μκ° ν΅μ λ°©μμ μ΄λ€ κ²λ€μ΄ μμκΉμ?
ν΄λ§(Polling)
ν΄λΌμ΄μΈνΈκ° μ£ΌκΈ°μ μΌλ‘ μλ²μ μμ²μ 보λ΄λ λ°©μμ λλ€.
μ¦, μΌμ μκ°λ₯Ό μ ν΄ λκ³ μλ‘μ΄ λ°μ΄ν°κ° μλμ§ μμ²μ 보λ΄μ νμΈνκ² λ©λλ€.
μ΄λ, μλ‘μ΄ λ°μ΄ν°κ° μλλΌλ μλ²λ μλ΅μ 보λ λλ€.
κ·Έλμ ν΄λΌμ΄μΈνΈλ μλ΅μ λ°μΌλ©΄ μ²λ¦¬νκ³ μΌμ μκ° νμ λ€μ μμ²μ 보λ΄λ κ³Όμ μ λ°λ³΅νκ² λλ κ²μ΄μ£ .
μλ μ½λ μμ λ νλ¦μ μ΄ν΄λ₯Ό λκΈ° μν μμ£Ό κ°λ¨ν μμ μ λλ€.
// ν΄λΌμ΄μΈνΈ
setInterval(function(){
fetch('/server').then(function(response){
console.log(response);
});
}, 5000); // 5μ΄λ§λ€ μλ²μ μμ²
// μλ² (Node.js)
app.get('/server', function(req, res){
res.send('μλ‘μ΄ λ°μ΄ν°');
});
μ₯μ μΌλ‘λ λ§€μ° κ°λ¨ν λ©μ»€λμ¦μ΄κΈ° λλ¬Έμ ꡬνμ΄ λ§€μ° μ½μ΅λλ€.
μλ² μΈ‘ λν μμ²μ λν μλ΅λ§ μ²λ¦¬νλ©΄ λ©λλ€.
νμ§λ§, μ΄ λ°©μμλ λ¨μ μ΄ λΆλͺ ν μ‘΄μ¬ν©λλ€.
- λΆνμν μμ²(Request) μ β‘οΈ μλ² λΉμ© μ¦κ°
- μμ²κ³Ό μλ΅ μ¬μ΄μ μ§μ° μκ°μ΄ λ°μν©λλ€.
λ‘± ν΄λ§(Long Polling)
λ‘± ν΄λ§μ ν΄λ§μμ μ‘°κΈ λ κ°μ λ λ°©μμ λλ€.
λ¨Όμ , λμΌνκ² ν΄λΌμ΄μΈνΈλ μλ²μκ² μμ²(Request)μ 보λ λλ€.
μ΄ν μλ²λ μλ‘μ΄ λ°μ΄ν°κ° μλ€λ©΄ μΌμ μκ° λμ μλ΅μ νμ§ μκ³ μλ‘μ΄ λ°μ΄ν°κ° μμ λκΉμ§ κΈ°λ€λ¦½λλ€.
λ§μ½ μΌμ μκ° λμ μλ‘μ΄ λ°μ΄ν°κ° μλ€λ©΄ Time Outμ΄ λ°μνκ³ , μ΄λ μλ²λ Time Outμ λν μλ΅μ 보λ λλ€..
λ°λ©΄μ μλ‘μ΄ λ°μ΄ν°κ° μλ€λ©΄ μ¦μ μλ‘μ΄ λ°μ΄ν°μ λν μλ΅(Resonse)μ 보λ λλ€.
μλ μ½λλ λ§μ°¬κ°μ§λ‘, νλ¦μ λν μ΄ν΄λ₯Ό λκΈ° μν κ°λ¨ν μμ μ λλ€.
// ν΄λΌμ΄μΈνΈ
function longPoll(){
fetch('/server').then(function(response){
console.log(response);
longPoll();
});
}
longPoll();
// μλ² (Node.js)
app.get('/server', function(req, res){
setTimeout(function(){
res.send('μλ‘μ΄ λ°μ΄ν°');
}, 10000); // 10μ΄ νμ μλ΅
});
ν΄λ§κ³Ό μμ£Ό μ μ¬ν©λλ€.
μ μ¬νμ§λ§ ν΄λ§μ λΉν΄μ λΆνμν μμ²(Request) μλ μ€μ΄λ€κ² λ©λλ€.
ν΄λ§μ λΉν΄μ μ€μ΄λ κ²μ΄μ§ λΆνμν μμ²μ κ³μ μ§νλ©λλ€.
λν, μμ²κ³Ό μλ΅ μ¬μ΄μ λ°μνλ μ§μ° μκ°μ λΆκ°νΌν μ μμ΅λλ€.
μλ² μΌνΈ μ΄λ²€νΈ(Server-Sent Event)
μλ² μΌνΈ μ΄λ²€νΈ λ°©μμ μ λ°©μλ€κ³Όλ μ‘°κΈ λ€λ₯΄κ² λμν©λλ€.
ν΄λΌμ΄μΈνΈλ μ΅μ΄λ‘ ν λ² μλ²μ μ°κ²°μ μμ²ν©λλ€.
κ·ΈλΌ μλ²λ μμ²μ λ°κ³ , μ΄ν μλ‘μ΄ λ°μ΄ν°κ° μκΈΈ λλ§λ€ μ μ ν μ²λ¦¬νμ¬ ν΄λΌμ΄μΈνΈμκ² μλ΅μ 보λ λλ€.
μ¦, HTTP ν΅μ μ μ’ λ£νμ§ μκ³ μ°κ²°μ μ μ§νλ λ°©μμ λλ€.
μλ μ½λλ λ§μ°¬κ°μ§λ‘, νλ¦μ λν μ΄ν΄λ₯Ό λκΈ° μν κ°λ¨ν μμ μ λλ€.
// ν΄λΌμ΄μΈνΈ
const source = new EventSource("/server");
source.onmessage = function(event) {
console.log(event.data);
};
// μλ² (Node.js)
app.get('/server', function(req, res){
res.setHeader('Content-Type', 'text/event-stream');
setInterval(function(){
res.write('data: μλ‘μ΄ λ°μ΄ν°\n\n');
}, 5000); // 5μ΄λ§λ€ λ°μ΄ν° μ μ‘
});
SSEλ₯Ό μ¬μ©νμ¬ μ€μκ°μΌλ‘ ν΄λΌμ΄μΈνΈμκ² μλ΅μ λ³΄λΌ μ μμ΅λλ€.
λν, μ΄λ²€νΈ κΈ°λ°μΌλ‘ μλ²μμ λ³΄λΈ λ©μμ§μ λν΄ μ΄λ²€νΈ μ²λ¦¬κ° κ°λ₯ν©λλ€.
μ°κ²°μ΄ λμ΄μ§ κ²½μ°μλ SSEλ μλμΌλ‘ μ¬μ°κ²°μ μλν©λλ€.
νμ§λ§ μ΄ λ°©μμ ν΄λΌμ΄μΈνΈμ μ΅μ΄ μμ² μ΄ν μλ²λ§ μΌλ°©μ μΌλ‘ μλ΅μ νκ² λ©λλ€.
μ¦, μ°λ¦¬κ° μ²μ·¨νλ λΌλμ€μ κ°λ€κ³ λ³Ό μ μμ΅λλ€.
μμμ μμλ³Έ λ°©μλ€λ‘ HTTP ν΅μ μΌλ‘ μ€μκ° ν΅μ λ°©μμ ꡬνν μ μμ΅λλ€.
νμ§λ§, λ¨μ§ μ€μκ° ν΅μ μ ꡬννκΈ° μν λ°©λ²μΌ λΏ, μλ²½ν μ€μκ° ν΅μ μ 보μ₯νμ§λ μμ΅λλ€.
κ·Έλμ μ΄ λ¬Έμ μ μ ν΄κ²°νκΈ° μν΄ λ°λ‘ μΉ μμΌ(Web Socket)μ΄ λ±μ₯νμ΅λλ€.
μΉ μμΌ(Web Socket)μ΄λ?
μΉ μμΌμ HTML5μ λ±μ₯ μ€μκ° μΉ μ ν리μΌμ΄μ μ μν΄ μ€κ³λ ν΅μ νλ‘ν μ½μ΄λ©°, TCP(Transmission Control Protocol)λ₯Ό κΈ°λ°μΌλ‘ ν©λλ€.
TCPλ₯Ό κΈ°λ°μΌλ‘ ν μΉ μμΌμ μ λ’°μ± μλ λ°μ΄ν° μ μ‘μ 보μ₯νλ©°, λ©μμ§ κ²½κ³λ₯Ό μ‘΄μ€νκ³ , μμκ° λ³΄μ₯λ μλ°©ν₯ ν΅μ μ μ 곡ν μ μμ΅λλ€.
HTTPμ λ€λ₯΄κ² ν΄λΌμ΄μΈνΈμ μλ² κ°μ μ΅μ΄ μ°κ²°μ΄ μ΄λ£¨μ΄μ§λ©΄, μ΄ μ°κ²°μ ν΅ν΄ μλ°©ν₯ ν΅μ μ μ§μμ μΌλ‘ ν μ μμ΅λλ€.
μ¦, μ ν ν΅νμ κ°μ΄ μμͺ½ λͺ¨λμμ μ 보λ₯Ό μ£Όκ³ λ°μ μ μλ€λ μλ―Έμ λλ€.
μ΄ 'μ§μμ μ°κ²°'μ ν΅ν΄μ μλ²λ ν΄λΌμ΄μΈνΈμκ² μ€μκ°μΌλ‘ λ°μ΄ν°λ₯Ό λ³΄λΌ μ μμΌλ©°, λ°λλ‘ ν΄λΌμ΄μΈνΈλ μλ²μκ² λ°μ΄ν°λ₯Ό λ³΄λΌ μ μμ΅λλ€.
μ΄λ λ°μ΄ν°λ ‘ν¨ν·(packet)’ ννλ‘ μ λ¬λλ©°, μ μ‘μ μ°κ²° μ€λ¨κ³Ό μΆκ° HTTP μμ² μμ΄ μλ°©ν₯μΌλ‘ μ΄λ€μ§λλ€.
ν¨ν·(packet)μ΄λβ
λ€νΈμν¬ ν΅μ μμ λ°μ΄ν°λ₯Ό μμ μ‘°κ°μΌλ‘ λλ μ μ μ‘νλ λ¨μλ₯Ό λ§ν©λλ€.
μΉμμΌ μ°κ²°μ νλ €λ©΄ new WebSocketμ νΈμΆνλ©΄ λλλ°, μ΄λ wsλΌλ νΉμ νλ‘ν μ½μ μ¬μ©ν©λλ€.
const socket = new WebSocket("ws://yong-nyong.tistory.com/socket");
ws λ§κ³ wss://λΌλ νλ‘ν μ½λ μ‘΄μ¬νλ©°, λ νλ‘ν μ½μ κ΄κ³λ HTTPμ HTTPSμ κ΄κ³μ μ μ¬ν©λλ€.
μμΌμ΄ μ μμ μΌλ‘ μμ±λλ©΄ μλ λ€ κ°μ μ΄λ²€νΈλ₯Ό μ¬μ©ν μ μκ² λ©λλ€.
- open – μ°κ²°μ΄ μ±κ³΅μ μΌλ‘ λμμ λ λ°μ
- message – λ°μ΄ν°λ₯Ό μμ νμμ λ λ°μ
- error – μ°κ²° μ μλ¬κ° μκ²Όμ λ λ°μ
- close – μ°κ²°μ΄ μ’ λ£λμμ λ λ°μ
μΆκ° μμ±μ 곡μ λ¬Έμμμ νμΈν΄ μ£ΌμΈμ.
μΉ μμΌ νΈλμ °μ΄ν¬(handshake)
new WebSocket(url)μ νΈμΆν΄ μμΌμ μμ±νλ©΄ μ¦μ μ°κ²°μ΄ μμλ©λλ€.
μΉ μμΌμ HTTP κΈ°λ°μΌλ‘ μ΄κΈ° handshakeλ₯Ό μνν©λλ€.
μ΄ν, λ°μ΄ν° μ μ‘μ μΉ μμΌ νλ‘ν μ½μ μ΄μ©νμ¬ ν΅μ νκ² λ©λλ€.
new WebSocket("wss://yong-nyong-tistory.com/socket")μ νΈμΆν΄ μ΅μ΄ μμ²μ μ μ‘νλ€κ³ κ°μ ν©μλ€.
μ΄λμ μμ²(Reqeust) ν€λλ₯Ό μ΄ν΄λ³΄λ©΄ μλμ κ°μ΅λλ€.
GET /socket
Host: yong-nyong-tistory.com
Origin: https://yong-nyong-tistory.com
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: Ivyio/9s+lYongNyongczP8Q==
Sec-WebSocket-Version: 13
- Origin – ν΄λΌμ΄μΈνΈ originμ λνλ λλ€.
- Connection: Upgrade – ν΄λΌμ΄μΈνΈ μΈ‘μμ νλ‘ν μ½μ λ°κΎΈκ³ μΆλ€λ μ νΈλ₯Ό 보λλ€λ κ²μ λνλ λλ€. (https β‘οΈ wss)
- Upgrade: websocket – ν΄λΌμ΄μΈνΈ μΈ‘μμ μμ²ν νλ‘ν μ½μ 'websocket’μ΄λΌλ κ²μ μλ―Έν©λλ€. (https β‘οΈ wss)
- Sec-WebSocket-Key – 보μμ μν΄ λΈλΌμ°μ μμ μμ±ν ν€λ‘, μλ²κ° μΉμμΌ νλ‘ν μ½μ μ§μνλμ§λ₯Ό νμΈνλ λ° μ¬μ©λ©λλ€.
- Sec-WebSocket-Version – μΉμμΌ νλ‘ν μ½ λ²μ μ λνλ λλ€.
λ€μμΌλ‘ μλ²κ° ν΄λΉ μμ²μ λ°μΌλ©΄ μΉ μμΌ μ°κ²°μ μλ½νλ μλ΅μ 보λ λλ€.
ν΄λΉ μλ΅μλ '101 Switching Protocols' μν μ½λμ ν¨κ» μλ΅ν©λλ€.
101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: hsBYongNyong24s99EO10UlZ22C2g=
μ΄ κ³Όμ μ ν΅ν΄μ ν΄λΌμ΄μΈνΈμ μλ² κ° μ€μκ° ν΅μ μ΄ κ°λ₯ν ν΅λ‘κ° μ΄λ¦¬κ² λλ κ²μ λλ€.
μ΄λ κ² μΉ μμΌ μ°κ²°μ΄ μ±λ¦½λλ©΄, ν΄λΌμ΄μΈνΈμ μλ² κ°μ μ€μκ° μλ°©ν₯ ν΅μ μ΄ κ°λ₯ν΄μ§λλ€.
λ°μ΄ν° μ μ‘μ 'νλ μ(Frame)'μ΄λΌλ λ¨μλ‘ μ μ‘λ©λλ€.
κ° νλ μμ ν μ€νΈ λ°μ΄ν° λλ μ΄μ§ λ°μ΄ν°λ₯Ό ν¬ν¨ν μ μμ΅λλ€.
βοΈ ν μ€νΈ νλ μ(text frame): ν μ€νΈ λ°μ΄ν°κ° λ΄κΈ΄ νλ μ
βοΈ μ΄μ§ λ°μ΄ν° νλ μ(binary data frame): μ΄μ§ λ°μ΄ν°κ° λ΄κΈ΄ νλ μ
βοΈ ν·ν νλ μ(ping/pong frame): 컀λ₯μ μ΄ μ μ§λκ³ μλμ§ νμΈν λ μ¬μ©νλ νλ μμΌλ‘ μλ²λ λΈλΌμ°μ μμ μλ μμ±ν΄μ 보λ΄λ νλ μ
βοΈ μ΄ μΈμλ 컀λ₯μ μ’ λ£ νλ μ(connection close frame) λ± λ€μν νλ μμ΄ μ‘΄μ¬ν©λλ€.
μΉ μμΌ(Web Socket)μ νκ³μ
λͺ¨λ μ§ μ₯μ μ΄ μμΌλ©΄ λ¨μ μ΄ μκΈ° λ§λ ¨μ λλ€.
κ·Έλ λ€λ©΄ λ¨μ μ 무μμ΄ μμκΉμ?
- λΈλΌμ°μ μ§μ: μΉ μμΌμ HTML5 μ¬μμ μΌλΆμ λλ€. μ¦, HTML5λ₯Ό μ§μνμ§ μλ λΈλΌμ°μ μμλ μ¬μ©ν μ μμ΅λλ€.
- μλ² λΉμ©: μΉ μμΌμ μ§μμ μΈ μ°κ²°μ μ μ§νλ―λ‘, λ§μ μμ μΉμμΌ μ°κ²°μ λμμ κ΄λ¦¬ν΄μΌ νλ κ²½μ° μλ²μ λΆνκ° μ¦κ°ν μ μμ΅λλ€.
- λ€μν μλ¬μ²λ¦¬: λ§μ½ μ°κ²°μ΄ λμ΄μ‘μ μ μ΄λ€ μ΄μ μμ μ°κ²°μ΄ λμ΄μ‘λμ§μ κ°μ μμΈν μλ¬ μ²λ¦¬μ λν νκ³κ° μμ΅λλ€. μΉμμΌμ μ°κ²°μ΄ λμ΄μ§ μ΄μ μ λν΄μ μ νν μ μ μμ΅λλ€.
- μ¬μ°κ²° μ²λ¦¬: μ μ μλ μλ¬λ‘ μΈν΄ μ°κ²°μ΄ λμ΄μ§λ©΄ μ§μμ μΈ μ°κ²°μ ν΄μΌ νλ μΉ μμΌ νΉμ±μ μ¬μ°κ²°μ ν μ μλλ‘ κ΅¬νν΄μΌ ν©λλ€. μΉμμΌμ μλμΌλ‘ μ¬μ°κ²°μ μ§ννμ§ μμ΅λλ€.
π λ§λ¬΄λ¦¬
μ΄λ‘μ, μ€μκ° μλ°©ν₯ ν΅μ μ μ½κ² ꡬνν μ μλλ‘ ν΄μ£Όλ μΉ μμΌ(Web Socket)μ λν μ μ, λ±μ₯ λ°°κ²½, λμλ°©μ, νκ³μ μ λν΄μ μμλ΄€μ΅λλ€.
μ΅κ·Ό λΉ λ₯Έ μ£ΌκΈ°λ‘ κ°±μ μ΄ λ°μνλ μ€μκ° λ°μ΄ν°λ₯Ό μ²λ¦¬ν¨μ μμ΄μ μΉ μμΌμ μ¬μ©νμ΅λλ€.
μΉ μμΌμ μν λ§ μκ³ μμλ μν©μΈμ§λΌ, κ·Όλ³Έμ μΌλ‘ κΉκ² μμλ³Ό νμκ° μλ€κ³ μκ°νμ¬ μ΄λ κ² ν¬μ€ν νκ² λμμ΅λλ€.
μΉ μμΌμ μ§μνλ λΌμ΄λΈλ¬λ¦¬λ λͺ κ°μ§ μμΌλ©°, μΉ μμΌμ νκ³μ μ μ΄λ μ λ ν΄κ²°νκ³ μ¬μ©μ κ°νΈνκ² ν΄ μ€λλ€.
νμ§λ§ νκ³μ μ ν΄κ²°ν΄ μ€λ€κ³ ν΄μ 무쑰건 μ’μ κ²λ§μ μλλλ€.
μΌλ° μΉ μμΌμ λΌμ΄λΈλ¬λ¦¬λ³΄λ€ κ°λ³κ³ λΉ λ₯΄λ©°, λ μ μ μλ² μμμ μ¬μ©ν©λλ€.
λν, μ¬μ°κ²° λ‘μ§ κ°μ κΈ°λ₯λ μ§μ ꡬνν μ μμ΅λλ€.
λ°λΌμ μν©μ λ°λΌ μΌλ° μΉ μμΌκ³Ό λΌμ΄λΈλ¬λ¦¬ μ€ λ λμ μ νμ νλ κ²μ μΆμ²ν©λλ€.
λμμ΄ λμκΈΈ λ°λλλ€.
μ°Έκ³ λ¬Έν:
- https://www.youtube.com/watch?v=yXPCg5eupGM
- https://developer.mozilla.org/ko/docs/Web/API/WebSocket
- https://ko.javascript.info/websocket
- https://www.youtube.com/watch?v=VODXNECZOBQ&t=884s
- https://inpa.tistory.com/entry/WEB-%F0%9F%8C%90-%EC%9B%B9-%EC%86%8C%EC%BC%93-Socket-%EC%97%AD%EC%82%AC%EB%B6%80%ED%84%B0-%EC%A0%95%EB%A6%AC