DOCS/journey/troubleshooting/250821_happybell80_robeing_이메일처리_아키텍처_정립.md
happybell80 0252dd1a7f fix: 51123 서버 IP 주소 업데이트 (성수 이전)
192.168.219.45 → 192.168.0.100 일괄 변경

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:52:26 +09:00

5.5 KiB

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

주요 변경 사항

# docker-compose.yml 변경
DATABASE_URL=${DATABASE_URL:-postgresql://robeings:robeings@host.docker.internal:5432/main_db}

2.3 robeing 전용 스키마 생성

-- 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 수정

# 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 연락처 검색 로직

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 (테스트 후 머지)