WebSocket 실시간 채팅: FastAPI + SvelteKit 구현 - 코드픽 블로그
WebSocket 실시간 채팅: FastAPI + SvelteKit 구현
기술 가이드

WebSocket 실시간 채팅: FastAPI + SvelteKit 구현

2026년 3월 1일 46 views by 코드벤터

WebSocket 실시간 채팅: FastAPI + SvelteKit 구현 완전 가이드

실시간 채팅은 현대 웹 애플리케이션의 핵심 기능 중 하나입니다. HTTP 요청-응답 방식과 달리, WebSocket은 서버와 클라이언트 간 양방향 통신을 지속적으로 유지해 지연 없는 메시지 전달을 가능하게 합니다. 이 글에서는 Python 백엔드 프레임워크 FastAPI와 풀스택 프론트엔드 프레임워크 SvelteKit을 조합하여 실시간 채팅 애플리케이션을 처음부터 구현하는 방법을 소개합니다.


왜 FastAPI + SvelteKit인가?

항목FastAPISvelteKit
언어PythonJavaScript / TypeScript
비동기 처리asyncio 기반 네이티브 지원서버 액션 + 클라이언트 반응성
WebSocket내장 지원브라우저 WebSocket API 활용
성능Node.js급 고성능컴파일 기반 최소 번들
학습 곡선완만 (자동 문서화 포함)완만 (Svelte 문법 직관적)
실시간 UI서버 측 브로드캐스트반응형 상태 자동 업데이트

두 프레임워크 모두 개발자 경험(DX)이 뛰어나고, 서로 REST/WebSocket API로 자연스럽게 연동됩니다.


프로젝트 구조

bash
chat-app/
├── backend/
│   ├── main.py
│   └── requirements.txt
└── frontend/
    ├── src/
    │   └── routes/
    │       └── +page.svelte
    └── package.json

Step 1: FastAPI 백엔드 구현

패키지 설치

bash
pip install fastapi uvicorn websockets

ConnectionManager 구현

다중 클라이언트 연결을 관리하는 핵심 클래스입니다.

python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.middleware.cors import CORSMiddleware
from typing import List

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class ConnectionManager:
    def __init__(self):
        self.active_connections: List[WebSocket] = []

    async def connect(self, websocket: WebSocket):
        await websocket.accept()
        self.active_connections.append(websocket)

    def disconnect(self, websocket: WebSocket):
        self.active_connections.remove(websocket)

    async def broadcast(self, message: str):
        for connection in self.active_connections:
            await connection.send_text(message)

manager = ConnectionManager()

@app.websocket("/ws/{client_id}")
async def websocket_endpoint(websocket: WebSocket, client_id: str):
    await manager.connect(websocket)
    try:
        while True:
            data = await websocket.receive_text()
            await manager.broadcast(f"{client_id}: {data}")
    except WebSocketDisconnect:
        manager.disconnect(websocket)
        await manager.broadcast(f"{client_id} 님이 채팅방을 나갔습니다.")

서버 실행

bash
uvicorn main:app --reload --port 8000

Step 2: SvelteKit 프론트엔드 구현

프로젝트 생성

bash
npm create svelte@latest frontend
cd frontend
npm install

채팅 페이지 구현 (src/routes/+page.svelte)

svelte
<script lang="ts">
  import { onMount, onDestroy } from "svelte";

  let ws: WebSocket;
  let messages: string[] = [];
  let inputText = "";
  const clientId = Math.random().toString(36).substring(2, 7);

  onMount(() => {
    ws = new WebSocket(`ws://localhost:8000/ws/${clientId}`);

    ws.onmessage = (event) => {
      messages = [...messages, event.data];
    };

    ws.onclose = () => {
      console.log("연결 종료");
    };
  });

  onDestroy(() => {
    if (ws) ws.close();
  });

  function sendMessage() {
    if (ws.readyState === WebSocket.OPEN && inputText.trim()) {
      ws.send(inputText);
      inputText = "";
    }
  }
</script>

<main>
  <h1>실시간 채팅 - {clientId}</h1>
  <div class="messages">
    {#each messages as msg}
      <p>{msg}</p>
    {/each}
  </div>
  <form on:submit|preventDefault={sendMessage}>
    <input bind:value={inputText} placeholder="메시지를 입력하세요..." />
    <button type="submit">전송</button>
  </form>
</main>

Step 3: 채팅방(Room) 기능 추가

실서비스에서는 여러 채팅방이 필요합니다. 아래는 방별 연결을 관리하는 확장 구현입니다.

python
from collections import defaultdict

class RoomManager:
    def __init__(self):
        self.rooms: dict = defaultdict(list)

    async def join(self, room: str, websocket: WebSocket):
        await websocket.accept()
        self.rooms[room].append(websocket)

    def leave(self, room: str, websocket: WebSocket):
        self.rooms[room].remove(websocket)

    async def broadcast_room(self, room: str, message: str):
        for conn in self.rooms[room]:
            await conn.send_text(message)

room_manager = RoomManager()

@app.websocket("/ws/{room}/{client_id}")
async def room_endpoint(websocket: WebSocket, room: str, client_id: str):
    await room_manager.join(room, websocket)
    try:
        while True:
            data = await websocket.receive_text()
            await room_manager.broadcast_room(room, f"[{room}] {client_id}: {data}")
    except WebSocketDisconnect:
        room_manager.leave(room, websocket)

Step 4: 배포 고려 사항

운영 환경에서는 다음 요소를 반드시 점검해야 합니다.

  • Nginx WebSocket 프록시: proxy_pass와 함께 Upgrade 헤더 설정 필요
  • Gunicorn + Uvicorn workers: 멀티코어 활용을 위해 gunicorn -k uvicorn.workers.UvicornWorker 사용
  • Redis Pub/Sub: 여러 서버 인스턴스 간 메시지 동기화를 위해 Redis 브로드캐스트 채널 사용
  • JWT 인증: WebSocket 핸드셰이크 시 쿼리 파라미터로 토큰 전달 후 검증
  • 재연결 로직: 클라이언트에서 지수 백오프(exponential backoff) 방식으로 자동 재연결 구현

정리

FastAPI의 비동기 WebSocket 지원과 SvelteKit의 반응형 UI를 결합하면, 복잡한 라이브러리 없이도 완성도 높은 실시간 채팅을 구현할 수 있습니다. ConnectionManager 패턴으로 연결을 체계적으로 관리하고, Svelte의 반응성으로 메시지가 도착하는 즉시 화면에 반영됩니다.

코드벤터는 FastAPI와 SvelteKit 기반의 실무 프로젝트 경험을 바탕으로, 실시간 기능이 필요한 서비스 개발을 지원합니다. WebSocket 아키텍처 설계부터 배포까지 전 과정을 함께할 수 있으니, 프로젝트가 있다면 언제든지 코드픽(codepick.kr)에서 전문가를 찾아보세요.

개발 의뢰 상담

AI 서비스나 플랫폼 개발을
고민 중이신가요?

CodePick에서는
기획 → 개발 → 운영까지 함께합니다.
아이디어만 있어도 상담 가능합니다.

CodeVenter 개발팀이 직접 담당 · 1~2 영업일 내 회신

✓ 스타트업 MVP 개발✓ AI 서비스 개발✓ 웹 플랫폼 개발✓ 기업 시스템 구축✓ 모바일 앱 개발

AI Development Studio

코드픽 by 코드벤터

  • 대표: 윤승환 · 사업자등록번호: 121-57-64983
  • 대구광역시 중구 국채보상로 586, 16층 · info@codeventer.com

© 2025 코드벤터. All rights reserved.