[FastAPI] SocketIO 마운트해서 사용하기
"사용자 2명 : 챗봇" 을 구현하기 위해
room 기능을 제공하는 SocketIO를 사용하기로 했다.
SocketIO는 WebSocket을 기반으로 하는 라이브러리지만
WebSocket에만 의존하지 않고 필요한 경우 다른 전송 방법 (ex_폴링)을 사용할 수 있다.
또한 WebSocket보다 고급 기능을 제공한다.
챗봇 엔진은 FastAPI를 사용하기로 했다.
따라서 SocketIO를 FastAPI에 mount해서 사용해야 한다.
# sockets.py
import socketio
sio_server = socketio.AsyncServer(
async_mode = 'asgi',
cors_allowed_origins=[]
)
sio_app = socketio.ASGIApp(
socketio_server=sio_server,
socketio_path='/ws/socket.io'
)
@sio_server.on('connect')
async def connect(sid, environ, auth):
print(f'{sid}: connected')
@sio_server.on('disconnect')
async def disconnect(sid):
print(f'{sid}: disconnected')
# server.py
from fastapi import FastAPI
from sockets import sio_app
app = FastAPI()
@app.get('/')
async def home():
return {'message': 'Hello World'}
app.mount('/ws', app=sio_app)
FastAPI에서 mount는 특정 경로에 외부 WSGI 또는 ASGI 애플리케이션을 연결하는 기능을 의미한다.
즉, FastAPI 애플리케이션의 일부 경로를 외부 애플리케이션에 위임하는 것이다.
이를 통해 FastAPI 애플리케이션에서는 HTTP 요청을 처리하고
특정 경로에서는 외부 애플리케이션이 요청을 처리하도록할 수 있다.
위 코드는
모든 '/ws'로 시작하는 경로에 대한 WebSocket 요청을 외부 애플리케이션인 'sio_app'에 위임하여 처리하는 것이다.
여기서 주의할 점은 경로 설정이다.
SocketIO 앱 (socketio.ASGIApp)을 마운트할 때 사용하는 경로에 따라서 클라이언트에서 연결을 시도하는 경로가 달라질 수 있다.
app.mount('/ws', socketio.ASGIApp(sio))를 사용하면 클라이언트는 /ws/socket.io 경로로 연결 해야한다.
socketio.ASGIApp의 기본 socketio_path가 'socket.io'이기 때문이다.
참고로 python-socketio 라이브러리에서
@sio.on('event_name')와 @sio.event는 동일한 기능이다.
두 가지 방식으로 이벤트 핸들러를 등록할 수 있으며
단지, @sio.on('event_name')방식은 이벤트 이름을 명시적으로 지정하는 반면
@sio.event방식은 핸들러 함수의 이름을 이벤트 이름으로 사용한다.
테스트를 위해 Postman을 사용했지만 제대로 동작하지 않았다.
문서에서 제공하는 python-socketio[asyncio_client]를 사용해 클라이언트를 생성했다.
# client.py
import socketio
import asyncio
sio_client = socketio.AsyncClient()
@sio_client.event
async def connect():
print('I\'m connected')
@sio_client.event
async def disconnect():
print('I\'m disconnected')
async def main():
await sio_client.connect(
url='http://localhost:8000/ws',
socketio_path='/ws/socket.io'
)
await sio_client.disconnect()
asyncio.run(main())
FastAPI를 실행하자
uvicorn server:app --host 0.0.0.0 --port 8000 --reload
이후 client를 실행하면 아래와 같다.
다음 글은 room 기능 구현!
'WebFramework > [FastAPI]' 카테고리의 다른 글
[FastAPI] SocketIO Admin UI (0) | 2024.01.25 |
---|---|
[FastAPI] room 기능 구현 및 worker간 공유 (RabbitMQ) (0) | 2024.01.24 |
[FastAPI] BackgroundTasks, Celery (0) | 2024.01.09 |
[FastAPI] 중첩된 JSON 모델(Nested JSON Models) 사용 (0) | 2023.09.25 |
[FastAPI] SQLAlchemy 요소 (0) | 2023.08.08 |