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 ์ค์