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 하이퍼테이블 삽입 제어
예시 데이터:
{
"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 사용
문서 끝