361 lines
12 KiB
Markdown
361 lines
12 KiB
Markdown
# PostgreSQL 테이블 구조
|
|
|
|
## 작성일: 2025-08-20
|
|
## 최종 수정일: 2025-09-24
|
|
## 데이터베이스: main_db
|
|
|
|
---
|
|
|
|
## 1. 조직 관련 테이블
|
|
|
|
### company
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | UUID | NO | PK |
|
|
| name | VARCHAR(255) | NO | |
|
|
| url | VARCHAR(255) | YES | |
|
|
| created_at | TIMESTAMPTZ | YES | |
|
|
| updated_at | TIMESTAMPTZ | YES | |
|
|
|
|
### team
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | UUID | NO | PK |
|
|
| company_id | UUID | NO | FK → company |
|
|
| name | VARCHAR(32) | NO | |
|
|
| created_at | TIMESTAMPTZ | YES | |
|
|
| updated_at | TIMESTAMPTZ | YES | |
|
|
|
|
### user
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | UUID | NO | PK |
|
|
| team_id | UUID | NO | FK → team |
|
|
| email | VARCHAR(255) | NO | UNIQUE |
|
|
| name | VARCHAR(255) | YES | |
|
|
| picture | VARCHAR(500) | YES | |
|
|
| oauth_provider | VARCHAR(50) | YES | google/slack |
|
|
| oauth_id | VARCHAR(255) | YES | |
|
|
| is_active | BOOLEAN | YES | |
|
|
| last_login_at | TIMESTAMPTZ | YES | |
|
|
| created_at | TIMESTAMPTZ | YES | |
|
|
| updated_at | TIMESTAMPTZ | YES | |
|
|
| username | VARCHAR(64) | YES | |
|
|
| is_admin | BOOLEAN | NO | |
|
|
|
|
### workspace_member
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | UUID | NO | PK |
|
|
| user_id | UUID | NO | FK → user |
|
|
| role | user_role | NO | OWNER/MEMBER/GUEST |
|
|
| is_active | BOOLEAN | YES | |
|
|
| joined_at | TIMESTAMP | YES | |
|
|
| updated_at | TIMESTAMP | YES | |
|
|
|
|
---
|
|
|
|
## 2. 제품 및 로빙 테이블
|
|
|
|
### product
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | UUID | NO | PK |
|
|
| name | VARCHAR(32) | NO | |
|
|
| app_id | VARCHAR(16) | YES | |
|
|
| scope | JSON | YES | |
|
|
| description | VARCHAR(256) | YES | |
|
|
| created_at | TIMESTAMPTZ | YES | |
|
|
| updated_at | TIMESTAMPTZ | YES | |
|
|
|
|
### robeing
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | UUID | NO | PK |
|
|
| product_id | UUID | NO | FK → product |
|
|
| team_id | UUID | NO | FK → team |
|
|
| name | VARCHAR(32) | YES | |
|
|
| level | INTEGER | YES | |
|
|
| experience | INTEGER | YES | |
|
|
| memory | INTEGER | YES | |
|
|
| compute | INTEGER | YES | |
|
|
| react | INTEGER | YES | |
|
|
| empathy | INTEGER | YES | |
|
|
| leadership | INTEGER | YES | |
|
|
| updated_at | TIMESTAMPTZ | YES | |
|
|
| created_at | TIMESTAMPTZ | YES | |
|
|
| robeing_container_id | VARCHAR(64) | YES | |
|
|
| robeing_container_url | VARCHAR(128) | YES | |
|
|
|
|
---
|
|
|
|
## 3. Slack 통합 테이블
|
|
|
|
### slack_workspace
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | UUID | NO | PK |
|
|
| team_id | UUID | NO | FK → team |
|
|
| slack_team_id | VARCHAR(32) | YES | |
|
|
| bot_token | VARCHAR(255) | YES | |
|
|
| is_enterprise_install | BOOLEAN | YES | |
|
|
| is_active | BOOLEAN | YES | |
|
|
| installed_at | TIMESTAMPTZ | YES | |
|
|
| updated_at | TIMESTAMPTZ | YES | |
|
|
| created_at | TIMESTAMPTZ | YES | |
|
|
|
|
---
|
|
|
|
## 4. 사용자 설정 및 토큰 테이블
|
|
|
|
### user_preference
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | INTEGER | NO | PK |
|
|
| user_id | UUID | NO | FK → user |
|
|
| slack_user_id | VARCHAR(32) | YES | |
|
|
| news_keywords | VARCHAR(128)[] | YES | |
|
|
| email_filter | VARCHAR(128)[] | YES | |
|
|
| briefing_enabled | BOOLEAN | YES | |
|
|
| briefing_time | TIME | YES | |
|
|
| updated_at | TIMESTAMPTZ | YES | |
|
|
| created_at | TIMESTAMPTZ | YES | |
|
|
|
|
### gmail_token
|
|
| 컬럼명 | 타입 | NULL | 설명 |
|
|
|--------|------|------|------|
|
|
| id | UUID | NO | PK |
|
|
| user_id | UUID | NO | FK → user |
|
|
| token_data | JSONB | YES | |
|
|
| oauth_config | JSONB | YES | |
|
|
| scopes | JSONB | YES | |
|
|
| metadata | JSONB | YES | |
|
|
| expiry | TIMESTAMP | YES | |
|
|
| is_equipped | BOOLEAN | YES | |
|
|
| equipped_to | VARCHAR(50) | YES | |
|
|
| token_type | VARCHAR | YES | |
|
|
| expires_at | DOUBLE PRECISION | YES | |
|
|
| created_at | TIMESTAMPTZ | YES | |
|
|
| updated_at | TIMESTAMPTZ | YES | |
|
|
|
|
---
|
|
|
|
## 5. 로그 및 데이터 테이블
|
|
|
|
### conversation_log
|
|
- **용도**: 대화 기록
|
|
- **Primary Key**: id (INTEGER)
|
|
|
|
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
|
|--------|------|------|--------|------|
|
|
| id | INTEGER | NO | | PK |
|
|
| user_id | UUID | NO | | FK → user |
|
|
| channel_id | VARCHAR(16) | YES | | |
|
|
| message | VARCHAR | YES | | |
|
|
| response | VARCHAR | YES | | |
|
|
| intent | VARCHAR(256) | YES | | |
|
|
| confidence | DOUBLE PRECISION | YES | | |
|
|
| thread_ts | VARCHAR(128) | YES | | |
|
|
| timestamp | TIMESTAMPTZ | YES | | |
|
|
| channel_type | VARCHAR(32) | YES | | |
|
|
|
|
### intent_* (동적 의도 레지스트리)
|
|
- **용도**: 제로샷 의도 분류 설정을 DB에서 관리
|
|
- **관련 테이블**
|
|
- `intents`: 의도 메타데이터 (id, name, description, active, created_at, updated_at)
|
|
- `intent_prototypes`: 의도별 임베딩(pgvector) 버전/출처 기록
|
|
- `intent_thresholds`: semantic/LLM 경로별 임계값 관리
|
|
- `intent_path_stats`: fastpath/semantic/llm/clarify 경로 별 베타분포 파라미터(alpha, beta) 저장
|
|
|
|
SemanticIntentClassifier는 위 테이블에서 활성화된 의도를 불러오고, 프로토타입/임계값이 없을 경우 YAML 레지스트리로 폴백합니다. 이 구조 덕분에 신규 의도를 추가할 때 DB 레코드만 업데이트하면 서비스가 재시작 없이 최신 의도 설명을 사용할 수 있습니다.
|
|
|
|
### news
|
|
- **용도**: 뉴스 데이터
|
|
- **Primary Key**: id (UUID)
|
|
|
|
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
|
|--------|------|------|--------|------|
|
|
| id | UUID | NO | | PK |
|
|
| user_id | UUID | YES | | FK → user |
|
|
| data | JSONB | YES | | |
|
|
| created_at | TIMESTAMPTZ | YES | CURRENT_TIMESTAMP | |
|
|
| updated_at | TIMESTAMPTZ | YES | CURRENT_TIMESTAMP | |
|
|
|
|
### rb_news
|
|
- **용도**: 뉴스 발행 관리
|
|
- **Primary Key**: id (UUID)
|
|
|
|
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
|
|--------|------|------|--------|------|
|
|
| id | UUID | NO | gen_random_uuid() | PK |
|
|
| title | TEXT | NO | | |
|
|
| url | TEXT | NO | | UNIQUE |
|
|
| summary | TEXT | YES | | |
|
|
| slack_message_ts | VARCHAR(100) | YES | | |
|
|
| slack_channel_id | VARCHAR(100) | YES | | |
|
|
| is_published | BOOLEAN | YES | false | |
|
|
| published_at | TIMESTAMPTZ | YES | | |
|
|
| created_at | TIMESTAMPTZ | YES | now() | |
|
|
|
|
**인덱스**:
|
|
- `rb_news_pkey`: PRIMARY KEY (id)
|
|
- `rb_news_url_key`: UNIQUE (url)
|
|
- `idx_rb_news_url`: btree (url)
|
|
- `idx_rb_news_slack_message_ts`: btree (slack_message_ts)
|
|
- `idx_rb_news_created_at`: btree (created_at DESC)
|
|
|
|
### team_document
|
|
- **용도**: 팀 문서 RAG 시스템
|
|
- **Primary Key**: id (UUID)
|
|
|
|
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
|
|--------|------|------|--------|------|
|
|
| id | UUID | NO | gen_random_uuid() | PK |
|
|
| team_id | UUID | NO | | FK → team |
|
|
| filename | VARCHAR(255) | NO | | |
|
|
| file_hash | VARCHAR(64) | NO | | SHA256 |
|
|
| file_size | BIGINT | YES | | bytes |
|
|
| mime_type | VARCHAR(100) | YES | | |
|
|
| storage_path | TEXT | NO | | /mnt/hdd/uploads/{team_id}/ |
|
|
| text_content | TEXT | YES | | |
|
|
| chunk_count | INTEGER | YES | 0 | ChromaDB 청크 수 |
|
|
| processing_status | VARCHAR(20) | YES | 'pending' | pending/completed/failed |
|
|
| metadata | JSONB | YES | '{}' | uploaded_by, tags, summary 등 |
|
|
| created_at | TIMESTAMPTZ | YES | CURRENT_TIMESTAMP | |
|
|
| updated_at | TIMESTAMPTZ | YES | CURRENT_TIMESTAMP | |
|
|
|
|
**인덱스**:
|
|
- `idx_team_doc_hash`: UNIQUE (team_id, file_hash) - 팀별 파일 중복 방지
|
|
|
|
---
|
|
|
|
### naverworks_token
|
|
- **용도**: NAVER WORKS OAuth 토큰 및 Passport 정보
|
|
- **Primary Key**: id (UUID)
|
|
- **Unique**: user_id
|
|
- **Foreign Key**: user_id → user(id) ON DELETE CASCADE
|
|
|
|
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
|
|--------|------|------|--------|------|
|
|
| id | UUID | NO | gen_random_uuid() | PK |
|
|
| user_id | UUID | NO | | FK → user |
|
|
| access_token | TEXT | YES | | 개별 저장용 |
|
|
| refresh_token | TEXT | YES | | 개별 저장용 |
|
|
| token_type | VARCHAR(50) | YES | 'Bearer' | |
|
|
| expires_at | TIMESTAMP | YES | | |
|
|
| scopes | JSONB | YES | | |
|
|
| domain_id | VARCHAR(255) | YES | | |
|
|
| service_account | VARCHAR(255) | YES | | |
|
|
| metadata | JSONB | YES | | |
|
|
| created_at | TIMESTAMPTZ | YES | CURRENT_TIMESTAMP | |
|
|
| updated_at | TIMESTAMPTZ | YES | CURRENT_TIMESTAMP | |
|
|
| username | VARCHAR(255) | YES | | |
|
|
| account_id | VARCHAR(255) | YES | | |
|
|
| token_data | JSONB | YES | | 통합 저장용 |
|
|
| oauth_config | JSONB | YES | | |
|
|
| is_equipped | BOOLEAN | YES | false | Passport 장착 여부 |
|
|
|
|
**인덱스**:
|
|
- idx_naverworks_token_user_id (user_id)
|
|
- idx_naverworks_token_expires_at (expires_at)
|
|
|
|
**트리거**:
|
|
- update_naverworks_token_updated_at: updated_at 자동 갱신
|
|
|
|
## 6. 기타 정보
|
|
|
|
### Custom Types
|
|
- **user_role**: ENUM (OWNER, MEMBER, GUEST)
|
|
|
|
### Functions
|
|
- **update_column_updated_at**: 모든 테이블의 updated_at 자동 갱신 트리거
|
|
|
|
### 외래키 관계
|
|
|
|
| 테이블 | 컬럼 | 참조 테이블 | 참조 컬럼 |
|
|
|--------|------|------------|----------|
|
|
| team | company_id | company | id |
|
|
| user | team_id | team | id |
|
|
| robeing | product_id | product | id |
|
|
| robeing | team_id | team | id |
|
|
| slack_workspace | team_id | team | id |
|
|
| workspace_member | user_id | user | id |
|
|
| conversation_log | user_id | user | id |
|
|
| gmail_token | user_id | user | id |
|
|
| news | user_id | user | id |
|
|
| user_preference | user_id | user | id |
|
|
| team_document | team_id | team | id |
|
|
|
|
---
|
|
|
|
---
|
|
|
|
## 7. 감정 분석 테이블 (robeing_metrics DB)
|
|
|
|
### emotion_readings
|
|
- **용도**: 사용자 및 로빙 감정 분석 시계열 데이터
|
|
- **데이터베이스**: robeing_metrics (TimescaleDB)
|
|
- **특징**: 시계열 하이퍼테이블, Top-p 기반 복합 감정 저장
|
|
|
|
| 컬럼명 | 타입 | NULL | 기본값 | 설명 |
|
|
|--------|------|------|--------|------|
|
|
| created_at | TIMESTAMPTZ | NO | | 파티션 키 |
|
|
| user_id | UUID | YES | | user 테이블 참조 |
|
|
| company_id | UUID | YES | | |
|
|
| robeing_id | VARCHAR(50) | YES | | |
|
|
| emotion_type | VARCHAR(20) | YES | | user/robeing |
|
|
| probs | JSONB | NO | | 7개 감정 확률 분포 |
|
|
| entropy | DOUBLE PRECISION | YES | | |
|
|
| model_version | VARCHAR(50) | YES | | onnx-7emotions-v1 등 |
|
|
| meta | JSONB | YES | | source, message_length 등 |
|
|
| text_hash | VARCHAR(64) | YES | | SHA256 |
|
|
| top_emotions | JSONB | YES | | [{"label", "probability"}] |
|
|
| cumulative_p | DOUBLE PRECISION | YES | | Top-p 70% |
|
|
|
|
**인덱스**:
|
|
- `emotion_readings_created_at_idx`: btree (created_at DESC)
|
|
- `idx_emotion_user_time`: btree (user_id, created_at DESC)
|
|
- `idx_emotion_company_time`: btree (company_id, created_at DESC)
|
|
- `idx_emotion_robeing_time`: btree (robeing_id, created_at DESC)
|
|
- `idx_emotion_type`: btree (emotion_type, created_at DESC)
|
|
|
|
**제약 조건**:
|
|
- `emotion_readings_emotion_type_check`: emotion_type IN ('user', 'robeing')
|
|
|
|
**트리거**:
|
|
- `ts_insert_blocker`: TimescaleDB 하이퍼테이블 삽입 제어
|
|
|
|
**예시 데이터**:
|
|
```json
|
|
{
|
|
"top_emotions": [
|
|
{"label": "fear", "probability": 0.499},
|
|
{"label": "neutral", "probability": 0.335}
|
|
],
|
|
"cumulative_p": 0.833,
|
|
"probs": {
|
|
"fear": 0.499, "neutral": 0.335, "anger": 0.056,
|
|
"sadness": 0.048, "disgust": 0.032, "surprise": 0.018, "happiness": 0.012
|
|
},
|
|
"entropy": 1.234
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 주의사항
|
|
|
|
### 데이터베이스 정보
|
|
- **main_db**: 주요 서비스 데이터 (PostgreSQL)
|
|
- 소유자: robeings
|
|
- 테이블: user, team, robeing, conversation_log 등
|
|
- **robeing_metrics**: 시계열 메트릭 데이터 (TimescaleDB)
|
|
- 테이블: emotion_readings
|
|
- 특징: 시간 기반 파티셔닝, 자동 압축, retention 정책
|
|
- **타임스탬프**: TIMESTAMPTZ 사용 (WITH TIME ZONE)
|
|
- **자동 갱신**: update_column_updated_at 트리거로 updated_at 자동 관리
|
|
- **UUID 기반**: 주요 테이블 모두 UUID 사용
|
|
|
|
---
|
|
|
|
**문서 끝** |