DOCS/troubleshooting/250826_rb8001_conversation_storage_failure.md
happybell80 ec4865aefd docs: rb8001 PostgreSQL 저장 완전 해결 - Foreign key 처리 추가
- 1차 시도: UUID 변환 (Foreign key 위반 발생)
- 2차 해결: users 테이블 확인 로직 추가
- 등록 사용자만 user_id, 비등록은 slack_user_id 사용
- Foreign key 제약 유지하며 모든 대화 저장 가능
- 커밋: 84d124a, 5a0af8a
2025-08-26 20:25:29 +09:00

9.2 KiB

rb8001 PostgreSQL 대화 저장 UUID 타입 에러

작성일: 2025-08-26

작성자: 51124 서버 담당

상태: 완전 해결 (ChromaDB , PostgreSQL , Foreign key )

영향: PostgreSQL conversation_logs 정상 저장

최종 업데이트: 2025-08-26 19:30


1. 문제 상황

1.1 증상

  • PostgreSQL: UUID 타입 에러로 저장 실패
  • ChromaDB: 정상 저장 성공
  • 대화 이력: ChromaDB는 저장되나 PostgreSQL 조회 불가
  • 영향 범위: 모든 비-UUID 형식 user_id 사용자

1.2 실제 테스트 결과

# 테스트 요청
curl -X POST http://localhost:8001/api/message \
  -d '{"text": "테스트 저장 확인", "user_id": "test_user_123"}'

# 로그 확인
INFO: ChromaDB: Conversation saved for user test_user_123
ERROR: PostgreSQL save failed: invalid input syntax for type uuid: "test_user_123"

# 실제 에러
psycopg2.errors.InvalidTextRepresentation: invalid input syntax for type uuid: "test_user_123"
LINE 1: ... VALUES ('rb8001', 'test_user_123', 'web', ...

2. 원인 분석

2.1 실제 저장 로직 구현 상태

구성요소 상태 실제 동작
router.py:290-297 _save_conversation() 호출됨 정상 호출
router.py:309-365 _save_conversation() 구현됨 구현 완료
memory_manager.store_memory() ChromaDB 저장 성공
PostgreSQL 저장 UUID 타입 체크 타입 에러

2.2 ChromaDB 상태

  • 정상 작동: robeing_rb8001_memories 컬렉션에 저장 성공
  • 로그: "Stored memory: 852cb2556eb911413dfa2d33b76d04d1"
  • 컬렉션 로드: "Loaded existing collection: robeing_rb8001_memories"

2.3 PostgreSQL 스키마 문제

-- conversation_logs 테이블 스키마
user_id UUID  -- 문제: UUID 타입만 허용
slack_user_id VARCHAR(100)  -- 추가됨 (250826 문서)

-- 실제 저장 시도
INSERT INTO conversation_logs (user_id, ...) 
VALUES ('test_user_123', ...)  -- 실패: UUID 형식 아님

3. 코드 분석

3.1 실제 구현된 저장 코드

# rb8001/app/router/router.py:290-297
async def _call_internal_llm(...):
    # LLM 호출
    result = await self.llm_service.process_request(llm_request)
    
    # 저장 함수 호출 (실제로 구현됨)
    if result.get("success") and result.get("content"):
        await self._save_conversation(
            message=message,
            response=result.get("content"),
            user_id=user_id,  # 여기서 "test_user_123" 같은 문자열 전달
            channel=channel,
            intent=task_type,
            confidence=result.get("confidence", 0.8)
        )
    
    return result

# router.py:338-344
conversation_log = ConversationLog(
    robeing_id=settings.ROBEING_ID,
    user_id=user_id,  # UUID 타입 필요한데 문자열 전달 -> 에러
    channel_id=channel,
    message=message,
    response=response,
    ...
)

3.2 robeing-monitor 엔드포인트도 404

curl -X POST http://localhost:9024/api/logs/rb8001/conversation
# 404 Not Found

4. 영향도

4.1 기능 영향

  • 대화 이력 조회: 불가능
  • 컨텍스트 유지: 불가능 (매 대화가 새 대화)
  • 학습/개선: 불가능 (데이터 없음)
  • 감사 로그: 없음

4.2 서비스별 상태

서비스 대화 기능 ChromaDB 저장 PostgreSQL 저장
Slack (U091UNVE41M) 작동 성공 UUID 에러
Frontend (test_user) 작동 성공 UUID 에러
DM 작동 성공 UUID 에러

5. 해결 방안

5.1 즉시 필요한 작업

  1. UUID 변환 로직 추가: Slack ID나 일반 문자열을 UUID로 변환
  2. slack_user_id 필드 활용: user_id 대신 slack_user_id 사용
  3. 스키마 수정 고려: user_id를 nullable로 만들기

5.2 코드 수정 예시

# rb8001/app/router/router.py의 _save_conversation() 수정
import uuid

async def _save_conversation(self, ...):
    # UUID 변환 로직 추가
    try:
        # UUID 형식 체크
        uuid.UUID(user_id)
        user_uuid = user_id
    except ValueError:
        # UUID가 아니면 생성 또는 None
        namespace = uuid.UUID('6ba7b810-9dad-11d1-80b4-00c04fd430c8')
        user_uuid = str(uuid.uuid5(namespace, user_id))
    
    # PostgreSQL 저장 시
    conversation_log = ConversationLog(
        robeing_id=settings.ROBEING_ID,
        user_id=user_uuid,  # UUID 사용
        slack_user_id=user_id if not is_uuid else None,  # 원본 ID 저장
        channel_id=channel,
        message=message,
        response=response,
        ...
    )

6. 검증 방법

6.1 저장 확인

# 테스트 메시지 전송
curl -X POST http://localhost:8001/api/message \
  -H "Content-Type: application/json" \
  -d '{"text": "테스트", "user_id": "test_user"}'

# PostgreSQL 확인
psql -h localhost -p 5433 -U robeings -d main_db \
  -c "SELECT * FROM conversation_logs ORDER BY timestamp DESC LIMIT 1;"

# ChromaDB 확인 (수정 후)
docker exec rb8001 python -c "
from chromadb import PersistentClient
client = PersistentClient('/code/chroma_db')
print('Collections:', client.list_collections())
"

7. 주의사항

7.1 ChromaDB 복구

  • 백업 없이 초기화 시 기존 데이터 손실
  • 메타데이터 수동 복구 어려움
  • 재생성이 더 안전할 수 있음

7.2 대용량 처리

  • 저장 로직 추가 시 응답 지연 가능
  • 비동기 처리 고려 필요
  • 에러 시 응답은 정상 반환되도록

8. 관련 파일

51124 서버

  • /home/admin/ivada_project/rb8001/app/brain/state_client.py - 저장 함수
  • /home/admin/ivada_project/rb8001/app/memory/manager.py - ChromaDB 관리
  • /home/admin/ivada_project/rb8001/app/router/router.py - 라우팅 로직
  • /home/admin/ivada_project/rb8001/main.py - 엔드포인트

데이터 위치

  • ChromaDB: /home/admin/ivada_project/rb8001/chroma_db/
  • PostgreSQL: main_db.conversation_logs 테이블

9. 예상 소요 시간

  • 코드 수정: 30분
  • 테스트: 30분
  • ChromaDB 복구: 1시간 (재생성 시)

10. 우선순위

중간 - ChromaDB는 정상 작동하므로 기본 기능은 유지됨. PostgreSQL 저장만 실패

11. 수정 후 상태 (2025-08-26 19:00 업데이트)

  • ChromaDB: 정상 저장 및 조회 가능
  • PostgreSQL: UUID 변환 로직 추가로 정상 저장

12. 📊 테스트 결과 (2025-08-26 18:30)

12.1 해결된 이슈

  1. 채팅 API: 정상 작동 (응답 받음)
  2. Stats API: rb8001 스탯 정상 조회 (undefined 없음)
  3. PostgreSQL 직접 삽입: UUID 형식으로 수동 삽입시 성공

12.2 ⚠️ 남은 문제

  1. 51124 서버 rb8001:

    • conversation_logs 저장 안됨 (최근 데이터 14시간 전)
    • UUID 타입 에러로 PostgreSQL 저장 실패 중
    • ChromaDB만 저장되고 PostgreSQL은 실패
  2. Gateway JWT 에러:

    • "Signature verification failed" 발생
    • 하지만 기본 사용자(default)로 처리됨

12.3 📝 확인 내역

항목 상태 결과
채팅 API 응답: "안녕하세요, 사용자님..."
Stats API rb8001 레벨 1, 경험치 0
DB 직접 삽입 ID 23번으로 저장 성공
51124 자동 저장 14시간 전 이후 저장 안됨

12.4 핵심 문제

51124 서버의 rb8001이 UUID 형식이 아닌 user_id를 보내서 PostgreSQL 저장 실패

12.5 해결 과정

1차 시도 (2025-08-26 19:00) - UUID 변환

적용된 해결책

  • router.py:309-378 UUID 변환 로직 추가
  • UUID가 아닌 경우 UUID5로 변환
  • 문제 발견: Foreign key 제약 위반 (users 테이블에 없는 UUID)

2차 해결 (2025-08-26 19:30) - Foreign key 처리

최종 해결책

  1. router.py:344-391 users 테이블 확인 로직 추가

    • UUID 형식 & users 테이블 존재 → user_id에 저장
    • UUID 형식 & users 테이블 없음 → user_id는 NULL, slack_user_id에 저장
    • 비-UUID (Slack ID, 문자열) → user_id는 NULL, slack_user_id에 저장
  2. database.py:56 스키마 수정 유지

    • slack_user_id 컬럼 (VARCHAR) - 원본 ID 보존
    • user_id (UUID/NULL) - Foreign key 제약 준수
  3. Git 커밋 및 배포

    • 1차 커밋: 84d124a (UUID 변환)
    • 2차 커밋: 5a0af8a (Foreign key 해결)
    • Gitea Actions 자동 배포 → 51124 서버

12.6 최종 처리 로직

케이스 users 테이블 user_id 저장 slack_user_id 저장
등록된 UUID 사용자 존재 UUID 값 NULL
미등록 UUID 없음 NULL UUID 값
Slack ID (U0925SXQFDK) - NULL U0925SXQFDK
문자열 (test_user) - NULL test_user
happybell80 - NULL happybell80

12.7 검증된 장점

  • Foreign key 제약 유지
  • 모든 대화 저장 가능
  • users 테이블 오염 방지
  • slack_user_id로 사용자 추적 가능
  • 나중에 사용자 등록 시 매핑 가능

12.8 남은 작업

⚠️ Gateway JWT 에러: "Signature verification failed" (별도 이슈로 처리)