기본 콘텐츠로 건너뛰기

[FastAPI] socket.io with fastapi_socketio (feat:python-socketio, saw: 톱 2종)

안녕하세요 클스 입니다.


팀에 하나의 제품을 개발할 때 인력이 약 15명 이상 있을 경우 react, vue, flutter등 

선택의 폭이 넓어집니다. 그런데 애매하게 5~8명이 back-end, front-end, db, infra 

전부 하면서 web, android, ios 앱을 개발하기엔 쉽지 않습니다.

우리는 무엇을 선택하면 좋을까요? 

현재 우리팀은 FastAPI, vuejs 를 기본으로 사용하고 있는데.. vuejs가 아직 react의 방대함

그리고 커뮤니티를 따라가지는 못하는  듯합니다.

확실히 react 보다는 사용하기는 제 경우는 쉬웠습니다. 사설이 길었네요~


여하튼 이번에는 웹에서 실시간으로 사용자에게 알림(시스템 변경, 작업 완료...)을 

실시간으로 전달하기위해 많이 사용하는 websocket과 socketio가 있는데

둘의 확실한 선택 기준은 서비스 환경에서 통신에 문제가 있는가 없는가에 따라 다릅니다.

socketio는 통신이 막히면 가능한 방식을 찾아서 연결해서 사용자에게 메시지를 전달합니다.

HTTP long polling 방식으로 전달을 합니다. 문제는 주기적으로  long polling를 합니다.

그리고 socketio client를 사용하면 서버가 재시작되면 자동으로 다시 연결해줍니다. 

개발자 입장에서는 확실히 좋은 기능입니다. 

그외 방기능, 브로드캐스팅, 속삭임등등 일반 채팅방을 쉽게 구현할 수 있습니다.

또한 일반적으로 kafka, redis 와 다양한 mq 서버들과 연동이 가능합니다.


1. 목표

  • 간단한 채팅방이 가능한 채팅 기능을 만들어 본다
  • fastapi에서 socketio를 많이 사용을 안 하는지? 업데이트가 잘 안되고 있어서
    github등의 예제로는 404 Not Found, 403 등의 오류가 나서 접속이 안되었다
    => 이것 때문에 쓴 글이기도 하다

2. 사용

  • socket.io 기반으로 python-socketio를 fastapi에 맞게 개발한 fastapi_socketio를 
    기반으로 한다.
  • client는 일단 html로 한다.
  • quasar에 socketio client를 추가해서 다시 만든다. 

3. 나의 선택

  • 나는 socketio를 사용하지 않을 듯하다. 이미 websocket + redis로 유사한 기능을
    개발했기도 하고
  • 하도 socketio가 좋다고 하지만, 사용성에 있어 생각보다 클리어하지 않았고
  • 무엇보다 nodejs 로 개발되었고..
  • 뭔가 뒤에서 무거운 작업을 많이 할 것도 같고..

4. 설치 및 소스

pnpm install fastapi_socketio 

FastAPI의 app.py   

app = createApp() # App 생성 이후에 socketio를 만들어 줌.

############################# socket.io fastapi-socketio BEGIN ####################################

from fastapi_socketio import SocketManager
sio = SocketManager(app=app)

app.add_route("/socket.io/", route=sio, methods=["GET", "POST"])
app.add_websocket_route("/ws/socket.io/", sio)


######### --------------------------
@app.sio.on('connect')
async def connect(sid, environ):
print('connect ', sid)

@app.sio.on('disconnect')
def disconnect(sid):
print('disconnect ', sid)

@app.sio.on('join')
async def handle_join(sid, *args, **kwargs):
print('join ', sid)

# 방 입장 이벤트 처리
@app.sio.on("enter_room")
async def handle_enter_room(sid, room):
print(f"{sid} entered room {room}")
sio.enter_room(sid, room) # 클라이언트를 지정한 방에 입장시킴

# 방에서 나가기 이벤트 처리
@app.sio.on("leave_room")
async def handle_leave_room(sid, room):
print(f"{sid} left room {room}")
sio.leave_room(sid, room) # 클라이언트를 지정한 방에서 나가게 함

@app.sio.on('message')
async def message(sid, data):
print('message ', data)
# 받은 메시지 다시 전송
    
await sio.send(f'Re2 >>>>>>> :{data}')

chat_client_socketio.html

<!DOCTYPE html>

<html lang="ko">

<head>
<meta charset="UTF-8">
<title>Chat</title>
<script src="https://cdn.socket.io/4.7.0/socket.io.min.js"></script>
<script>
// Create a socket connection 아래 transports: ['websocket', 'polling'] } 두개를 써줘야 한다.
var socket = io("ws://localhost:8001", { path: "/ws/socket.io/", transports: ['websocket', 'polling'] });
// var socket = io("http://localhost:8001", { path: "/socket.io/", transports: ['websocket', 'polling'] }
</script>
</head>

<body>
<h1>FastAPI Socket.IO Chat</h1>
<div id="chat"></div>
<input type="text" id="message" value="내 메시지" placeholder="메시지 입력..." />
<button onclick="sendMessage()">전송</button>

<!-- 방 입장 및 퇴장 버튼 -->
<input type="text" id="room" value='7번방' placeholder="방 이름 입력..." />
<button onclick="enterRoom()">방 입장</button>
<button onclick="leaveRoom()">방 퇴장</button>
<button onclick="sendMessageToRoom()">방에만 전송</button>

<script>
socket.on('message', (data) => {
const chat = document.getElementById('chat');
chat.innerHTML += `<p>${data}</p>`;
});

function sendMessage() {
const message = document.getElementById('message').value;
socket.emit('message', message);
// document.getElementById('message').value = '';
}

function sendMessageToRoom() {
const room = document.getElementById('room').value; // 방 이름 가져오기
const message = document.getElementById('message').value;

const messageData = {
message: message,
room: room
};

socket.emit('message', { message, room }); // 메시지와 방 이름 함께 전송
}

function enterRoom() {
const room = document.getElementById('room').value;
socket.emit('enter_room', room);
// document.getElementById('room').value = '';
}

function leaveRoom() {
const room = document.getElementById('room').value;
socket.emit('leave_room', room);
// document.getElementById('room').value = '';
}
</script>
</body>

</html>

* 서버 재시작 후 client가 자동 연결되는 로그


INFO:     Application startup complete.

INFO:     ('127.0.0.1', 61816) - "WebSocket /socket.io/?EIO=4&transport=websocket" [accepted]

INFO:     ('127.0.0.1', 61824) - "WebSocket /socket.io/?EIO=4&transport=websocket" [accepted]

connect  tek0e16lm0TKD5FCAAAC

connect  QrqGhNp0FnIQiF9GAAAD


* 채팅 화면



* 참고

- FastAPI,socketio,python-socketio,Quasar,websocket,fastapi_socketio,long polling,

- https://channel.io/ko/blog/tech-socketio-redis-adapter-improvement 

- https://news.hada.io/topic?id=1124 websocket 재연결 문제 해결한 라이브러리
  https://sarus.anephenix.com/

- 웹소켓으로 GIS 작업 : https://progworks.tistory.com/65



추가적으로 톱은 왜? 샀나? 애들이 어릴때 2층 침대를 샀는데, 큰애가 대학을 가면서 나가서

둘째이 독립 침대를 만들어주려고 다리를 짤라야 했다.



자르는 동영상


https://www.youtube.com/shorts/VN-hdmi_gBc


아래 제품 소개는 제가 직접 사서 써본거에요~ 목적은 애들 2층 침대가 있는데,

다리를 잘라서 단층으로 만들거에요~

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다." 


1. 길이가 좀 짧은것(20CM) : 좁은 공간 작업 + 휴대성 (캠핑+벌초)

          대건 국산 파워이지 접톱 210MM 1개, DE-903

2. 길이가 좀 긴것(30CM) : 빠른 작업

  대건 국산 파워이지 접톱 300MM 1개, DE-906

댓글

이 블로그의 인기 게시물

[quaser.dev][2014-09-14] 윈도우즈(10, 64bit)에 개발환경 설정하기

[quaser.dev][2014-09-14] 윈도우즈(10, 64bit)에 개발환경 설정하기

[2024-10-19] iPhone, iPad에서 ChatGPT로 PDF 생성시 한글 깨짐 해결 방법

iPhone, iPad에서 ChatGPT로 PDF 생성 시 한글 깨짐 해결 방법

[2025-04-16(수)] OpenAI gpt-4.1 시리즈 발표, Anthropic Claude에 대한 생각

OpenAI gpt-4.1 시리즈 발표, Anthropic Claude에 대한 생각 안녕하세요. 클스 입니다. 4/15일자로 openai가 gpt-4.1 시리즈를 발표 했습니다. 현재는 api로만 사용가능합니다. 점차 웹/앱 사용자에게 오픈 될거라 생각 됩니다. 비용상 문제로 4.1-mini, nano를 사용해서 chatbot을 만들어 보고 있습니다. 4o 시리즈 보다는 확실히 빠르고, 답변의 정확도는 올라간 것 같습니다. 앤트로픽 클로드와 비교를 많이 하는데, 업무 시스템 혹은 AI 솔루션을 개발하는 입장에서는 어떤 생태계를 제공하는가가 주요한 결정 입니다. AI관련 인력을 충분히 보유한 회사의 경우는 어떤걸 사용해도 좋을 결과를 가지겠지만 일반적인 챗봇 개발 절차를 보면 다음과 같이 볼 수 있습니다. 1. 문서를 준비한다. 대부분 pdf, text, markdown 2. 문서를 파싱해서 vectordb에 올린다.     - 별도 벡터디비 구성 필요. 어떤 db를 선택할지 고민 필요     - 어떤 Parser를 사용할지, 텍스트 오버래핑은 얼마가 적당한지 고민 필요        (회사의 문서가 워낙 많고, 다양하면 하나하나 테스트 해서 좋은걸 선택하는 것이 어렵다)     - 유사도 측정은 어떤 알고리즘을 써야할지 고민 필요     - llamaindex도 고민해야 함. 3. RAG flow를 만든다.     - langchain을 쓸지, 각 AI 벤더에서 제공하는 sdk를 쓸지 고민 필요       (대부분 락인이 되지 않으려면 langchain을 사용하면 좋지만, 벤더에 특화면 기능 적용이 늦음) 4. 챗봇 UI 앱을 만든다.     - 답변이 text 로 구성되다 보니. 그래프, 이미지등 복합적인 컨텐츠를 재배치 하여 표현하기 상당히 어렵네요. (이건 제가 실력이 모자라서 .. 패스) ...