๊ณต์ ์น์ฌ์ดํธ : https://socket.io/
Socket.IO๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ(๋ธ๋ผ์ฐ์ )๊ฐ ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ์ ์ ์๊ฒ ํด์ฃผ๋ ํต์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
๋ณดํต Http์์ฒญ์ ํ๋ฒ ๋ณด๋ด๋ฉด ๋์ด์ง๋ง, socket.io๋ ์ฐ๊ฒฐ์ ๊ณ์ ์ ์งํด์ ์๋ฒ๊ฐ ๋จผ์ ๋ง์ ๊ฑธ ์๋ ์๋ค. ์ด ์ฐ๊ฒฐ์ ์์ผ(Socket)์ด๋ผ ๋ถ๋ฅด๊ณ , ์ด ์์ผ์ด ์ฐ๊ฒฐ๋๊ณ ๋๊ธฐ๊ณ ๋ฉ์์ง๋ฅผ ๋ฐ์ ๋ ๋ง๋ค ์ด๋ฒคํธ(event)๊ฐ ๋ฐ์๋๋ค.
Http๋ ์ง๋ฌธ-๋ต๋ณ์ ๊ตฌ์กฐ,
Socket์ ๊ณ์ ๋ํํ๋ **์ฑํ ๋ฐฉ**์ ๊ตฌ์กฐ
1. Socket.IO๋
์น ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ์ ์ค์๊ฐ(Real-time), ์๋ฐฉํฅ(Bidirectional), ์ด๋ฒคํธ ๊ธฐ๋ฐ(Event-based) ํต์ ์ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
์น์์ ์ฑํ , ์๋ฆผ, ์ค์๊ฐ ํ์ ๋ฌธ์ ๋ฑ ๋ฐ์ดํฐ๊ฐ ๋์์์ด ์ฃผ๊ณ ๋ฐ์์ ธ์ผ ํ๋ ์๋น์ค๋ฅผ ๋ง๋ค ๋ ๊ฐ์ฅ ๋๋ฆฌ ์ฌ์ฉ๋๋ ๋๊ตฌ ์ค ํ๋์ด๋ค.
2. Socket.IO์ ํน์ง
socket.io๋ ์น์์ผ(WebSocket)์ด๋ผ๋ ํต์ ํ๋กํ ์ฝ์ ๋ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๋๋ก '์ฌ์ฉํ๊ธฐ ํธํ ์ธํฐํ์ด์ค'์ '์ฐ๊ฒฐ์ ์์ ์ฑ์ ๋์ด๋ ๋ถ๊ฐ ๊ธฐ๋ฅ๋ค'์ ์ถ๊ฐํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ผ๊ณ ํ๋ค.
- ์ค์๊ฐ ์๋ฐฉํฅ ํต์ : ํด๋ผ์ด์ธํธ(๋ธ๋ผ์ฐ์ ) - ์๋ฒ๊ฐ ์ธ์ ๋ ์ง ์๋ก์๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ผ ์ ์๋ค.
- ์๋ ์ฌ์ฐ๊ฒฐ ๋ฐ ํด๋ฐฑ(Fallback) : ํต์ ์ด ๋์ด์ ธ๋ ์๋์ผ๋ก ์ฌ์ฐ๊ฒฐ์ ์๋ํ๋ฉฐ, ์ฌ์ฉํ๋ ๋ธ๋ผ์ฐ์ ๋ ๋คํธ์ํฌ ํ๊ฒฝ์ด ์น์์ผ์ ์ง์ํ์ง ์์ ๋ ์๋์ผ๋ก ๋ค๋ฅธ ํต์ ๊ธฐ์ ๋ก ์ ํํ๋ค(Fallback). ์ด ๋์ ์ด๋ค ํ๊ฒฝ์์๋ ์ค์๊ฐ ํต์ ์ ๋ณด์ฅํ๋ค. ์๋์ ๊ฐ์ ์ฌ๋ฌ ๊ธฐ์ ์ ์ฌ์ฉํ๋ค.
- HTTP long-polling
- WebSocket
- WebTransport
- ์ด๋ฒคํธ ๊ธฐ๋ฐ : ๋ฐ์ดํฐ๋ ํน์ ์ด๋ฒคํธ ์ด๋ฆ๊ณผ ํจ๊ป ์ฃผ๊ณ ๋ฐ์์ง๋๋ฐ, ์๋ฅผ ๋ค์ด socket.emit('chat message', '์๋ ')์ฒ๋ผ ์ด๋ฒคํธ๋ฅผ ์ ์กํ๊ณ , socket.on('chat message', ()=>{})๋ก ํด๋น ์ด๋ฒคํธ๋ฅผ ์์ ํ๋ค.
3. Socket.IO์ ๊ตฌ์ฑ ์์
Socket.IO๋ ํด๋ผ์ด์ธํธ์ ์๋ฒ, ๋ ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋๋ค.
1๏ธโฃ ํด๋ผ์ด์ธํธ(Client-side)
์ฃผ๋ก ์น ๋ธ๋ผ์ฐ์ ์์ ์ฌ์ฉ๋๋ฉฐ JavaScript์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ socket.io-client๋ฅผ ์ฌ์ฉํ๋ค.
์๋ฒ์ ์ฐ๊ฒฐํ๊ณ , ์ด๋ฒคํธ๋ฅผ ๋ณด๋ด๊ฑฐ๋ ์๋ฒ๋ก๋ถํฐ ์ด๋ฒคํธ๋ฅผ ๋ฐ๋๋ค.
Socket.IO - client์ ๊ธฐ๋ณธ ๊ตฌ์กฐ
import { io } from 'socket.io-client'
// 1. ์๋ฒ ์ฐ๊ฒฐ(์ฃผ์๋ ์๋ฒ์ socket.io ์ฃผ์)
const socket = io('https://example.com', {
path: '/gateway', // ์๋ฒ ์์ผ ๊ฒฝ๋ก
auth: { userId: 'user01' }, // ์๋ฒ๋ก ๋ณด๋ผ ์ธ์ฆ ์ ๋ณด
transports: ['websocket'], // WebSocket๋ง ์ฌ์ฉ
})
// 2. ์๋ฒ์ ์ฐ๊ฒฐ๋์์ ๋ ์คํ
socket.on('connect', () => {
console.log('โ
์ฐ๊ฒฐ ์ฑ๊ณต:', socket.id)
})
// 3. ์๋ฒ๊ฐ ๋ณด๋ธ ๋ฉ์์ง๋ฅผ ๋ฐ์ ๋(๋ฉ์์ง๋ฅผ ์์ ํ์ ๋) ์คํ
socket.on('message', (msg) => {
console.log('๐ฉ ์๋ฒ๋ก๋ถํฐ ์์ :', msg)
})
// 4. ์ฐ๊ฒฐ์ด ๋์ด์ก์ ๋ ์คํ
socket.on('disconnect', () => {
console.log('๐ ์ฐ๊ฒฐ ๋๊น')
})
// 5. ์ฐ๊ฒฐ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ์ ๋ ์คํ
socket.on('connect_error', (err) => {
console.log('โ ์ฐ๊ฒฐ ์ค๋ฅ:', err.message)
})
// 6. ๋ฉ์์ง ์ ์ก
socket.emit('message', { text: '์๋
์๋ฒ!' })
- io()๋ก ์ฐ๊ฒฐ
- on('eventName', callback)์ผ๋ก ์ด๋ฒคํธ ๋ฃ๊ณ
- emit('eventName', date)๋ก ๋ฉ์์ง๋ฅผ ๋ณด๋ธ๋ค.
2๏ธโฃ ์๋ฒ(Server-side)
์ฃผ๋ก Node.js ํ๊ฒฝ์์ ์ฌ์ฉ๋๋ฉฐ ์๋ฒ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ socket.io๋ฅผ ์ค์นํ์ฌ ์ฌ์ฉํ๋ค.
ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ์ ๊ด๋ฆฌํ๊ณ , ์ด๋ฒคํธ๋ฅผ ์์ ํ๋ฉฐ ํด๋ผ์ด์ธํธ์๊ฒ ๋ฐ์ดํฐ๋ฅผ broadcast(๋์์ ์ฌ๋ฌ ํด๋ผ์ด์ธํธ์๊ฒ ์ ์ก(ํ๊ฑฐ๋ ํน์ ํด๋ผ์ด์ธํธ์๊ฒ๋ง ๋ณด๋ธ๋ค.
Socket.IO - server์ ๊ธฐ๋ณธ ๊ตฌ์กฐ
import { Server } from 'socket.io'
// 1. ์๋ฒ ์์ฑ(ํฌํธ 3000์์ WebSocket ์๋ฒ ์์)
const io = new Server(3000, {
path: '/gateway', // ํด๋ผ์ด์ธํธ๊ฐ ์ฐ๊ฒฐํ ๊ฒฝ๋ก
})
// 2. ํด๋ผ์ด์ธํธ๊ฐ ์ฐ๊ฒฐ๋๋ฉด ๋ฐ์ํ๋ ์ด๋ฒคํธ
io.on('connection', (socket) => {
console.log(`โ
ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ๋จ: ${socket.id}`)
// 2 - 1. ํด๋ผ์ด์ธํธ๊ฐ ๋ณด๋ธ ๋ฉ์์ง ์์
socket.on('message', (msg) => {
console.log('๐ฉ ํด๋ผ์ด์ธํธ๋ก๋ถํฐ ๋ฉ์์ง ์์ :', msg)
})
// 2 - 2. ํด๋ผ์ด์ธํธ์๊ฒ ๋ค์ ๋ฉ์์ง ์ ์ก
socket.emit('message', `์๋ฒ๊ฐ ์๋ตํจ : ${msg.text}`)
// 2 - 3. ์ฐ๊ฒฐ ๋๊น ์ฒ๋ฆฌ
socket.on('disconnect', () => {
console.log(`๐ ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ ์ข
๋ฃ: ${socket.id}`)
})
// 2 - 4. ์ฐ๊ฒฐ ์ค ์ค๋ฅ ์ฒ๋ฆฌ
socket.on('error', (err) => {
console.log('โ ์์ผ ์ค๋ฅ:', err)
})
})
- new Server()๋ก WebSocket ์๋ฒ๋ฅผ ์ด๊ณ ํด๋ผ์ด์ธํธ๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค
- io.on()์ผ๋ก ํด๋ผ์ด์ธํธ๊ฐ ์ฐ๊ฒฐ๋๋ฉด ์๋์ผ๋ก ํธ์ถํ๋ค
- socket.on()์ผ๋ก ํด๋ผ์ด์ธํธ๊ฐ ๋ณด๋ธ ๋ค์ํ ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ค. socket๊ฐ์ฒด๋ ์ฐ๊ฒฐ๋ ํด๋ผ์ด์ธํธ๋ฅผ ๋ํํจ
- socket.emit()์ผ๋ก ํด๋ผ์ด์ธํธ์๊ฒ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๋ค.
4. ์ ์ฒด ํ๋ฆ
- ํด๋ผ์ด์ธํธ๊ฐ io(url)๋ก ์ฐ๊ฒฐ ์์ฒญ
- ์๋ฒ io.on('connection')์์ ์ฐ๊ฒฐ ์๋ฝ - socket.id ๋ถ์ฌ
- ํด๋ผ์ด์ธํธ → ์๋ฒ: emit('message', data)
- ์๋ฒ → ํด๋ผ์ด์ธํธ : socket.emit('message', data) ๋๋ broadcast.emit
- ์ฐ๊ฒฐ ๋๊น → disconnect ์ด๋ฒคํธ ๋ฐ์
- ์ค๋ฅ ๋ฐ์ → error ์ด๋ฒคํธ ๋ฐ์
[์ฐธ๊ณ ์๋ฃ]
Socket.IO
Reliable Rest assured! In case the WebSocket connection is not possible, it will fall back to HTTP long-polling. And if the connection is lost, the client will automatically try to reconnect.
socket.io
https://share.google/1ZPNeuBDlSpa3Z24c
Socket.IO์ ์ ์ฒด: Socket.IO์ ์น์์ผ์ ๋์ผํ ๊ฐ๋ ์ผ๊น?
Socket.io ์ ์ฒด ํ ์ค๋ก ์ ๋ฆฌ
velog.io