# PostgreSQL 테이블 구조 ## 작성일: 2025-08-20 ## 최종 수정일: 2025-09-02 ## 데이터베이스: main_db --- ## 1. 사용자 관련 테이블 ### users - **용도**: 시스템 전체 사용자 정보 - **Primary Key**: id (UUID) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | UUID | NO | | 사용자 고유 식별자 | | email | VARCHAR(255) | NO | | 이메일 주소 (UNIQUE) | | name | VARCHAR(255) | YES | | 사용자 실명 | | username | VARCHAR(50) | YES | | 로그인 ID (UNIQUE) | | picture | VARCHAR(500) | YES | | 프로필 이미지 URL | | oauth_provider | VARCHAR(50) | YES | | OAuth 제공자 (google 등) | | oauth_id | VARCHAR(255) | YES | | OAuth 고유 ID | | is_active | BOOLEAN | YES | true | 활성 상태 | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | | last_login_at | TIMESTAMP | YES | | 마지막 로그인 | --- ## 2. Workspace 관련 테이블 ### workspaces - **용도**: 워크스페이스 정보 - **Primary Key**: id (UUID) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | UUID | NO | | 워크스페이스 ID | | name | VARCHAR(255) | NO | | 워크스페이스 이름 | | company_id | UUID | YES | | 회사 ID (FK → companies) | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | ### workspace_members - **용도**: 워크스페이스 멤버 관계 - **Primary Key**: id (UUID) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | UUID | NO | | 멤버십 ID | | workspace_id | UUID | NO | | 워크스페이스 ID (FK → workspaces) | | user_id | UUID | NO | | 사용자 ID (FK → users) | | role | ENUM | YES | member | 역할 (admin/member) | | robeing_id | VARCHAR(50) | YES | | 할당된 로빙 ID | | robeing_url | VARCHAR(255) | YES | | 로빙 서비스 URL | | is_active | BOOLEAN | YES | true | 활성 상태 | | joined_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 가입 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | ### companies - **용도**: 회사 정보 - **Primary Key**: id (UUID) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | UUID | NO | | 회사 ID | | name | VARCHAR(255) | NO | | 회사명 | | domain | VARCHAR(255) | YES | | 도메인 | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | --- ## 3. Slack 통합 테이블 ### slack_workspaces - **용도**: Slack 워크스페이스 정보 - **Primary Key**: id (UUID) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | UUID | NO | | 워크스페이스 ID | | company_id | UUID | NO | | 회사 ID (FK → companies) | | team_id | VARCHAR(100) | NO | | Slack Team ID (UNIQUE) | | team_name | VARCHAR(255) | YES | | 팀 이름 | | bot_token | TEXT | YES | | Bot User OAuth Token | | bot_user_id | VARCHAR(100) | YES | | Bot User ID | | app_id | VARCHAR(100) | YES | | Slack App ID | | scopes | JSON | YES | | Bot 권한 스코프 목록 | | is_enterprise_install | BOOLEAN | YES | | 엔터프라이즈 설치 여부 | | is_active | BOOLEAN | YES | | 활성 상태 | | installed_at | TIMESTAMP | YES | | 설치 시각 | | updated_at | TIMESTAMP | YES | | 수정 시각 | ### slack_user_mapping - **용도**: Slack 사용자와 시스템 사용자 매핑 - **Primary Key**: id (UUID) - **Unique**: (slack_user_id, slack_workspace_id) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | UUID | NO | gen_random_uuid() | 매핑 ID | | slack_user_id | VARCHAR(100) | NO | | Slack User ID (U로 시작) | | slack_workspace_id | UUID | YES | | Slack 워크스페이스 ID (FK → slack_workspaces) | | user_id | UUID | YES | | 시스템 사용자 ID (FK → users) | | workspace_member_id | UUID | YES | | 워크스페이스 멤버 ID (FK → workspace_members) | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | --- ## 4. 로빙 관련 테이블 ### robeing_stats - **용도**: 로빙 통계 및 레벨 정보 - **Primary Key**: id (SERIAL) - **Unique**: robeing_id | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 자동 증가 ID | | user_id | UUID | YES | | 사용자 ID (FK → users) | | robeing_id | VARCHAR(50) | NO | | 로빙 ID (UNIQUE) | | name | VARCHAR(100) | YES | | 로빙 이름 | | level | INTEGER | YES | 1 | 레벨 | | experience | INTEGER | YES | 0 | 경험치 | | memory | INTEGER | YES | 10 | 메모리 스탯 | | compute | INTEGER | YES | 10 | 연산 스탯 | | react | INTEGER | YES | 10 | 반응 스탯 | | empathy | INTEGER | YES | 10 | 공감 스탯 | | leadership | INTEGER | YES | 10 | 리더십 스탯 | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | ### robeing_settings - **용도**: 로빙 설정 정보 - **Primary Key**: 미확인 (테이블 구조 확인 필요) ### user_preferences - **용도**: 사용자 개인 설정 - **Primary Key**: id (SERIAL) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 자동 증가 ID | | user_id | UUID | YES | | 사용자 ID (FK → users) | | slack_user_id | VARCHAR(100) | YES | | Slack 사용자 ID | | news_keywords | VARCHAR(128)[] | YES | | 뉴스 키워드 배열 | | email_filter | VARCHAR(128)[] | YES | | 이메일 필터 배열 | | briefing_enabled | BOOLEAN | YES | true | 브리핑 활성화 여부 | | briefing_time | TIME | YES | 09:00:00 | 브리핑 시간 | | updated_at | TIMESTAMP | YES | now() | 수정 시각 | --- ## 5. 대화 및 로그 테이블 ### conversation_logs - **용도**: 로빙 대화 기록 - **Primary Key**: id (SERIAL) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 자동 증가 ID | | robeing_id | VARCHAR | YES | | 로빙 ID | | channel_id | VARCHAR | YES | | 채널 ID | | message | VARCHAR | YES | | 사용자 메시지 | | response | VARCHAR | YES | | 로빙 응답 | | intent | VARCHAR | YES | | 인텐트 분류 | | confidence | DOUBLE PRECISION | YES | | 신뢰도 점수 | | timestamp | TIMESTAMP | YES | | 대화 시각 | | user_id | UUID | YES | | 사용자 ID (FK → users) | | slack_user_id | VARCHAR(100) | YES | | Slack 사용자 ID | | thread_ts | VARCHAR(128) | YES | | Slack 스레드 타임스탬프 | | channel_type | VARCHAR(32) | YES | | 채널 타입 | ### gmail_audit_logs - **용도**: Gmail 작업 감사 로그 - **Primary Key**: id (SERIAL) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 자동 증가 ID | | user_id | VARCHAR(100) | YES | | 사용자 ID | | robeing_id | VARCHAR(50) | YES | | 로빙 ID | | action | VARCHAR(50) | YES | | 실행 액션 | | success | BOOLEAN | YES | | 성공 여부 | | details | JSONB | YES | | 상세 정보 | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | --- ## 6. Gmail 관련 테이블 ### gmail_tokens - **용도**: Gmail OAuth 토큰 저장 - **Primary Key**: id (SERIAL) - **소유자**: robeings | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 토큰 ID | | user_id | UUID | NO | | 사용자 ID (FK → users) (UNIQUE) | | username | VARCHAR(50) | YES | | 사용자명 (users.username과 동일) | | slack_id | VARCHAR(50) | YES | | Slack User ID (U로 시작) | | robeing_id | VARCHAR(50) | YES | | 로빙 ID | | token_data | JSONB | YES | | access_token, refresh_token, token_type 등 | | oauth_config | JSONB | YES | | client_id, client_secret, token_uri | | scopes | JSONB | YES | | Gmail API 권한 목록 | | metadata | JSONB | YES | | email, name, picture, verified_email 등 | | expiry | TIMESTAMP | YES | | 토큰 만료 시각 | | is_equipped | BOOLEAN | YES | false | 장착 상태 | | equipped_to | VARCHAR(50) | YES | | 장착된 로빙 ID | | access_token | TEXT | YES | | 직접 저장된 액세스 토큰 | | refresh_token | TEXT | YES | | 직접 저장된 리프레시 토큰 | | token_type | VARCHAR | YES | 'Bearer' | 토큰 타입 | | expires_at | DOUBLE PRECISION | YES | | 토큰 만료 시간 (Unix timestamp) | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | ### gmail_audit_logs - **용도**: Gmail 아이템 작업 감사 로그 - **Primary Key**: id (SERIAL) - **소유자**: postgres (권한 조정 필요) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 로그 ID | | user_id | UUID | YES | | 사용자 ID (FK → users) | | robeing_id | VARCHAR(50) | YES | | 로빙 ID | | action | VARCHAR(50) | YES | | 작업 유형 (equip/unequip/reauth) | | success | BOOLEAN | YES | | 성공 여부 | | details | JSONB | YES | | 상세 정보 | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | ### gmail_tokens_old - **용도**: gmail_tokens 테이블 백업 (마이그레이션 과정 중 생성) - **Primary Key**: id (SERIAL) - **소유자**: robeings - **참고**: 이전 구조의 백업 테이블로, 향후 제거 가능 | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | (구조는 gmail_tokens와 유사하나 이전 버전) | | | | 마이그레이션 전 데이터 보관용 | --- ## 5. 로빙 관련 테이블 ### robeing_stats - **용도**: 로빙 통계 및 레벨 정보 - **Primary Key**: id (SERIAL) - **소유자**: robeings - **수정**: 2025-08-28 스탯 컬럼 추가 | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 통계 ID | | user_id | UUID | YES | | 사용자 ID (FK → users) | | robeing_id | VARCHAR(50) | NO | | 로빙 ID (UNIQUE) | | name | VARCHAR(100) | YES | | 로빙 이름 | | level | INTEGER | YES | 1 | 현재 레벨 | | experience | INTEGER | YES | 0 | 경험치 | | memory | INTEGER | YES | 10 | 메모리 스탯 | | compute | INTEGER | YES | 10 | 연산 스탯 | | react | INTEGER | YES | 10 | 반응 스탯 | | empathy | INTEGER | YES | 10 | 공감 스탯 | | leadership | INTEGER | YES | 10 | 리더십 스탯 | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | ### robeing_settings - **용도**: 로빙 설정 정보 - **Primary Key**: id (SERIAL) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 설정 ID | | robeing_id | VARCHAR(50) | NO | | 로빙 ID (UNIQUE) | | settings | JSONB | YES | | 설정 JSON | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | --- ## 6. robeing 전용 스키마 테이블 ### robeing.contacts - **용도**: 로빙이 관리하는 연락처 정보 - **Primary Key**: id (UUID) - **스키마**: robeing | 컴럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | UUID | NO | gen_random_uuid() | 연락처 ID | | robeing_id | VARCHAR(50) | NO | | 로빙 ID | | name | VARCHAR(100) | NO | | 이름 | | email | VARCHAR(255) | YES | | 이메일 주소 | | phone | VARCHAR(50) | YES | | 전화번호 | | company | VARCHAR(200) | YES | | 회사명 | | relationship | VARCHAR(100) | YES | | 관계 (동료, 고객 등) | | notes | TEXT | YES | | 메모 | | extra | JSONB | YES | {} | 추가 정보 | | created_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 생성 시각 | | updated_at | TIMESTAMP | YES | CURRENT_TIMESTAMP | 수정 시각 | ### robeing.conversations - **용도**: 로빙 대화 기록 - **Primary Key**: id (UUID) - **스키마**: robeing | 컴럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | UUID | NO | gen_random_uuid() | 대화 ID | | robeing_id | VARCHAR(50) | NO | | 로빙 ID | | user_message | TEXT | YES | | 사용자 메시지 | | robeing_response | TEXT | YES | | 로빙 응답 | | context | JSONB | YES | {} | 대화 컨텍스트 | | metadata | JSONB | YES | {} | 메타데이터 | | timestamp | TIMESTAMP | YES | CURRENT_TIMESTAMP | 대화 시각 | --- ## 7. 대화 로그 테이블 ### conversation_logs - **용도**: 대화 기록 저장 - **Primary Key**: id (SERIAL) - **최근 수정**: 2025-08-26 (slack_user_id 추가) | 컬럼명 | 타입 | NULL | 기본값 | 설명 | |--------|------|------|--------|------| | id | SERIAL | NO | | 로그 ID | | robeing_id | VARCHAR | YES | | 로빙 ID | | channel_id | VARCHAR | YES | | 채널 ID (web=Frontend/Slack DM 혼재, C로 시작=Slack 채널) ⚠️ | | message | VARCHAR | YES | | 사용자 메시지 | | response | VARCHAR | YES | | 로빙 응답 | | intent | VARCHAR | YES | | 의도 분석 결과 | | confidence | DOUBLE PRECISION | YES | | 신뢰도 점수 | | timestamp | TIMESTAMP | YES | | 대화 시각 | | user_id | UUID | YES | | 사용자 ID (FK → users) - NULL 허용 | | slack_user_id | VARCHAR(100) | YES | | Slack User ID (2025-08-26 추가) | --- ## 인덱스 정보 ### 주요 인덱스 - users: email (UNIQUE), username (UNIQUE) - gmail_tokens: user_id (UNIQUE), username, slack_id, robeing_id, oauth_config (GIN), token_data (GIN) - slack_user_mapping: slack_user_id, user_id - workspace_members: workspace_id, user_id - conversation_logs: user_id, robeing_id, created_at - robeing.contacts: robeing_id, name, email - robeing.conversations: robeing_id, timestamp --- ## 외래키 제약 | 테이블 | 컬럼 | 참조 테이블 | 참조 컬럼 | |--------|------|------------|----------| | workspace_members | user_id | users | id | | workspace_members | workspace_id | workspaces | id | | slack_user_mapping | user_id | users | id | | slack_user_mapping | slack_workspace_id | slack_workspaces | id | | gmail_tokens | user_id | users | id | | robeing_stats | user_id | users | id | | conversation_logs | user_id | users | id | --- ## 주의사항 ### 데이터 타입 일관성 - **user_id**: 모든 테이블에서 UUID 타입 사용 - **robeing_id**: VARCHAR(50) 통일 - **timestamp**: TIMESTAMP WITHOUT TIME ZONE 사용 ### 최근 변경사항 (2025-08-26) 1. conversation_logs 테이블 수정: - user_id: NULL 허용으로 변경 (UUID 변환 실패 대응) - slack_user_id: VARCHAR(100) 컬럼 추가 (Slack ID 직접 저장) - 컬럼 구조 실제 테이블과 일치하도록 수정 ### 이전 변경사항 (2025-08-23) 1. gmail_tokens 테이블 구조 변경: - user_id: VARCHAR(100) → UUID로 변경 (users.id 외래키) - username: VARCHAR(50) 컬럼 추가 (빠른 조회용) - slack_id: VARCHAR(50) 컬럼 추가 (Slack 연동용) 2. 외래키 관계 정립: - gmail_tokens.user_id → users.id - 데이터 무결성 보장 ### ✅ 완료된 개선사항 (2025-08-28) 1. ~~일부 테이블의 소유자가 postgres로 되어있어 권한 조정 필요~~ ✅ 해결됨 - gmail_audit_logs: postgres → robeings ✅ - robeing_stats: postgres → robeings ✅ 2. auth_db → main_db로 마이그레이션 완료 ✅ 3. gmail_tokens_old 백업 테이블 정리 검토 (선택사항) --- **문서 끝**