FastAPI로 실시간 채팅 서버 구현하기

FastAPI는 Python으로 웹 애플리케이션과 API를 빠르게 개발할 수 있는 고성능 웹 프레임워크입니다. 이번 블로그 포스트에서는 FastAPI를 사용하여 실시간 채팅 서버를 구현하는 방법에 대해 알아보겠습니다.

환경 설정

먼저, FastAPI를 설치하고 채팅 서버를 구현하기 위해 필요한 추가 패키지들을 설치해야 합니다. 아래의 명령을 사용하여 필요한 패키지들을 설치할 수 있습니다.

pip install fastapi uvicorn python-socketio

기본 애플리케이션 구조

FastAPI에서는 기본 애플리케이션 구조를 작성해야 합니다. 이를 위해 main.py라는 파일을 생성하고 다음과 같이 코드를 작성합니다.

from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse
import uvicorn

app = FastAPI()

app.mount("/static", StaticFiles(directory="static"), name="static")

@app.get("/", response_class=HTMLResponse)
def get_index():
    return """
    <html>
        <head>
            <title>Real-time Chat</title>
            <script src="/static/chat.js"></script>
        </head>
        <body>
            <h1>Welcome to Real-time Chat</h1>
            <div id="messages"></div>
            <input type="text" id="message" />
            <button onclick="sendMessage()">Send</button>
        </body>
    </html>
    """

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

위의 코드는 FastAPI 애플리케이션을 생성하고, 루트 경로(/)에 접근할 경우 index.html을 반환합니다. 추가적으로 필요한 정적 파일들은 /static 경로에 위치시킵니다.

실시간 채팅 구현

이제 실시간 채팅을 구현하기 위해 chat.js 파일을 생성하고 다음과 같이 코드를 작성합니다.

var socket = io("http://localhost:8000");

socket.on("message", function (data) {
    var messages = document.getElementById("messages");
    messages.innerHTML += "<p>" + data + "</p>";
});

function sendMessage() {
    var messageInput = document.getElementById("message");
    var message = messageInput.value;
    messageInput.value = "";

    socket.emit("message", message);
}

위의 코드는 클라이언트에서 socket.io를 사용하여 웹소켓 통신을 구현합니다. 서버로부터 메시지를 받을 때마다 메시지를 화면에 표시하고, 메시지를 보내는 함수 sendMessage()를 구현합니다.

서버 측 코드 작성

서버 측 코드에서는 FastAPI 라우터 내부에서 WebSocket 연결을 다루는 방법을 알아보겠습니다. main.py 파일에 다음 코드를 추가합니다.

import socketio

sio = socketio.AsyncServer(async_mode='fastapi')
socket_app = socketio.ASGIApp(sio)

@sio.event
async def connect(sid, environ):
    print(f"New websocket connection: {sid}")

@sio.event
async def disconnect(sid):
    print(f"Websocket Disconnected: {sid}")

@sio.event
async def message(sid, data):
    print(f"Message received: {data}")
    await sio.emit("message", data)

app.mount("/ws", socket_app)

위의 코드는 socketio를 사용하여 WebSocket 연결을 다루는 부분을 구현합니다. connect() 함수는 클라이언트가 웹소켓에 접속하였을 때 호출되며, disconnect() 함수는 웹소켓 연결이 해제되었을 때 호출됩니다. 또한, 클라이언트로부터 메시지를 받으면 message() 함수를 호출하고, 해당 메시지를 모든 클라이언트로 보내도록 합니다.

서버 실행

이제 모든 준비가 끝났습니다. 터미널에서 다음 명령을 실행하여 FastAPI 애플리케이션을 실행합니다.

uvicorn main:app --reload

브라우저에서 http://localhost:8000을 열어서 채팅 애플리케이션에 접속하고, 여러 개의 클라이언트를 열어 메시지를 주고받아 보세요.

마치며

FastAPI와 socket.io를 활용하여 실시간 채팅 서버를 구현하는 방법에 대해 알아보았습니다. FastAPI의 강력한 기능과 함께 웹소켓을 사용하여 실시간 통신을 구현하는 것은 매우 유용한 방법입니다. 이를 바탕으로 더 다양한 애플리케이션을 개발해 보세요!

#FastAPI #실시간채팅