WebSocket

๐ŸŒ WebSocket ์„œ๋ฒ„ ๊ตฌ์ถ• ๊ฐ€์ด๋“œ ๐Ÿš€


1๏ธโƒฃ WebSocket์ด๋ž€?

WebSocket์€ ๋ธŒ๋ผ์šฐ์ €์™€ ์„œ๋ฒ„ ๊ฐ„ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ์œ„ํ•œ ํ”„๋กœํ† ์ฝœ์ž…๋‹ˆ๋‹ค.
๊ธฐ์กด์˜ HTTP๋Š” ์š”์ฒญ-์‘๋‹ต ๋ฐฉ์‹์ด์ง€๋งŒ, WebSocket์€ ์„œ๋ฒ„๊ฐ€ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋Š” ํŠน์ง•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

โœ… ์ฃผ์š” ํŠน์ง•

  • ์–‘๋ฐฉํ–ฅ ํ†ต์‹  ์ง€์› (์„œ๋ฒ„ โ†’ ํด๋ผ์ด์–ธํŠธ, ํด๋ผ์ด์–ธํŠธ โ†’ ์„œ๋ฒ„)
  • Persistent Connection (์—ฐ๊ฒฐ ์œ ์ง€)
  • ๋‚ฎ์€ ๋„คํŠธ์›Œํฌ ์˜ค๋ฒ„ํ—ค๋“œ (ํ—ค๋”๊ฐ€ ์ ์Œ)
  • ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ „์†ก ๊ฐ€๋Šฅ (์ฑ„ํŒ…, ๊ฒŒ์ž„, ์ฃผ์‹ ๋ฐ์ดํ„ฐ ๋“ฑ์— ํ™œ์šฉ)

2๏ธโƒฃ WebSocket ์„œ๋ฒ„ ๊ตฌ์ถ• (Python + FastAPI)

Python์˜ FastAPI + WebSockets ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ„๋‹จํ•œ WebSocket ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๐Ÿ”น 1. WebSocket ์„œ๋ฒ„ ์„ค์น˜

pip install fastapi uvicorn

3๏ธโƒฃ WebSocket ์„œ๋ฒ„ ์ฝ”๋“œ (FastAPI)

๐Ÿ“‚ websocket_server.py

from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse
import uvicorn

app = FastAPI()

# ํด๋ผ์ด์–ธํŠธ ๊ด€๋ฆฌ
clients = []

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()  # WebSocket ์—ฐ๊ฒฐ ์ˆ˜๋ฝ
    clients.append(websocket)
    try:
        while True:
            data = await websocket.receive_text()  # ํด๋ผ์ด์–ธํŠธ๋กœ๋ถ€ํ„ฐ ๋ฉ”์‹œ์ง€ ์ˆ˜์‹ 
            for client in clients:
                await client.send_text(f"Message: {data}")  # ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ์— ๋ฉ”์‹œ์ง€ ์ „์†ก
    except:
        clients.remove(websocket)

# ๊ฐ„๋‹จํ•œ HTML ํŽ˜์ด์ง€ ์ œ๊ณต
@app.get("/")
async def home():
    return HTMLResponse("""
    <html>
        <head>
            <script>
                var ws = new WebSocket("ws://localhost:8000/ws");
                ws.onmessage = function(event) {
                    document.getElementById("output").innerHTML += event.data + "<br>";
                };
                function sendMessage() {
                    var input = document.getElementById("message");
                    ws.send(input.value);
                    input.value = "";
                }
            </script>
        </head>
        <body>
            <h2>WebSocket Chat</h2>
            <input id="message" type="text">
            <button onclick="sendMessage()">Send</button>
            <div id="output"></div>
        </body>
    </html>
    """)

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)

4๏ธโƒฃ WebSocket ์„œ๋ฒ„ ์‹คํ–‰

python websocket_server.py

๐ŸŒ ๋ธŒ๋ผ์šฐ์ €์—์„œ ์‹คํ–‰
http://localhost:8000/ ์— ์ ‘์† ํ›„ ๋ฉ”์‹œ์ง€๋ฅผ ์ž…๋ ฅํ•˜๋ฉด WebSocket์„ ํ†ตํ•ด ์‹ค์‹œ๊ฐ„์œผ๋กœ ์†ก์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


5๏ธโƒฃ WebSocket ํด๋ผ์ด์–ธํŠธ ํ…Œ์ŠคํŠธ (Python)

์•„๋ž˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด WebSocket ์„œ๋ฒ„์— ๋ฉ”์‹œ์ง€๋ฅผ ์ „์†กํ•˜๊ณ  ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import asyncio
import websockets

async def test_websocket():
    uri = "ws://localhost:8000/ws"
    async with websockets.connect(uri) as websocket:
        await websocket.send("Hello WebSocket!")
        response = await websocket.recv()
        print(f"Received: {response}")

asyncio.run(test_websocket())

6๏ธโƒฃ WebSocket ๋ฐฉํ™”๋ฒฝ ์„ค์ •

โœ… WebSocket์€ ๊ธฐ๋ณธ์ ์œผ๋กœ 8000๋ฒˆ ํฌํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋ฐฉํ™”๋ฒฝ์„ ์—ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”น UFW (Ubuntu/Debian)

sudo ufw allow 8000/tcp

๐Ÿ”น firewalld (CentOS/RHEL)

sudo firewall-cmd --permanent --add-port=8000/tcp
sudo firewall-cmd --reload

7๏ธโƒฃ WebSocket ์„œ๋ฒ„ ๋ฐฐํฌ (Gunicorn + Uvicorn)

FastAPI WebSocket ์„œ๋ฒ„๋ฅผ Gunicorn + Uvicorn์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”น 1. Gunicorn ์„ค์น˜

pip install gunicorn

๐Ÿ”น 2. Gunicorn์„ ์‚ฌ์šฉํ•˜์—ฌ ์‹คํ–‰

gunicorn -w 4 -k uvicorn.workers.UvicornWorker websocket_server:app --bind 0.0.0.0:8000

โœ… -w 4: ์›Œ์ปค ํ”„๋กœ์„ธ์Šค 4๊ฐœ ์‚ฌ์šฉ
โœ… -k uvicorn.workers.UvicornWorker: Uvicorn ๊ธฐ๋ฐ˜์˜ Gunicorn ์›Œ์ปค ์‚ฌ์šฉ


8๏ธโƒฃ WebSocket ๋กœ๊ทธ ๋ฐ ๋ฌธ์ œ ํ•ด๊ฒฐ

๐Ÿ”น 1. WebSocket ๋กœ๊ทธ ํ™•์ธ

sudo journalctl -u websocket_server -f

๐Ÿ”น 2. ํฌํŠธ ์‚ฌ์šฉ ์—ฌ๋ถ€ ํ™•์ธ

netstat -tulnp | grep 8000

๐Ÿ”น 3. WebSocket ์—ฐ๊ฒฐ ํ…Œ์ŠคํŠธ

curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" http://localhost:8000/ws

9๏ธโƒฃ ๊ฒฐ๋ก  ๐Ÿš€

โœ… WebSocket์„ ์‚ฌ์šฉํ•˜๋ฉด ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โœ… FastAPI + Uvicorn์„ ํ™œ์šฉํ•˜๋ฉด Python์œผ๋กœ ๊ฐ„๋‹จํ•˜๊ฒŒ WebSocket ์„œ๋ฒ„๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
โœ… Gunicorn๊ณผ ํ•จ๊ป˜ ๋ฐฐํฌํ•˜๋ฉด ์„ฑ๋Šฅ์„ ๋”์šฑ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ“š ์ถ”๊ฐ€ ์ž๋ฃŒ
1๏ธโƒฃ FastAPI WebSocket ๊ณต์‹ ๋ฌธ์„œ
2๏ธโƒฃ WebSocket ํ”„๋กœํ† ์ฝœ ๊ณต์‹ ๋ฌธ์„œ
3๏ธโƒฃ Gunicorn + Uvicorn ์„ค์ •

RSS Feed
๋งˆ์ง€๋ง‰ ์ˆ˜์ •์ผ์ž