# RO-BEING 이메일 처리 아키텍처 정립 및 DB 마이그레이션 ## 날짜: 2025-08-21 ## 작성자: happybell80 & Claude ## 1. 문제 상황 ### 초기 문제 - Gmail 통합 기능 구현 중 "종태님한테 메일 보내줘" 같은 자연어 요청 처리 필요 - 이름을 이메일 주소로 변환하는 로직이 없음 - robeing이 개인 연락처를 저장할 공간 부재 - auth_db라는 명칭이 실제 용도(main_db)와 불일치 ### 핵심 이슈 1. robeing이 사용자처럼 연락처를 관리할 DB 구조 없음 2. 대화 내역을 ChromaDB에만 저장하여 데이터 영속성 위험 3. auth_db 명칭이 혼란 야기 (실제로는 메인 DB 역할) 4. robing vs robeing 용어 불일치 ## 2. 해결 과정 ### 2.1 DB 아키텍처 재설계 #### Polyglot Persistence 전략 채택 ``` PostgreSQL (main_db) - 구조화된 데이터 ├── robeing.contacts - 연락처 정보 ├── robeing.conversations - 대화 기록 └── 기존 테이블들 (users, workspaces 등) ChromaDB - 벡터 검색 └── 대화 임베딩, 의미 검색 Neo4j (선택적) - 관계 데이터 └── 복잡한 인맥 관계 (향후 고려) ``` ### 2.2 auth_db → main_db 마이그레이션 #### 변경 대상 서비스 (51123 서버) - auth-server - robeing-gateway - robeing-monitor - frontend-base #### 변경 대상 서비스 (51124 서버) - rb10508_micro - rb8001 - rb10408_test #### 주요 변경 사항 ```yaml # docker-compose.yml 변경 DATABASE_URL=${DATABASE_URL:-postgresql://robeings:robeings@host.docker.internal:5432/main_db} ``` ### 2.3 robeing 전용 스키마 생성 ```sql -- 51123 서버 PostgreSQL에 실행 CREATE SCHEMA IF NOT EXISTS robeing; -- 연락처 테이블 CREATE TABLE robeing.contacts ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), robeing_id VARCHAR(50) NOT NULL, name VARCHAR(100) NOT NULL, email VARCHAR(255), phone VARCHAR(50), company VARCHAR(200), relationship VARCHAR(100), notes TEXT, extra JSONB DEFAULT '{}', created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); -- 대화 기록 테이블 CREATE TABLE robeing.conversations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), robeing_id VARCHAR(50) NOT NULL, user_message TEXT, robeing_response TEXT, context JSONB DEFAULT '{}', metadata JSONB DEFAULT '{}', timestamp TIMESTAMP DEFAULT NOW() ); ``` ## 3. 이메일 처리 아키텍처 정립 ### 3.1 역할 분담 명확화 #### robeing (rb10508_micro) - 디지털 동료 역할 - 사람처럼 자신의 연락처 관리 - "종태님"을 이메일 주소로 변환 - Gmail 권한 확인 (robeing-monitor 통해) - 대화 맥락 이해 및 의도 파악 #### skill-email - 이메일 발송 전문 서비스 - 단순 이메일 발송 도구 - robeing이 전달한 정보로 메일 발송 - OAuth 토큰 관리 - Gmail API 호출 ### 3.2 처리 플로우 ``` 사용자: "종태님한테 메일 보내줘" ↓ 1. robeing (rb10508_micro) - robeing-monitor에 Gmail 권한 확인 - robeing.contacts 테이블에서 "종태님" 검색 - 이메일 주소 찾기 (없으면 사용자에게 문의) ↓ 2. skill-email 호출 - 수신자 이메일 전달 - 메일 내용 확인 - 첨부파일 확인 - 메일 발송 ↓ 3. 결과 반환 - 발송 성공/실패 알림 - 대화 기록 저장 ``` ### 3.3 설계 철학 - **robeing은 사람**: 자기 연락처를 기억하고 관리 - **skill은 도구**: robeing이 사용하는 전문 서비스 - **판단의 주체**: robeing이 결정하고 skill이 실행 ## 4. 용어 통일 ### robing → robeing 변경 - 모든 코드베이스에서 용어 통일 - 문서, 주석, 변수명 모두 변경 - Git 커밋 메시지도 통일 ## 5. 구현 세부사항 ### 5.1 rb10508_micro 수정 ```python # app/api/endpoints.py conn = await asyncpg.connect( host='192.168.0.100', port=5432, user='robeings', password='robeings', database='main_db' # auth_db에서 변경 ) ``` ### 5.2 연락처 검색 로직 ```python async def search_contact(name: str, robeing_id: str): query = """ SELECT email, phone, extra FROM robeing.contacts WHERE robeing_id = $1 AND name ILIKE $2 """ result = await conn.fetchone(query, robeing_id, f'%{name}%') return result ``` ## 6. 교훈 ### 6.1 아키텍처 설계 - **명확한 역할 분담**: 각 서비스의 책임 영역 명확화 - **데이터 영속성**: 중요 데이터는 PostgreSQL에 저장 - **유연한 스키마**: JSONB 활용으로 확장성 확보 ### 6.2 네이밍의 중요성 - DB 이름은 용도를 명확히 반영해야 함 - 용어 불일치는 즉시 수정 필요 - 일관된 용어 사용이 코드 가독성 향상 ### 6.3 마이그레이션 전략 - 모든 서비스 동시 변경 필요 - docker-compose.yml, 설정 파일, 코드 모두 확인 - Git에 즉시 푸시하여 일관성 유지 ## 7. 향후 과제 ### 즉시 구현 필요 - [ ] 이름-이메일 매핑 캐시 (5분 TTL) - [ ] 연락처 자동 학습 기능 - [ ] 대화에서 이메일 추출 및 저장 ### 중기 과제 - [ ] Neo4j 도입 검토 (복잡한 관계 관리) - [ ] 연락처 중복 제거 로직 - [ ] 사용자별 연락처 격리 ## 8. 참고 사항 ### 서버 구성 - 51123: main 서비스 (nginx, auth, frontend) - 51124: robeing & skill 서비스 ### 포트 할당 - 8001: rb8001 (프로덕션) - 10508: rb10508_micro (테스트) - 8501: skill-email ### Git 브랜치 전략 - main: 대부분 서비스 - happybell80: rb8001, rb10408_test (테스트 후 머지)