-
Notifications
You must be signed in to change notification settings - Fork 7
๐ชต 2. ์๋ฐฉํฅ ์น ํต์ ์ ์งํ: HTTP๋ ๋ฐ๋ณด~
์ด๋ฒ์ ์น ํ๊ฒฝ์์์ ํด๋ผ์ด์ธํธ - ์๋ฒ ๊ฐ ์ค์๊ฐ ํต์ ๊ธฐ์ ์ ์ฌ์ฉํ ๊ธฐํ๊ฐ ์๊ฒจ์ ํ์ตํ๋ ค๊ณ ํ๋ ์์ค์, ๋จผ์ ์ค์๊ฐ ํต์ ์ ๋ํด ์ฌ๋ ์๋ ๋ฐฐ๊ฒฝ๊ณผ ์ดํด๊ฐ ํ์ํด ์ด๋ ๊ฒ ์์ฑํ๊ฒ ๋์ต๋๋ค.
์น์ ๋ณธ๋ ๋ฌธ์ ๊ณต์ ๋ฅผ ์ํ ํ๋ซํผ์ผ๋ก ์์๋์ต๋๋ค. HTTP ํ๋กํ ์ฝ์ ์ด๋ฌํ ๋ชฉ์ ์ ๋ง๊ฒ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ์๋ฒ๊ฐ ์๋ตํ๋ ๋จ๋ฐฉํฅ ํต์ ๋ชจ๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋์ต๋๋ค. ํ์ง๋ง ์น์ด ๋ฐ์ ํ๋ฉด์ ์ค์๊ฐ ์ฑํ , ์จ๋ผ์ธ ๊ฒ์, ํ์ ํ์ ๋ฑ ์ฆ๊ฐ์ ์ธ ์๋ฐฉํฅ ํต์ ๊ณผ ๋ ๋ง์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด์ค ํ์๊ฐ ์๊ฒผ๊ณ , ์ด๋ ์๋ก์ด ํต์ ๋ฐฉ์์ ํ์์ฑ์ ๋ถ๋ฌ์์ต๋๋ค.
์ด ๊ธ์์ HTTP๋ฅผ ์ดํดํ๊ณ ์๋ค๋ ์กฐ๊ฑด์ ์ ์ ํ๊ณ ์์ต๋๋ค. ํน์ฌ๋ ๋ชจ๋ฅธ๋ค๋ฉด ์ด์ ์ ๋คํธ์ํฌ ๊ฐ๋ตํ ์ ์ : IP, TCP/UDP, HTTP(S)
์ ๋ํด์ ๋จผ์ ์ฝ๊ณ ์ค์๋ ๊ฑธ ์ถ์ฒํฉ๋๋ค.
๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ๊ท์ฝ์ธ HTTP/1.1์ ์๋์ ๊ฐ์ ํน์ง์ ๊ฐ์ง๊ณ ์์์ต๋๋ค.
์์ฒญ-์๋ต ํ ์ฐ๊ฒฐ ์ข ๋ฃ.
HTTP/1.1์ ์์ฒญ์ด ์ค๋ฉด ์๋ฒ๊ฐ ์๋ต์ ๋ฐํํ ํ ์ฐ๊ฒฐ์ ๋๋ ํน์ฑ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. ์ฆ, ๊ฐ ์์ฒญ์ด ๋ ๋ฆฝ์ ์ผ๋ก ์ฒ๋ฆฌ๋๋ฉฐ ํด๋ผ์ด์ธํธ์ ์๋ฒ๋ ํญ์ ์๋ก์ด ์ฐ๊ฒฐ์ ๋งบ๊ณ ๋๋ ๊ณผ์ ์ ๋ฐ๋ณตํ๊ฒ ๋ฉ๋๋ค. ์ด๋ ๋ฆฌ์์ค๊ฐ ๋ญ๋น๋๋ ๊ตฌ์กฐ์ด๋ฉฐ, ์์ฃผ ํต์ ํด์ผ ํ๋ ํ๊ฒฝ์์๋ ๋นํจ์จ์ ์ ๋๋ค.
ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ํ ์๋ฒ ์๋ต๋ง ๊ฐ๋ฅ.
HTTP/1.1์ ํด๋ผ์ด์ธํธ๊ฐ ์๋ฒ์ ์์ฒญ์ ๋ณด๋ด๊ณ ์๋ฒ๊ฐ ์๋ตํ๋ ๋ฐฉ์์ผ๋ก ์๋ํฉ๋๋ค. ๋ค์ ๋งํด, ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์ ์์๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ์ ์๋ ๊ตฌ์กฐ์ ๋๋ค. ์ด๋ฌํ ํน์ฑ์ ์ค์๊ฐ ๋ฐ์ดํฐ ์ ์ก์ด ํ์ํ ์ ํ๋ฆฌ์ผ์ด์ ์์ ํ๊ณ๋ฅผ ๋ํ๋ด๊ณ , ๋ณ๋์ ํด๋ง(polling) ๋ฐฉ์ ๋ฑ์ ํตํด ์ฃผ๊ธฐ์ ์ผ๋ก ์๋ฒ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํด์ผ ํ๋ ๋นํจ์จ์ ๋ฐ์์ํต๋๋ค.
์ด์ ์์ฒญ๊ณผ ํ์ฌ ์์ฒญ ๊ฐ์ ๊ด๊ณ๊ฐ ์์.
HTTP๋ ๋ฌด์ํ ํ๋กํ ์ฝ๋ก, ๊ฐ ์์ฒญ์ด ์๋ก ๋ ๋ฆฝ์ ์ด๋ฉฐ ์ด์ ์์ฒญ์ ์ํ๋ฅผ ์ ์งํ์ง ์์ต๋๋ค. ์์๋ฅผ ๋ค์๋ฉด ์ฌ์ฉ์๊ฐ ๋ก๊ทธ์ธํ๋ค๋ ์ํ ์ ๋ณด๋ฅผ HTTP ์์ฒด์์ ๊ธฐ์ตํ์ง ์๊ธฐ ๋๋ฌธ์, ์ธ์ ์ด๋ ์ฟ ํค ๋ฑ์ ๋ณ๋๋ก ๊ด๋ฆฌํ์ฌ ์ฌ์ฉ์๋ฅผ ์๋ณํด์ผ ํฉ๋๋ค. ์ด๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ ๊ฐ์ ์ง์์ ์ธ ์ํ ์ ์ง๋ฅผ ์ด๋ ต๊ฒ ๋ง๋ค๊ณ , ๋ฐ์ดํฐ๊ฐ ๋ณ๊ฒฝ๋์ง ์๋๋ผ๋ ๋งค๋ฒ ์ฌ์ ์กํด์ผ ํ๋ ๋จ์ ์ด ์์ต๋๋ค.
์์ ๊ฐ์ ํน์ง๋ค์ ์ด๊ธฐ ์ ์ ์ธ ์น ํ์ด์ง ์ ๊ณต์๋ ์ ํฉํ์ผ๋, ์ฑํ ์ ํ๋ฆฌ์ผ์ด์ , ์ค์๊ฐ ํ์ ๋๊ตฌ ๋ฑ ์ํธ์์ฉ์ด ๋น๋ฒํ๊ณ ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ์ค์ํ ํ๋์ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ํ๊ณ๋ฅผ ๋๋ฌ๋์ต๋๋ค. ๋ํ, 1.1์ ๋จ์ ์ ์์ ๊ธฐ ์ํด ๋์จ HTTP/2์ HTTP/3๋ก๋ ์๋ฒ ์์ ์์ฒญ ๋ถ๊ฐ, ์๋ฒ ์ฐ๊ฒฐ ์ ์ง์ ๋ํ ๋นํจ์จ์ ๋ฑ์ ๋ํ ๋จ์ ์ด ์์ด์ง์ง ์์์ต๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด WebSocket ๋ฑ๊ณผ ๊ฐ์ ์๋ก์ด ์๋ฐฉํฅ ํต์ ํ๋กํ ์ฝ์ด ๋ฑ์ฅํ๊ฒ ๋์์ต๋๋ค.
์ด๋ฌํ HTTP์ ๊ตฌ์กฐ์ ํ๊ณ๋ก ์ธํด ์ค์๊ฐ ์ํธ์์ฉ์ด ์ค์ํ ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๋ค์ํ ํด๊ฒฐ ๋ฐฉ์์ด ์๋๋์ต๋๋ค. ์ด ํญ๋ชฉ์์๋ ๊ทธ์ ๋ํ ํด๊ฒฐ ๋ฐฉ์๊ณผ ๋จ์ ๋ฐ ํ๊ณ๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์๋ฒ์ ์ฃผ๊ธฐ์ ์ผ๋ก ์์ฒญ์ ๋ณด๋ด๊ณ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด ์๋ตํ๋ ๋ฐฉ์ > ์ค์๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ป๊ธฐ ์ํด ์ฃผ๊ธฐ์ ์ผ๋ก ์๋ฒ์ ์์ฒญ์ ๋ณด๋ด์ ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ์๋์ง ํ์ธ
๋จ๋ฐฉํฅ ํต์ ํ๋กํ ์ฝ์ ํ๊ณ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด, (Ajax) Polling๊ณผ Long Polling์ด ๋์ ๋์์ต๋๋ค. ๋์ ์ฐจ์ด๋ ์๋ต ์ง์ฐ ๋ฐฉ์์ ์์ต๋๋ค.
- (Ajax) Polling: ์์ฒญ ํ ์ฆ์ ์๋ต, ์ฃผ๊ธฐ์ ์ผ๋ก ์๋ฒ์ ์๋ก์ด ์์ฒญ ์ ์ก.
- Long Polling: ์์ฒญ ํ ์๋ฒ๊ฐ ์ ๋ฐ์ดํฐ๊ฐ ๋ฐ์ํ ๋๊น์ง ์๋ต ์ง์ฐ(Persisted). ๋ฐ์ดํฐ๊ฐ ๋ฐ์ํ๋ฉด ์๋ต์ ๋ณด๋ด๊ณ ์ฐ๊ฒฐ์ ๋์ ํ, ํด๋ผ์ด์ธํธ๋ ๋ค์ ์์ฒญ ์์.
๋จ์ ์ ์๋์ ๊ฐ์ต๋๋ค.
- ๋ถํ์ํ HTTP ์ค๋ฒํค๋: ๋ ๋ชจ๋ ์์ฒญ ์๋ง๋ค HTTP ํค๋์ ๊ธฐํ ๋ถ๊ฐ ์ ๋ณด๊ฐ ํฌํจ๋ผ ๋คํธ์ํฌ ์์์ด ๋ญ๋น.
-
์๋ฒ ์์ ๋ญ๋น
- Ajax Polling: ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ์์ด๋ ์ฃผ๊ธฐ์ ์ผ๋ก ์์ฒญ => ์๋ฒ์๊ฒ ๋ถํ์ ๋ฆฌ์์ค ์๋ชจ ๋ฐ์.
- Long Polling: Ajax Polling ๋ค์ ๊ฐ์ . But, ๋ง์ ์ฐ๊ฒฐ ์ ์ง => ์๋ฒ ๋ถ๋ด ์ฆ๊ฐ.
-
์ค์๊ฐ์ฑ์ ํ๊ณ
- Ajax Polling: ์ค์ ๋ ๊ฐ๊ฒฉ๋ง๋ค ์์ฒญ => ๊ทธ ์ฌ์ด ์ค์๊ฐ์ฑ ๋ณด์ฅ X.
- Long Polling: ์ฆ๊ฐ์ ์ธ ๋ฐ์ดํฐ ์ ์ก์ด ๊ฐ๋ฅ, But ์ฐ๊ฒฐ ๊ด๋ฆฌ ๋ณต์ก.
- ํ์ฅ์ฑ ๋ฌธ์ : ๋ง์ ํด๋ผ์ด์ธํธ๊ฐ ๋์์ ์์ฒญํ ๊ฒฝ์ฐ ์๋ฒ์ ํฐ ๋ถํ๊ฐ ๋ฐ์ํด ํ์ฅ์ฑ ํ๋ฝ.
์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก์ ๋จ๋ฐฉํฅ ์ค์๊ฐ ๋ฐ์ดํฐ ์คํธ๋ฆผ์ ์ ๊ณตํ๋ ์น ํ์ค ๊ธฐ์
Polling์ ํ๊ณ๋ฅผ ๊ฐ์ ํ๊ณ WebSocket๋ณด๋ค ๊ฐ๋จํ ๊ตฌํ์ ์ํ๋ ๊ฒฝ์ฐ๋ฅผ ์ํด ๋ฑ์ฅํ ๊ธฐ์ ์ ๋๋ค. SSE๋ ๊ธฐ์กด HTTP ์ฐ๊ฒฐ์ ํตํด ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์๊ฒ ์ง์์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ์ ์๊ฒ ํด์ค๋๋ค.
// ํด๋ผ์ด์ธํธ ์ธก ์ฝ๋
const eventSource = new EventSource('/api/events');
eventSource.onmessage = (event) => {
console.log('์๋ก์ด ๋ฐ์ดํฐ:', event.data);
};
// ์๋ฒ ์ธก ์ฝ๋ (Node.js ์์)
app.get('/api/events', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
// ์๋ก์ด ๋ฐ์ดํฐ๊ฐ ์์ ๋๋ง๋ค ์ ์ก
setInterval(() => {
res.write(`data: ${JSON.stringify({ time: new Date() })}\n\n`);
}, 1000);
});
- ํด๋ผ์ด์ธํธ๊ฐ HTTP ์ฐ๊ฒฐ์ ์์ฑ
- ์๋ฒ๋ ์ฐ๊ฒฐ์ ์ ์งํ๋ฉฐ
text/event-stream
ํ์์ผ๋ก ๋ฐ์ดํฐ ์ ์ก - ์๋ ์ฌ์ฐ๊ฒฐ ๋ฉ์ปค๋์ฆ ์ ๊ณต
-
๋จ์ํ ๊ตฌํ
- ์ผ๋ฐ HTTP๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํ ๊ฐ๋ฅ
- WebSocket๋ณด๋ค ์๋ฒ ๊ตฌํ์ด ๊ฐ๋จ
- ๊ธฐ์กด HTTP ์ธํ๋ผ ํ์ฉ ๊ฐ๋ฅ (ํ๋ก์, ๋ก๋๋ฐธ๋ฐ์ ๋ฑ)
-
์๋ ์ฌ์ฐ๊ฒฐ
- ์ฐ๊ฒฐ์ด ๋์ด์ก์ ๋ ์๋์ผ๋ก ์ฌ์ฐ๊ฒฐ ์๋
- ๋ง์ง๋ง ์ด๋ฒคํธ ID๋ฅผ ์ถ์ ํ์ฌ ๋๋ฝ๋ ๋ฉ์์ง ๋ณต๊ตฌ ๊ฐ๋ฅ
-
๋ธ๋ผ์ฐ์ ํธํ์ฑ
- ๋๋ถ๋ถ์ ๋ชจ๋ ๋ธ๋ผ์ฐ์ ์์ ์ง์
- ํด๋ฆฌํ์ ํตํ ํ์ ํธํ์ฑ ์ ๊ณต
-
๋จ๋ฐฉํฅ ํต์
- ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก๋ง ๋ฐ์ดํฐ ์ ์ก ๊ฐ๋ฅ
- ํด๋ผ์ด์ธํธ์์ ์๋ฒ๋ก์ ๋ฐ์ดํฐ ์ ์ก์ ๋ณ๋์ HTTP ์์ฒญ ํ์
-
์ฐ๊ฒฐ ์ ์ ํ
- ๋ธ๋ผ์ฐ์ ๋น ๋์ ์ฐ๊ฒฐ ์ ์ ํ ์กด์ฌ
- ๋๋ฉ์ธ๋น ์ฐ๊ฒฐ ์ ํ์ผ๋ก ์ธํ ํ์ฅ์ฑ ์ ์ฝ
-
์ ํ๋ ๋ฐ์ดํฐ ํ์
- ํ ์คํธ ๊ธฐ๋ฐ ๋ฐ์ดํฐ๋ง ์ ์ก ๊ฐ๋ฅ
- ๋ฐ์ด๋๋ฆฌ ๋ฐ์ดํฐ ์ ์ก ๋ถ๊ฐ
- ์ค์๊ฐ ์ฃผ์ ์์ธ, ๋ด์ค ํผ๋
- ์์ ๋ฏธ๋์ด ์ ๋ฐ์ดํธ
- ์ค์๊ฐ ๋ก๊ทธ ๋ชจ๋ํฐ๋ง
- ์งํ ์ํฉ ์ ๋ฐ์ดํธ
SSE๋ ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก์ ๋จ๋ฐฉํฅ ์ค์๊ฐ ๋ฐ์ดํฐ ์ ์ก์ด ํ์ํ๊ณ , ๊ตฌํ์ ๋จ์์ฑ์ด ์ค์ํ ๊ฒฝ์ฐ์ ์ ํฉํ ์ ํ์ ๋๋ค. WebSocket๋ณด๋ค ๊ฐ๋ฒผ์ฐ๋ฉด์๋ Polling๋ณด๋ค ํจ์จ์ ์ธ ์ค๊ฐ์์ ์์น๋ฅผ ์ฐจ์งํ๊ณ ์์ต๋๋ค.
์ค์๊ฐ ํต์ ์ ์ํ ์ด๊ธฐ ์๋์๋ ๋ Polling ํ์ ๋ค์ ์ค์๊ฐ ๋ฐ์ดํฐ ํ์ธ์ ๊ฐ๋ฅํ๊ฒ ํ์ง๋ง, ์ง์์ ์ธ ์๋ฒ ์ฐ๊ฒฐ๊ณผ ์ค์๊ฐ์ฑ์ ๋ณด์ฅํ๊ธฐ์๋ ํ๊ณ๊ฐ ์์์ต๋๋ค.
์ดํ ๋ฑ์ฅํ SSE๋ ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก์ ๋จ๋ฐฉํฅ ์ค์๊ฐ ์คํธ๋ฆฌ๋ฐ์ ํจ๊ณผ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๊ฒ ํ์ง๋ง, ์๋ฐฉํฅ ํต์ ์ด ํ์ํ ์ํฉ์์๋ ์ฌ์ ํ ์ ์ฝ์ด ์์์ต๋๋ค.
๊ฒฐ๊ตญ ์ด๋ฌํ ํ๊ณ๋ค์ ๊ทผ๋ณธ์ ์ผ๋ก ํด๊ฒฐํ๊ธฐ ์ํด WebSocket ๋ฑ์ ์๋ฐฉํฅ ํต์ ํ๋กํ ์ฝ์ด ๋ฑ์ฅํ๊ฒ ๋์์ต๋๋ค. ๋ฐ์ชฝ์ง๋ฆฌ๊ฐ ์๋ ์น์์์ ์ค์๊ฐ ์๋ฐฉํฅ ํต์ ์ด WebSocket์ ๋ฑ์ฅ์ผ๋ก ๊ตฌํ๋ ์ ์์๋ ๊ฒ๋๋ค!
2008๋ TCP ์ฐ๊ฒฐ ๊ด๋ จ ๋ ผ์์์, Michael Carter๊ฐ ์ฃผ๋ํด WebSocket ํ๋กํ ์ฝ์ ์ ์ํ์ต๋๋ค. '์น ์๋ฐฉํฅ ํต์ ๋ฌธ์ ๋ฅผ ๊ทผ๋ณธ์ ์ผ๋ก ํด๊ฒฐํ๊ธฐ ์ํด์' ์์ฃ . HTML5 ํ์คํ ๊ณผ์ ์์ WebSocket์ ์ค์ํ ๋ถ๋ถ์ผ๋ก ์๋ฆฌ์ก์๊ณ , 2011๋ RFC 6455๋ก ํ์คํ๋์์ต๋๋ค.
- HTTP ํ๋กํ ์ฝ ์์์ Handshaking ์ต์ด ์ํ.
- ์ต์ด ์ฐ๊ฒฐ ์๋ฆฝ ํ ๋์ผํ ์ฐ๊ฒฐ ์ฌ์ฌ์ฉ.
-
Upgrade: websocket
ํค๋๋ก ์์ฒญ. -
Connection: Upgrade
ํค๋๋ก ์๋ต ๋ฐ ์ฐ๊ฒฐ.
-
- HTTP์ฒ๋ผ ๋งค ์์ฒญ๋ง๋ค ์๋ก์ด ์ฐ๊ฒฐ ๋งบ์ง ์์.
- ์ฐ๊ฒฐ ์๋ฆฝ์ ๋ฐ๋ฅธ ๋ฆฌ์์ค ์๋ชจ ์ต์ํ.
HTTP๋ ์์ฒญ๋ง๋ค 3-way handshake๊ฐ ํ์ํ์ง๋ง, WebSocket์ ์ต์ด 1ํ handshake ํ ๊ณ์ ์ฌ์ฉํ๋ ํน์ง์ ๊ฐ์ง๊ณ ์์ต๋๋ค.
- ํด๋ผ์ด์ธํธ์ ์๋ฒ๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ๋ฉ์์ง ์ ์ก ๊ฐ๋ฅ.
- ์๋ฒ๊ฐ ํด๋ผ์ด์ธํธ์ ์์ฒญ ์์ด๋ ๋ฐ์ดํฐ ์ ์ก ๊ฐ๋ฅ.
- ์ฆ, ์ค์๊ฐ ์๋ฆผ, ์ฑํ ๋ฑ์ ์ด์์ .
// ์๋ฒ์์ ํด๋ผ์ด์ธํธ๋ก ์๋ฐ์ ๋ฉ์์ง ์ ์ก ์์
webSocket.send(
JSON.stringify({
type: 'notification',
message: '์๋ก์ด ๋ฉ์์ง๊ฐ ๋์ฐฉํ์ต๋๋ค.',
}),
);
์์ฒ๋ผ ์ฐ๊ฒฐ๋ webSocket
๊ฐ์ฒด์ send
๋ฉ์๋๋ฅผ ํ์ฉํ๋ฉด ํด๋ผ์ด์ธํธ์ ์์ฒญ ์์ด๋ ์๋ต์ ์์ฃผ ๊ฐ๋ณ๊ฒ ๋ณด๋ผ ์ ์์ต๋๋ค.
- ๋งค์ฐ ์์ ํค๋ ํฌ๊ธฐ. (2-14 ๋ฐ์ดํธ)
- HTTP์ ๋ฌด๊ฑฐ์ด ํค๋์ ๋น๊ตํด ๋ฐ์ดํฐ ์ ์ก ํจ์จ์ฑ ๋์.
- HTTP ํค๋ ์์. (์ฝ 200๋ฐ์ดํธ)
GET /api/data HTTP/1.1 Host: example.com User-Agent: Mozilla/5.0 ... Accept: */* Connection: keep-alive Cookie: session=abc123...
- WebSocket ํ๋ ์ ํค๋ ์์. (2-14๋ฐ์ดํธ)
FIN RSV1-3 Opcode MASK Payload len [Extended payload length] [Masking key]
- ์ฐ๊ฒฐ ์ํ ๋ชจ๋ํฐ๋ง์ ์ํ ๋ด์ฅ ๋ฉ์ปค๋์ฆ.
-
ping
/pong
ํ๋ ์์ ํตํ ์ฐ๊ฒฐ ์์กด ํ์ธ. - ์๋ ์ฌ์ฐ๊ฒฐ ๊ตฌํ ์ฉ์ด.
class WebSocketClient {
constructor(url) {
this.url = url;
this.reconnectAttempts = 0;
this.connect();
}
connect() {
this.ws = new WebSocket(this.url);
// ์ฐ๊ฒฐ ์ํ ๋ชจ๋ํฐ๋ง
this.ws.onclose = (event) => {
if (event.code !== 1000) {
// ๋น์ ์ ์ข
๋ฃ
this.reconnect();
}
};
// ์ฃผ๊ธฐ์ ์ธ ping/pong ์ฒดํฌ
this.heartbeat = setInterval(() => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send('ping');
}
}, 30000);
}
reconnect() {
if (this.reconnectAttempts < 5) {
setTimeout(() => {
this.reconnectAttempts++;
this.connect();
}, 1000 * Math.pow(2, this.reconnectAttempts));
}
}
}
๊ทธ ์ธ WebSocket ํ๋กํ ์ฝ์ ์๋ธํ๋กํ ์ฝ ์ง์ ๋ฐ ์ปค์คํ ํ๋กํ ์ฝ ๊ตฌํ๋ ๊ฐ๋ฅํ๊ณ , Text ๋ฐ Binary ๋ฑ์ ๋ฐ์ดํฐ ๊ฐ์ ๋ค์ํ ๋ฉ์์ง ํฌ๋งท๋ ์ง์์ด ๋ฉ๋๋ค. WebSocket์ ์ด๋ฌํ ํน์ง๋ค์ ํตํด ์ค์๊ฐ ์๋ฐฉํฅ ํต์ ์ด ํ์ํ ํ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์ ์๊ตฌ์ฌํญ์ ํจ๊ณผ์ ์ผ๋ก ์ถฉ์กฑ์์ผ ํฐ ๋ฐ์ ์ ์ด๋ฃจ์์ต๋๋ค.
WebSocket์ ์ค์๊ฐ ์ํธ์์ฉ์ด ํ์ํ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ํฐ ๋ฐ์ ์ ์ด๋ฃจ์์ง๋ง, ๋ช ๊ฐ์ง ์ค์ํ ๋จ์ ์ด ์์ต๋๋ค. ์ด๋ฌํ ๋จ์ ๋๋ฌธ์ WebRTC์ ๊ฐ์ P2P ์ค์๊ฐ ํต์ ํ๋กํ ์ฝ์ด ๊ฐ๋ฐ๋์ต๋๋ค.
Client A โ Server โ Client B
WebSocket์ ๋ฌด์กฐ๊ฑด ์ค์ ์๋ฒ๋ฅผ ํตํด ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์ ์กํด์ผ ํฉ๋๋ค. ํด๋ผ์ด์ธํธ ๊ฐ์ ์ง์ ํต์ ์ด ํ์ํ ๊ฒฝ์ฐ์๋ ์๋ฒ๊ฐ ์ค๊ฐ ์ญํ ์ ํด์ผ ํ๋ฏ๋ก, ์ง์ฐ ์๊ฐ์ด ๋์ด๋๊ณ ์๋ฒ ์์์ด ์ถ๊ฐ๋ก ์๋ชจ๋ฉ๋๋ค.
// WebSocket์ผ๋ก ๋น๋์ค ์คํธ๋ฆผ ์ ์ก ์๋ ์์
const ws = new WebSocket('wss://example.com');
// ๋นํจ์จ์ ์ธ ๋ฏธ๋์ด ๋ฐ์ดํฐ ์ ์ก
videoStream.getTracks().forEach((track) => {
track.addEventListener('sample', (event) => {
ws.send(event.sample.buffer); // ๋ฌด๊ฑฐ์ด ๋ฏธ๋์ด ๋ฐ์ดํฐ๋ฅผ ์๋ฒ ๊ฒฝ์ ๋ก ์ ์ก
});
});
WebSocket์ ํ ์คํธ ๋๋ ์ด์ง ๋ฐ์ดํฐ ๋ฑ์ธ ๋ฉ์์ง ํฌ๋งท ์ ์ก์ ์ต์ ํ๋ผ ์์ต๋๋ค. ๋ค์ ๋งํด, ๋ ๋ง์ ๊ธฐ์ ์ ์น์ ์ฌ์ฉํ๊ธฐ ์ํด ๊ณ ํ์ง ์์ ๋ฐ ์์ฑ ๋ฐ์ดํฐ ๋ฑ์ ๋ด์ ํ์ ํ์๋ ์ค์๊ฐ ์์ฑ ํตํ๋ฅผ ์ง์ํด์ผํ๋๋ฐ, WebSocket์ ๊ณ ํ์ง ๋ฏธ๋์ด ์คํธ๋ฆฌ๋ฐ์๋ ์ ํฉํ์ง ์์ต๋๋ค.
๋ค์ ๋งํด, ๊ทธ ๋ฌด๊ฑฐ์ด ๋ฐ์ดํฐ๋ฅผ ์ต์ ํ๋ ์์ด ์๋ฒ ๊ฒฝ์ ๋ฅผ ๊ฑฐ์น๋ค๋ ๊ฒ ์์ฒด๊ฐ ๋นํจ์จ์ ์ด๋ผ๋ ๊ฒ๋๋ค.
class WebSocketConnection {
constructor() {
this.ws = null;
this.reconnectAttempts = 0;
}
connect() {
this.ws = new WebSocket('wss://example.com');
// ๋คํธ์ํฌ ๋ณํ ๋์์ด ์ ํ์
this.ws.onclose = () => {
// ๋จ์ ์ฌ์ฐ๊ฒฐ ์๋๋ง ๊ฐ๋ฅ
this.reconnect();
};
}
// ์ ํ์ ์ธ ๋คํธ์ํฌ ๋์
reconnect() {
if (this.reconnectAttempts < 5) {
setTimeout(() => {
this.connect();
}, 1000 * Math.pow(2, this.reconnectAttempts));
}
}
}
WebSocket์ TCP ๊ธฐ๋ฐ์ผ๋ก ์ค๊ณ๋์ด ์์ด, ๋คํธ์ํฌ ํ๊ฒฝ ๋ณํ์ ๋ํ ์ ์๋ ฅ์ด ๋ถ์กฑํฉ๋๋ค. ์๋ฅผ ๋ค์๋ฉด, ๋ชจ๋ฐ์ผ ํ๊ฒฝ์์ ๋คํธ์ํฌ๊ฐ Wi-Fi์์ LTE๋ก ์ ํ๋ ๊ฒฝ์ฐ ์ฐ๊ฒฐ์ด ๋๊ธฐ๊ธฐ ์ฝ์ต๋๋ค.
์ด๋ฌํ WebSocket์ ๋จ์ ๋ค์ ๋ค์ ์ธ๋์ ํ์์ฑ์ ๊ฐ์กฐํ๋ ์ด์ ๊ฐ ๋์ต๋๋ค. ํนํ ์๋ฒ ํต์ ์ด ํ์์๋ ์น์ด๋ ๊ณ ํ์ง ์ค์๊ฐ ๋ฏธ๋์ด ์ ์ก์ด ํ์ํ ํ๊ฒฝ์์๋ ์ด๋ฌํ ๋จ์ ๋ค์ด ๋๋์ฑ ๋ถ๊ฐ๋์ต๋๋ค.
2010๋ ๋ ์ด๋ฐ, Google์ ์น์์ ์ค์๊ฐ ํต์ ์ P2P ๋ฐฉ์์ผ๋ก ๊ตฌํํ ์ ์๋๋ก ํ๋ ์๋ก์ด ํ๋กํ ์ฝ์ ๋ฐํํ์ต๋๋ค. ์ด ํ๋กํ ์ฝ์ด ๋ฐ๋ก **WebRTC(Web Real-Time Communication)**์ ๋๋ค.
WebRTC๋ WebSocket์ด ํด๊ฒฐํ์ง ๋ชปํ ๋ฌธ์ ๋ค์ ๊ทน๋ณตํ๊ธฐ ์ํด ๋ฑ์ฅํ์ต๋๋ค. ํนํ, ์ค์๊ฐ์ผ๋ก ๊ณ ํ์ง ๋ฏธ๋์ด ์ ์กํ๋ ๊ธฐ์ ๊ณผ P2P ํต์ ์ ์ง์ํ๋ WebRTC๋ ์น ์์์์ ์ค์๊ฐ ํต์ ์ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ๊ตฌํํ๊ธฐ ์ํ ๊ธฐ์ ๋ก ์ฃผ๋ชฉ๋ฐ์์ต๋๋ค.
- ํ๋ฌ๊ทธ์ธ ์์กด์ฑ ์ ๊ฑฐ: ๊ธฐ์กด์๋ Flash๋ Silverlight ๊ฐ์ ํ๋ฌ๊ทธ์ธ ํตํด ์ค์๊ฐ ํต์ ์ ๊ตฌํ, ํ์ง๋ง ์ถ๊ฐ ์ค์น๊ฐ ํ์ํ๊ณ ๋ณด์ ๋ฌธ์ ๋ฐ์ ์ฆ๊ฐ.
- ์ค์ ์๋ฒ ๊ฒฝ์ ๋ก ์ธํ ์ง์ฐ: ์ค์ ์๋ฒ๋ฅผ ํตํ ๋ฐ์ดํฐ ์ค๊ณ๋ก ์ธํด ์ง์ฐ ๋ฐ์, ์๋ฒ ๋ฆฌ์์ค ์๋ชจ ์ฆ๊ฐ. ์๋ฒ ์์ด ํด๋ผ์ด์ธํธ ๊ฐ ์ง์ ํต์ ์ด ๊ฐ๋ฅํ ํ๋กํ ์ฝ์ด ํ์ํด์ก์.
- ๋์ ๋์ญํญ ๋น์ฉ: ๊ณ ํ์ง ๋ฏธ๋์ด ์ ์ก์ ์ํ, ๋คํธ์ํฌ ๋์ญํญ์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๋ ๋ฏธ๋์ด ์ ์ก ์ต์ ํ ๊ธฐ๋ฅ ํ์.
๊ทธ๋์ 2011๋
, Google์ Global IP Solutions์ ์ธ์ํ๊ณ WebRTC ํ๋ก์ ํธ๋ฅผ ์คํ์์ค๋ก ๊ณต๊ฐํ๋ฉด์ ๋ณธ๊ฒฉ์ ์ธ ๊ฐ๋ฐ์ด ์์๋์์ต๋๋ค.
WebRTC๋ ๊ธฐ์กด์ ์ค์ ์๋ฒ ๋ฐฉ์(e.g. Client โ Server โ Client
)์ **P2P ๋ฐฉ์(e.g. Client โโ Client
)**์ผ๋ก ๋ฐ์ ์์ผ ์ค์๊ฐ ๋ฐ์ดํฐ ์ ์ก์ ํจ์จํํ์ต๋๋ค. (๋ฌผ๋ก ์ฐ๊ฒฐ์ ์ํ ์ต์ํ์ ์๊ทธ๋๋ง ์๋ฒ๊ฐ ํ์ํ๊ธด ํ์ง๋ง์)
-
์๋ํ๋ ๋คํธ์ํฌ ์ฒ๋ฆฌ
- ICE(Interactive Connectivity Establishment) ํ๋ ์์ํฌ๋ฅผ ํตํ ์ต์ ๊ฒฝ๋ก ์๋ ์ ํ.
- NAT ํต๊ณผ ์๋ ์ฒ๋ฆฌ.
- ํด๋ผ์ด์ธํธ ๊ฐ ์ฐ๊ฒฐ์ ์ํํ๊ฒ ์ค์ ๊ฐ๋ฅ.
- ๋คํธ์ํฌ ๋ณํ์ ๋์ ๋์.
-
์ต์ ํ๋ ๋ฏธ๋์ด ์ฒ๋ฆฌ
- ์๋ ๋นํธ๋ ์ดํธ ์กฐ์ .
- ๋คํธ์ํฌ ์ํ์ ๋ง์ถฐ ๋ฏธ๋์ด ํ์ง ์กฐ์ .
- ํจํท ์์ค ๋ณต๊ตฌ ๋ฐ ์ง์ฐ ์ต์ํ ๊ธฐ๋ฅ์ ์ ๊ณต.
- ์์ฑ ํตํ, ํ์ ํ์ ๋ฑ ์ค์๊ฐ ํต์ ์์ ๋์ ํ์ง์ ์ ์ง.
- ์๋ ๋นํธ๋ ์ดํธ ์กฐ์ .
-
ํตํฉ๋ ๋ณด์
- ๊ธฐ๋ณธ์ ์ผ๋ก DTLS/SRTP ์ํธํ.
- ์ธ์ฆ์ ๊ธฐ๋ฐ ๋ณด์.
- ์ค๊ฐ์ ๊ณต๊ฒฉ ๋ฐฉ์ง.
-
๋ธ๋ผ์ฐ์ ๋ค์ดํฐ๋ธ ์ง์
- ํ๋ฌ๊ทธ์ธ ์๋ ์ค์๊ฐ ํต์
- ํ์คํ๋ API.
- Chrome, Firefox, Safari ๋ฑ ํฌ๋ก์ค ๋ธ๋ผ์ฐ์ ๊ฐ๋ฅ.
WebRTC๋ ์ด์ ๊ฐ์ ํน์ง๋ค ๋๋ถ์ ์ค์๊ฐ ์ปค๋ฎค๋์ผ์ด์ ์ ํ์๋ก ํ๋ ์ ํ๋ฆฌ์ผ์ด์ (ํ์ ํ์, ํ์ผ ๊ณต์ , ์ค์๊ฐ ๊ฒ์ ๋ฑ)์์ ํจ์จ์ ์ธ P2P ์ฐ๊ฒฐ๊ณผ ๊ณ ํ์ง ๋ฏธ๋์ด ์ ์ก์ ๊ตฌํํ ์ ์๋ ์ค์ํ ๊ธฐ์ ๋ก ์๋ฆฌ ์ก์์ต๋๋ค.
๋ง๋ฅ๊ฐ์ ๋ณด์ด์ง๋ง ๋จ์ ๋ ์กด์ฌํฉ๋๋ค. ๋คํธ์ํฌ ๋ฐ NAT ๋ฌธ์ (ICE๋ก ์ํ ๊ฐ๋ฅ), ๋คํธ์ํฌ ๋์ญํญ ๊ด๋ จ ์ฑ๋ฅ ๋ฌธ์ , ๋ณต์กํ ๊ตฌํ ๋ฐ ์ค์ , P2P ์ฐ๊ฒฐ์ ์ํ ํ์ฅ์ฑ ๋ฌธ์ (SFU๋ MCU๋ก ์ํ ๊ฐ๋ฅ), ๊ตฌํ ๋ธ๋ผ์ฐ์ ๋ฏธ์ง์ ๋ฑ์ ๋จ์ ์ด ์๊ธด ํฉ๋๋ค.
์ง๊ธ๊น์ง ์น ํต์ ์ ๋ณํ๋ฅผ ์ดํด๋ดค์ต๋๋ค. HTTP์ ํ๊ณ๋ถํฐ P2P ํต์ ๊น์ง ๋ง์ด์ฃ . ๊ธ์ ์ ๋ณด์ ๋ ์๋์ด๋ผ๋ฉด ์๊ฒ ์ง๋ง ๊ฐ๊ฐ์ ๊ธฐ์ ์ ์ฅ๋จ์ ์ด ์์ด ๋์๊ฒ ๋ง๋ ๊ธฐ์ ์ ์ ํํ๋ ๊ฒ์ด ์ค์ํ ๊ฒ์ ๋๋ค.
์๋ฐ ๊ฒํฅ๊ธฐ, ๋ฐ์ชฝ์ง๋ฆฌ ์๋ฐฉํฅ ํต์ .
- ๋ฌธ์ ๊ณต์ ์ค์ฌ์ ๋จ๋ฐฉํฅ ํต์ ์์ ์์.
- Polling๊ณผ Long Polling์ผ๋ก ์ค์๊ฐ์ฑ ๋ชจ๋ฐฉ.
- ํ์ง๋ง ๊ทผ๋ณธ์ ์ธ ํ๊ณ ์กด์ฌ.
์๋ก์ ํด๋ผ์ด์ธํธ ๋ฐ์ดํฐ๋ฅผ ์ค๊ฐํด์ฃผ๋ ์๋น ์๋ฒ.
- ์ง์ ํ ์๋ฐฉํฅ ํต์ ์คํ.
- ๋จ์ผ ์ฐ๊ฒฐ์ ํตํ ํจ์จ์ฑ ํฅ์.
- ์ค์๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ธฐ๋ฐ ๋ง๋ จ.
- ๊ทธ๋ฌ๋ ์๋ฒ ์ค์ฌ ์ํคํ ์ฒ์ ํ๊ณ ์กด์ฌ.
- P2P ๊ธฐ๋ฐ์ ํด๋ผ์ด์ธํธ ์ง์ ํต์ ์คํ.
- ๋ฏธ๋์ด ์คํธ๋ฆฌ๋ฐ ์ต์ ํ.
- ๋ณด์๊ณผ ์ฑ๋ฅ์ ๊ท ํ.
์ด์จ๋ 2, 3๋ฒ ๋ ๊ธฐ์ ์ ๋ฑ์ฅ์ผ๋ก, ์น์ ๋จ์ํ ๋ฌธ์ ๊ณต์ ๋ฅผ ๋์ด ํ๋ถํ ์ค์๊ฐ ์ํธ์์ฉ์ด ๊ฐ๋ฅํ ํ๋ซํผ์ผ๋ก ์งํํ์ต๋๋ค. WebSocket๊ณผ WebRTC๋ ๊ฐ๊ธฐ ๋ค๋ฅธ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ค๊ณ๋์์ผ๋ฉฐ, ํ๋ ์น ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ค์ ์๋ฒ ๊ธฐ๋ฐ์ ๋ฉ์์ง๊ณผ P2P ๋ฏธ๋์ด ์ ์ก์ด๋ผ๋ ์ํธ ๋ณด์์ ์ธ ์ญํ ์ ์ํํ๊ณ ์์ต๋๋ค. ์์ผ๋ก๋ ์น์ ๋์ฑ ์งํํด ๋ง์ ์ญํ ์ ๋ด๋นํ ์ ์์ ๊ฒ์ ๋๋ค.
๋ค์ ๊ธ์์๋ ์ง์ WebRTC๋ฅผ ์จ๋ณด๋ฉฐ ๋ฅ๋ค์ด๋ธํด๋ณด๋ ์๊ฐ์ ๊ฐ์ ธ๋ณผ ๊ฒ ๊ฐ์ต๋๋ค. ๊ธฐ๋ํด์ฃผ์ธ์!@@
- ๐ Polling / Long Polling / Server Sent Event / WebSocket ์ ๋ฆฌ
- [Web] ์น ์์ผ(Web Socket)์ด๋? ๋ฑ์ฅ ๋ฐฐ๊ฒฝ๊ณผ ๋ชฉ์ , ๋์ ๋ฐฉ์ (feat. Polling, Long polling, Server-Sent Event)
- ์นด์นด์คํก ์์คํ ๋์์ธ | WebSocket | ๋ฉ์์ง ํ | SQL vs NoSQL
- JAVASCRIPT.INFO ๋คํธ์ํฌ ์์ฒญ
- 2008๋ TCP ์ฐ๊ฒฐ ๊ด๋ จ ๋ ผ์
- RFC 6455
- WebSockets Demystified, Part 1: Understanding the Protocol
- ๋คํธ์ํฌ ๊ฐ๋ตํ ์ ์ : IP, TCP/UDP, HTTP(S)
- WebRTC? WebSockets? 5๋ถ ๊ฐ๋ ์ ๋ฆฌ!
- WebRTC Mozilla
- WebRTC ๊ณต์ ๋ฌธ์
- WebRTC RFC 8835
- 1. ๊ฐ๋ฐ ํ๊ฒฝ ์ธํ ๋ฐ ํ๋ก์ ํธ ๋ฌธ์ํ
- 2. ์ค์๊ฐ ํต์
- 3. ์ธํ๋ผ ๋ฐ CI/CD
- 4. ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์์ด Canvas ๊ตฌํํ๊ธฐ
- 5. ์บ๋ฒ์ค ๋๊ธฐํ๋ฅผ ์ํ ์์ CRDT ๊ตฌํ๊ธฐ
-
6. ์ปดํฌ๋ํธ ํจํด๋ถํฐ ์น์์ผ๊น์ง, ํจ์จ์ ์ธ FE ์ค๊ณ
- ์ข์ ์ปดํฌ๋ํธ๋ ๋ฌด์์ธ๊ฐ? + Headless Pattern
- ํจ์จ์ ์ธ UI ์ปดํฌ๋ํธ ์คํ์ผ๋ง: Tailwind CSS + cn.ts
- Tailwind CSS๋ก ๋์์ธ ์์คํ ๋ฐ UI ์ปดํฌ๋ํธ ์ธํ
- ์น์์ผ ํด๋ผ์ด์ธํธ ๊ตฌํ๊ธฐ: React ํ๊ฒฝ์์ ํจ์จ์ ์ธ ์น์์ผ ์ํคํ ์ฒ
- ์น์์ผ ํด๋ผ์ด์ธํธ ์ฝ๋ ๋ถ์ ๋ฐ ๊ณต์
- 7. ํธ๋ฌ๋ธ ์ํ ๋ฐ ์ฑ๋ฅ/UX ๊ฐ์
- 1์ฃผ์ฐจ ๊ธฐ์ ๊ณต์
- 2์ฃผ์ฐจ ๋ฐ๋ชจ ๋ฐ์ด
- 3์ฃผ์ฐจ ๋ฐ๋ชจ ๋ฐ์ด
- 4์ฃผ์ฐจ ๋ฐ๋ชจ ๋ฐ์ด
- 5์ฃผ์ฐจ ๋ฐ๋ชจ ๋ฐ์ด
- WEEK 06 ์ฃผ๊ฐ ๊ณํ
- WEEK 06 ๋ฐ์ผ๋ฆฌ ์คํฌ๋ผ
- WEEK 06 ์ฃผ๊ฐ ํ๊ณ