티스토리 뷰

반응형

로컬 LLM + RAG 기반 AI 채팅봇 만들기

4.3 WebSocket을 활용한 실시간 채팅 기능 구현

이제 프론트엔드에서 사용자가 입력한 메시지를 WebSocket을 통해 백엔드(Ktor)로 전송하고,
AI 챗봇의 응답을 받아 실시간으로 화면에 표시하는 기능을 구현
하겠습니다.


1) WebSocket을 활용한 실시간 채팅 흐름

1️⃣ [사용자] 웹 UI에서 메시지를 입력  
2️⃣ [프론트엔드] WebSocket을 통해 메시지를 백엔드(Ktor)로 전송  
3️⃣ [백엔드] AI 챗봇이 메시지를 받아 LLM 모델에 요청  
4️⃣ [백엔드] LLM 응답을 받아 WebSocket을 통해 클라이언트로 전송  
5️⃣ [프론트엔드] AI 응답을 받아 채팅 UI에 표시  

2) WebSocket을 통한 메시지 전송 및 응답 처리

📌 ① WebSocket 클라이언트 설정 (src/lib/websocket.ts)

export const connectWebSocket = (onMessage: (msg: string) => void) => {
    const socket = new WebSocket("ws://localhost:8080/chat");

    socket.onopen = () => {
        console.log("WebSocket 연결 성공!");
    };

    socket.onmessage = (event) => {
        onMessage(event.data);
    };

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

    return socket;
};

📌 ② WebSocket을 이용한 사용자 메시지 전송 (src/components/ChatInput.svelte)

<script>
  import { createEventDispatcher, onMount } from 'svelte';
  import { connectWebSocket } from '../lib/websocket';

  let input = "";
  let socket;
  const dispatch = createEventDispatcher();

  onMount(() => {
    socket = connectWebSocket((message) => {
      dispatch('sendMessage', { sender: "ai", text: message });
    });
  });

  const sendMessage = () => {
    if (input.trim() !== "") {
      dispatch('sendMessage', { sender: "user", text: input });
      socket.send(input);
      input = "";
    }
  };
</script>

<div class="p-4 flex bg-white border-t">
  <input 
    class="flex-1 border p-2 rounded-lg"
    bind:value={input} 
    placeholder="메시지를 입력하세요..."
    on:keydown={(e) => e.key === 'Enter' && sendMessage()}
  />
  <button class="ml-2 px-4 py-2 bg-blue-500 text-white rounded-lg" on:click={sendMessage}>
    전송
  </button>
</div>

3) Ktor WebSocket 백엔드 구현 (메시지 처리 및 응답 생성)

📌 ① WebSocket을 통한 메시지 수신 및 응답 (WebSocketHandler.kt)

package ktor_chatbot.websocket

import io.ktor.server.application.*
import io.ktor.server.routing.*
import io.ktor.server.websocket.*
import io.ktor.websocket.*
import kotlinx.coroutines.channels.consumeEach
import ktor_chatbot.services.LlmService
import org.koin.ktor.ext.inject
import org.slf4j.LoggerFactory
import java.util.concurrent.ConcurrentHashMap

fun Application.configureWebSocketChat() {
    val logger = LoggerFactory.getLogger("WebSocketChat")
    val llmService: LlmService by inject()
    val activeSessions = ConcurrentHashMap<String, DefaultWebSocketSession>()

    routing {
        webSocket("/chat") {
            val sessionId = hashCode().toString()
            activeSessions[sessionId] = this
            logger.info("WebSocket 연결됨: $sessionId")

            try {
                incoming.consumeEach { frame ->
                    if (frame is Frame.Text) {
                        val userMessage = frame.readText()
                        logger.info("사용자 메시지: $userMessage")

                        // LLM에 메시지 전달 및 응답 생성
                        val response = llmService.getLlmResponse(userMessage)

                        // AI 응답을 클라이언트로 전송
                        send(Frame.Text(response))
                    }
                }
            } catch (e: Exception) {
                logger.error("WebSocket 오류 발생: ${e.localizedMessage}")
            } finally {
                activeSessions.remove(sessionId)
                logger.info("WebSocket 연결 종료: $sessionId")
            }
        }
    }
}

4) WebSocket 기능 테스트

🔹 Ktor 서버 실행

./gradlew run

🔹 브라우저 콘솔에서 WebSocket 테스트

const socket = new WebSocket("ws://localhost:8080/chat");

socket.onopen = () => {
    console.log("WebSocket 연결 성공!");
    socket.send("AI 챗봇이 뭐야?");
};

socket.onmessage = (event) => {
    console.log("서버 응답:", event.data);
};

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

✅ 예상 결과

[클라이언트] WebSocket 연결 성공!
[클라이언트] 서버 응답: "AI 챗봇은 사용자 질문을 분석하고 응답을 제공하는 시스템입니다."
[클라이언트] WebSocket 연결 종료

5) 성능 최적화 및 오류 처리

✅ ① WebSocket 연결 자동 재시도

<script>
  let socket;
  let reconnectTimeout = 5000;

  function connectWebSocket() {
    socket = new WebSocket("ws://localhost:8080/chat");

    socket.onopen = () => {
      console.log("WebSocket 연결됨");
    };

    socket.onclose = () => {
      console.log("WebSocket 연결 종료, 재연결 시도 중...");
      setTimeout(connectWebSocket, reconnectTimeout);
    };
  }

  connectWebSocket();
</script>

✅ ② AI 응답이 늦을 경우 로딩 표시

<script>
  let isLoading = false;

  function sendMessage() {
    isLoading = true;
    socket.send(input);
  }

  socket.onmessage = (event) => {
    isLoading = false;
    messages = [...messages, { sender: "ai", text: event.data }];
  };
</script>

{#if isLoading}
  <p class="text-gray-500">AI가 응답을 생성 중입니다...</p>
{/if}

6) 실시간 채팅 기능 구현 요약

기능 구현 파일

WebSocket 클라이언트 설정 websocket.ts
사용자 입력 및 메시지 전송 ChatInput.svelte
AI 응답 표시 ChatMessages.svelte
WebSocket 백엔드 처리 WebSocketHandler.kt
WebSocket 오류 처리 및 재연결 ChatInput.svelte

7) 다음 단계

이제 WebSocket을 활용하여 AI 챗봇과 실시간으로 대화하는 기능을 완성했습니다.
다음으로 5.1 챗봇 API 설계를 진행하여
RESTful API를 활용한 챗봇 기능 확장 및 API 문서화를 추가하겠습니다! 🚀

 

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함
반응형