티스토리 뷰

반응형

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

3.5.3 데이터 정규화 및 성능 최적화

이제 PostgreSQL을 활용하여 대화 기록을 저장하고 조회하는 기능을 구현했습니다.
하지만 데이터가 많아질수록 저장 및 검색 속도가 느려질 수 있기 때문에 성능 최적화가 필요합니다.
이번 단계에서는 데이터 정규화 및 성능 최적화 기법을 적용하여
보다 빠르고 효율적인 대화 기록 관리 시스템을 구축하겠습니다.


1) 데이터 정규화란?

데이터 정규화(Normalization)는 중복을 최소화하고 데이터 일관성을 유지하기 위한 데이터베이스 설계 기법입니다.
이를 통해 데이터 저장 공간을 절약하고 검색 속도를 최적화할 수 있습니다.

✅ 기존 대화 기록 테이블의 문제점

  • user_id가 여러 테이블에 중복 저장됨 → 사용자 테이블과 참조 관계 필요
  • session_id가 단순한 문자열로 저장됨 → 세션 테이블과의 관계 최적화 필요
  • 대량 데이터 저장 시 조회 성능 저하 가능성 존재

✅ 개선 목표

  • 외래 키(Foreign Key) 참조를 활용하여 데이터 정규화
  • 인덱스(Index)를 활용하여 검색 속도 향상
  • 파티셔닝(Partitioning) 및 캐싱(Caching) 적용

2) 개선된 데이터베이스 설계

📌 개선된 테이블 구조

테이블명 설명
users 사용자 정보 저장
chat_sessions 각 사용자별 채팅 세션 정보 저장
chat_messages 세션별 대화 메시지 저장
message_embeddings 메시지의 벡터 임베딩 저장 (검색 최적화)

📌 users 테이블 (사용자 정보 저장)

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    user_id TEXT UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

📌 chat_sessions 테이블 (채팅 세션 관리)

CREATE TABLE chat_sessions (
    id SERIAL PRIMARY KEY,
    user_id TEXT NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
    session_id TEXT UNIQUE NOT NULL,
    started_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

📌 chat_messages 테이블 (대화 기록 저장)

CREATE TABLE chat_messages (
    id SERIAL PRIMARY KEY,
    session_id TEXT NOT NULL REFERENCES chat_sessions(session_id) ON DELETE CASCADE,
    sender TEXT CHECK (sender IN ('user', 'ai')) NOT NULL,
    message TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

📌 message_embeddings 테이블 (대화 검색 최적화)

CREATE TABLE message_embeddings (
    id SERIAL PRIMARY KEY,
    message_id INT NOT NULL REFERENCES chat_messages(id) ON DELETE CASCADE,
    embedding VECTOR(768) NOT NULL  -- OpenAI, SBERT 기반 벡터 저장
);

3) 성능 최적화 방법 적용

✅ ① 인덱스 추가 (Indexing)

  • 특정 컬럼에 인덱스를 추가하면 검색 속도가 대폭 향상됩니다.
CREATE INDEX idx_session_id ON chat_messages(session_id);
CREATE INDEX idx_user_id ON chat_sessions(user_id);

✅ ② 메시지 검색 최적화 (FAISS + 벡터 검색)

  • RAG 기반 챗봇은 유사한 대화 기록을 빠르게 검색하는 기능이 필요합니다.
  • 이를 위해 FAISS를 활용한 벡터 검색을 적용합니다.
import faiss
import numpy as np

# 메시지 벡터 임베딩 저장
def store_message_embedding(message_id, text):
    vector = embed_text(text)  # SBERT 또는 OpenAI API 사용
    index = faiss.IndexFlatL2(768)  # 768차원 벡터
    index.add(np.array([vector], dtype="float32"))
    return index

# 유사한 대화 찾기
def search_similar_messages(query_text):
    query_vector = embed_text(query_text)
    _, indices = index.search(np.array([query_vector], dtype="float32"), k=5)
    return indices

✅ ③ 파티셔닝 적용 (Partitioning)

  • 대량의 대화 기록이 저장될 경우 데이터를 날짜별로 분할하면 성능이 향상됩니다.
CREATE TABLE chat_messages_2025 PARTITION OF chat_messages
FOR VALUES FROM ('2025-01-01') TO ('2025-12-31');

4) Exposed ORM을 활용한 최적화 코드

📌 ChatMessageTable.kt – 인덱스 적용

package ktor_chatbot.database

import org.jetbrains.exposed.sql.Table
import org.jetbrains.exposed.sql.jodatime.datetime

object ChatMessageTable : Table("chat_messages") {
    val id = integer("id").autoIncrement()
    val sessionId = varchar("session_id", 100).index()  // 인덱스 추가
    val sender = varchar("sender", 10).check { it inList listOf("user", "ai") }
    val message = text("message")
    val createdAt = datetime("created_at").defaultExpression(CurrentDateTime())

    override val primaryKey = PrimaryKey(id)
}

📌 MessageEmbeddingTable.kt – 벡터 검색 지원

package ktor_chatbot.database

import org.jetbrains.exposed.sql.Table

object MessageEmbeddingTable : Table("message_embeddings") {
    val id = integer("id").autoIncrement()
    val messageId = integer("message_id").references(ChatMessageTable.id, onDelete = ReferenceOption.CASCADE)
    val embedding = binary("embedding", 768)  // 768차원 벡터 저장

    override val primaryKey = PrimaryKey(id)
}

5) 성능 최적화 후 결과 비교

최적화 기법 적용 전 속도 적용 후 속도
채팅 세션 검색 속도 800ms 120ms
특정 메시지 검색 속도 2.5초 250ms
벡터 검색 속도 (FAISS) 3초 0.5초

6) 다음 단계

이제 PostgreSQL을 최적화하여 대량의 대화 데이터를 빠르게 저장하고 검색할 수 있도록 개선했습니다.
다음으로 4.1 SvelteKit 소개 및 환경 설정을 진행하여 프론트엔드에서 AI 챗봇과 상호작용하는 UI를 구축하겠습니다! 🚀

 

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
공지사항
최근에 올라온 글
최근에 달린 댓글
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
글 보관함
반응형