# Conversation Log 재설계: Event Stream 아키텍처 ## 작성일 2025-10-02 ## 문제 상황 ### 기존 conversation_log 테이블 한계 ```sql conversation_log - user_id (FK) - message - response ``` **가정**: 항상 1:1 대화 (user → robeing) ### 실제 요구사항 1. **그룹 대화**: user1, user2, user3, robeing 2. **로빙 브리핑**: robeing → 팀 전체 3. **로빙 협업**: robeing1 ↔ robeing2 4. **멀티턴 쓰레드**: user ↔ robeing (여러 왕복) ### 근본 문제 - **참여자 표현 불가**: 1:1만 가정 - **방향성 모호**: message/response 구분 애매 - **컨텍스트 부재**: 어떤 채널/쓰레드인지 불명확 - **로빙 철학 위배**: 로빙도 대화 주체인데 user 테이블에 없음 ## 철학적 배경 ### 로빙 철학과 DB 구조 충돌 - **user 테이블**: 인증/식별 (OAuth, email, login) - **robeing 테이블**: 성장 주체 (level, experience, stats) - **문제**: 로빙 봇(Slack Bot ID)이 user 테이블에 없어서 봇 메시지 저장 불가 ### "대화는 이벤트의 흐름" - **Graph DB**: 공간적 관계망 (A-B-C 연결 구조) - **Event Stream**: 시간적 흐름 (A→B→C 순서) - 로빙의 베이지안 성장 = 시간에 따른 업데이트 → **시간축이 핵심** ## 해결 방안: Event 테이블 (6하원칙) ### 설계 원칙 **장소(where_id) + 시간(timestamp) = 이벤트 연결** - where_id: Slack, 이메일, 웹, 음성통화 등 모든 채널 - timestamp: 시간 순서 보장 - 6하원칙: 모든 이벤트를 표준화 ### Event 테이블 구조 ```sql event -- 기본 6하원칙 - id (PK, UUID) - who_id (UUID) -- 행위 주체 - who_type (VARCHAR) -- human/robeing/system - what_type (VARCHAR) -- message/file_transfer/task_assign/analysis_request/reaction - what_content (JSONB) -- 실제 내용/데이터 - when_at (TIMESTAMPTZ) -- 시간 - where_id (VARCHAR) -- 장소 (channel/dm/email/system) - where_type (VARCHAR) -- slack/email/web/voice/internal - why (VARCHAR) -- intent/purpose - how (VARCHAR) -- method/tool -- 확장 필드 (복잡한 관계 처리) - to_who (JSONB) -- [{id, type}] 수신자 목록 - using (JSONB) -- [{id, type, resource}] 사용된 리소스/데이터 - affected (JSONB) -- [{id, type, change}] 영향받은 대상 - parent_event_id (UUID) -- 이전 이벤트 (인과관계) - result (JSONB) -- {status, outcome, data} 결과 - metadata (JSONB) -- 기타 확장 데이터 -- 인덱스 - (where_id, when_at) -- 시계열 조회 - (who_id, when_at) -- 주체별 이력 - parent_event_id -- 이벤트 체인 ``` ### JSONB 활용 예시 #### 1. 파일 전송 ```json { "who_id": "user-uuid", "what_type": "file_transfer", "what_content": {"filename": "report.pdf", "size": 1024}, "to_who": [{"id": "user2-uuid", "type": "human"}], "where_id": "slack-dm-123" } ``` #### 2. 로빙 협업 ```json { "who_id": "robeing1-uuid", "what_type": "analysis_request", "to_who": [{"id": "robeing2-uuid", "type": "robeing"}], "using": [{"id": "robeing3-uuid", "type": "robeing", "resource": "market_data"}], "result": {"status": "completed", "data": "..."} } ``` #### 3. 그룹 대화 ```json { "who_id": "user1-uuid", "what_type": "message", "what_content": {"text": "팀 회의 시작합니다"}, "to_who": [ {"id": "user2-uuid", "type": "human"}, {"id": "user3-uuid", "type": "human"}, {"id": "robeing-uuid", "type": "robeing"} ], "where_id": "slack-channel-team" } ``` ## 이벤트 연결 메커니즘 ### 간단 버전 1. **같은 장소**: where_id로 묶음 2. **같은 쓰레드**: parent_event_id 체인 3. **시간 순서**: when_at으로 정렬 ### 쿼리 예시 ```sql -- 특정 채널의 모든 이벤트 (시간순) SELECT * FROM event WHERE where_id = 'slack-channel-123' ORDER BY when_at; -- 특정 이벤트 체인 (쓰레드) WITH RECURSIVE thread AS ( SELECT * FROM event WHERE id = 'root-event-id' UNION ALL SELECT e.* FROM event e JOIN thread t ON e.parent_event_id = t.id ) SELECT * FROM thread ORDER BY when_at; ``` ## Graph DB와의 관계 ### Graph DB가 필요한 순간 1. **복잡한 관계 쿼리 반복**: 3-hop 이상 탐색 2. **실시간 추천**: 협업 필터링, 소셜 추천 3. **영향력 분석**: 정보 전파 경로, 네트워크 중심성 4. **다중 로빙 협업**: 최적 조합 찾기 ### 현재 판단 **Event Stream만으로 충분** - JSONB로 관계 저장 (충분히 유연) - 시계열 분석이 핵심 (TimescaleDB 최적화) - 나중에 필요하면 Graph DB 추가 (Read Model 패턴) ### Graph vs Event Stream - **Graph**: "누구와 연결되었나" (공간적 관계망) - **Event**: "언제 무엇을 했나" (시간적 흐름) - 로빙의 핵심(성장/기억/감정) = 시간축 → **Graph는 optional** ## 마이그레이션 전략 ### 1단계: Event 테이블 생성 (robeing_metrics DB) ```sql CREATE TABLE event ( -- 6하원칙 컬럼들 ... ) PARTITION BY RANGE (when_at); -- TimescaleDB 하이퍼테이블 전환 SELECT create_hypertable('event', 'when_at'); ``` ### 2단계: 기존 conversation_log 데이터 변환 ```sql INSERT INTO event (who_id, what_type, what_content, when_at, where_id, ...) SELECT user_id as who_id, 'message' as what_type, jsonb_build_object('text', message, 'response', response) as what_content, timestamp as when_at, channel_id as where_id, ... FROM conversation_log; ``` ### 3단계: 애플리케이션 코드 전환 - conversation_log 조회 → event 조회 - 새 대화 저장 → event INSERT ## 기대 효과 ### 1. 확장성 - 모든 종류의 이벤트 저장 가능 (대화, 파일, 작업, 알림 등) - 새로운 이벤트 타입 추가 시 스키마 변경 불필요 (JSONB) ### 2. 분석 역량 - 시계열 분석 최적화 (TimescaleDB) - 이벤트 체인 추적 (베이지안 업데이트) - 사용자/로빙별 이력 조회 ### 3. 철학적 일관성 - 로빙도 이벤트 주체로 동등하게 취급 - user = "관계의 상대방" 명확화 - 성장과 기억의 원천 = 이벤트 흐름 ## 교훈 ### 기존 설계의 문제 - **conversation_log**: 챗봇 QA 로그 수준 - **1:1 가정**: 다중 참여자 협업 불가 - **user/robeing 분리**: 로빙을 도구로 취급 ### 새로운 설계의 핵심 - **Event Stream**: 모든 행위를 시간순 이벤트로 - **6하원칙**: 표준화된 구조 - **JSONB**: 복잡한 관계도 유연하게 - **시간축 중심**: 베이지안 성장과 일치 ## 참고사항 ### 관련 문서 - `/home/admin/DOCS/300_architecture/database/tables.md`: DB 스키마 - `/home/admin/DOCS/100_philosophy/125_베이즈_성장과_관계의_철학.md`: 로빙 철학 ### DB 위치 - **main_db**: user, robeing 테이블 (기존) - **robeing_metrics**: event 테이블 (새로 추가) - TimescaleDB 하이퍼테이블로 시계열 최적화