DOCS/300_architecture/plans/250910_happybell80_PostgreSQL_테이블_변경_계획.md
happybell80 30b6d7e444 PostgreSQL 테이블 실제 구조와 코드 불일치 문서화
- 테이블명 불일치: user vs users, 단수형 vs 복수형
- 존재하지 않는 테이블: slack_user_mapping, gmail_audit_logs 등
- 구조 차이: workspace 중심 vs company-team 계층
- 비어있는 테이블 명시
2025-09-11 20:20:20 +09:00

13 KiB

PostgreSQL 데이터베이스 테이블 변경 계획

작성 정보

  • 작성일: 250910
  • 작성자: happybell80
  • 목적: PostgreSQL 테이블 구조 대대적 변경에 따른 영향 범위 파악 및 수정 계획

1. 데이터베이스 연결 정보

메인 데이터베이스

  • main_db: postgresql://robeings:robeings@192.168.219.45:5432/main_db
  • robeing_metrics: postgresql://postgres:@172.17.0.1:5432/robeing_metrics

사용 라이브러리

저장소 라이브러리
auth-server SQLAlchemy, asyncpg, psycopg2
rb8001 SQLAlchemy
rb10508_micro asyncpg
frontend-base asyncpg
robeing-gateway SQLAlchemy, asyncpg
robeing-monitor SQLAlchemy, asyncpg
skill-email psycopg2

2. 테이블별 사용 위치 상세

2.1 user 테이블 (실제 DB: user, 코드: users 참조)

실제 DB 컬럼: id(UUID), team_id(FK), email, username, oauth_provider, oauth_id, created_at, updated_at 코드 모델 차이:

  • auth-server: picture 컬럼 (DB에 없음)
  • robeing-gateway: avatar_url, provider, provider_id (DB에 없음)
파일 경로 라인 번호 작업 내용
auth-server/app/models/user.py 21-35 테이블 모델 정의 (picture 컬럼)
auth-server/app/providers/gmail_passport.py 178 SELECT id FROM users WHERE username = $1
auth-server/app/providers/gmail_passport.py 187 SELECT username FROM users WHERE id = $1
robeing-gateway/app/database.py 98-112 JOIN 쿼리 (workspace_members, workspaces와 함께)
robeing-gateway/app/database.py 182-191 SELECT * FROM users WHERE username = $1
robeing-gateway/app/database.py 321-328 SELECT * FROM users (전체 조회)
robeing-gateway/app/models.py 11-24 테이블 모델 정의 (avatar_url 컬럼)

2.2 company/team 테이블 (실제 DB: company+team, 코드: workspaces 참조)

실제 DB: company(id, name, url) + team(id, company_id, name) 구조 코드 모델: workspaces 테이블 참조 (DB에 없음)

파일 경로 라인 번호 작업 내용
auth-server/app/models/workspace.py 15-31 테이블 모델 정의
auth-server/scripts/run_migration.py 54 SELECT id, name, subdomain, robeing_id FROM workspaces
auth-server/migrations/add_user_workspace_tables.sql 25-28 ALTER TABLE companies RENAME TO workspaces
robeing-gateway/app/database.py 98-112 JOIN 쿼리
robeing-gateway/app/database.py 216-230 JOIN 쿼리 (workspace_members와 함께)
robeing-gateway/app/models.py 26-44 테이블 모델 정의

2.3 workspace_member 테이블 (실제 DB: workspace_member, 레코드 0건)

실제 DB 컬럼: user_id(FK), role(user_role enum), created_at, updated_at 코드 모델: workspace_members 테이블 참조 (복수형 차이)

파일 경로 라인 번호 작업 내용
auth-server/app/models/user.py 46-60 테이블 모델 정의
auth-server/migrations/add_user_workspace_tables.sql 41-52 CREATE TABLE 정의
robeing-gateway/app/database.py 98-112 JOIN 쿼리
robeing-gateway/app/database.py 263-266 중복 체크 쿼리
robeing-gateway/app/database.py 274-282 UPDATE 쿼리
robeing-gateway/app/database.py 285-299 INSERT 쿼리 (gen_random_uuid() 사용)
robeing-gateway/app/models.py 46-60 테이블 모델 정의

2.4 slack_user_mapping 테이블 (실제 DB: 없음)

코드에서 참조하나 실제 DB에 테이블 없음

파일 경로 라인 번호 작업 내용
auth-server/app/providers/slack.py 266 SELECT user_id FROM slack_user_mapping WHERE slack_user_id = :slack_user_id AND slack_workspace_id = :slack_workspace_id
auth-server/app/providers/slack.py 308-312 INSERT INTO slack_user_mapping ... DO UPDATE SET (slack_user_id, slack_workspace_id 조합 기준)
rb8001/app/router/router.py 92 SELECT user_id FROM slack_user_mapping WHERE slack_user_id = :slack_id
robeing-gateway/app/main.py 479-486 SELECT user_id FROM slack_user_mapping WHERE slack_user_id = $1

2.5 slack_workspace 테이블 (실제 DB: slack_workspace, 2건)

실제 DB 컬럼: id(UUID), team_id(FK), team_name, bot_token, bot_user_id, app_id, scope(json), created_at, updated_at 코드 모델: slack_workspaces 참조 (복수형 차이)

파일 경로 라인 번호 작업 내용
auth-server/app/models/workspace.py 43-62 테이블 모델 정의 (현재 company_id로 정의됨)
auth-server/migrations/add_user_workspace_tables.sql 60-76 ALTER TABLE 정의 (company_id → workspace_id 변경)
robeing-gateway/app/main.py 522-525 SELECT bot_token FROM slack_workspaces WHERE team_id = $1
robeing-gateway/app/main.py 567-570 SELECT bot_token FROM slack_workspaces WHERE team_id = $1

2.6 gmail_token 테이블 (실제 DB: gmail_token, 0건)

실제 DB 컬럼: user_id(FK), token_data(jsonb), oauth_config(jsonb), created_at, updated_at 코드 모델: gmail_tokens 참조 (복수형 차이), 추가 컬럼 사용

파일 경로 라인 번호 작업 내용
auth-server/app/providers/gmail_passport.py 193-198 INSERT INTO gmail_tokens ... DO UPDATE SET
auth-server/app/providers/gmail_passport.py 354 SELECT token_data FROM gmail_tokens WHERE user_id = $1
auth-server/app/providers/gmail_passport.py 370 DELETE FROM gmail_tokens WHERE user_id = $1
skill-email/services/db_credentials_provider.py 60-70 SELECT 쿼리 (is_equipped 필터)
skill-email/services/db_credentials_provider.py 163-177 UPDATE 쿼리
skill-email/services/db_credentials_provider.py 231-235 COUNT 쿼리
robeing-monitor/app/api/items.py 97-111 SELECT 쿼리
robeing-monitor/app/api/items.py 185-190 소유권 확인 쿼리
robeing-monitor/app/api/items.py 197-211 UPDATE 쿼리 (장착/해제)
robeing-monitor/app/api/items.py 252-256 UPDATE 쿼리 (해제)
robeing-monitor/app/api/items.py 307-319 SELECT 쿼리 (장착된 토큰)
robeing-monitor/app/api/items.py 384-388 DELETE 쿼리

2.7 gmail_audit_logs 테이블 (실제 DB: 없음)

코드에서 참조하나 실제 DB에 테이블 없음

파일 경로 라인 번호 작업 내용
robeing-monitor/app/api/items.py 214-223 INSERT 쿼리
robeing-monitor/app/api/items.py 263-270 INSERT 쿼리
robeing-monitor/app/api/items.py 395-401 INSERT 쿼리

2.8 robeing 테이블 (실제 DB: robeing, 2건)

실제 DB 컬럼: id(UUID), product_id(FK), team_id(FK), memory, compute, react, empathy, leadership, created_at, updated_at 코드 모델: robeing_stats 테이블 참조 (테이블명 불일치)

파일 경로 라인 번호 작업 내용
rb8001/app/state/database.py 24-38 테이블 모델 정의
rb10508_micro/app/api/endpoints.py 155-161 SELECT 쿼리
robeing-monitor/app/state/database.py 19-33 테이블 모델 정의
robeing-monitor/app/state/state_service.py 55 SELECT 쿼리
robeing-monitor/app/state/state_service.py 59-62 INSERT 쿼리
robeing-monitor/app/state/state_service.py 81 SELECT 쿼리
robeing-monitor/app/state/state_service.py 215 SELECT 전체 조회
robeing-monitor/app/api/items.py 169-173 SELECT level 쿼리

2.9 robeing_settings 테이블 (실제 DB: 없음)

코드에서 참조하나 실제 DB에 테이블 없음

파일 경로 라인 번호 작업 내용
rb8001/app/state/database.py 40-50 테이블 모델 정의
robeing-monitor/app/state/database.py 35-45 테이블 모델 정의
robeing-monitor/app/state/state_service.py 110 SELECT 쿼리
robeing-monitor/app/state/state_service.py 114-117 INSERT 쿼리
robeing-monitor/app/state/state_service.py 133 SELECT 쿼리

2.10 conversation_log 테이블 (실제 DB: conversation_log, 0건)

실제 DB 컬럼: user_id(FK), message, response, intent, created_at, updated_at 코드 모델: conversation_logs 참조 (복수형 차이), 추가 컬럼 사용

파일 경로 라인 번호 작업 내용
rb8001/app/state/database.py 52-65 테이블 모델 정의 (slack_user_id 포함)
rb8001/app/state/database.py 86-92 SELECT 쿼리 (최근 대화, slack_user_id 포함)
rb8001/app/router/router.py 464-496 INSERT 쿼리 (slack_user_id 포함)
robeing-monitor/app/state/database.py 47-59 테이블 모델 정의 (slack_user_id 없음)
robeing-monitor/app/state/state_service.py 156-159 INSERT 쿼리 (slack_user_id 없음)
robeing-monitor/app/state/state_service.py 173-177 SELECT 쿼리 (최근 로그, slack_user_id 없음)
robeing-monitor/app/state/state_service.py 194-203 SELECT 쿼리 (7일간, slack_user_id 없음)

2.11 user_preference 테이블 (실제 DB: user_preference, 0건)

실제 DB 컬럼: user_id(FK), slack_user_id, news_keywords[], briefing_enabled, briefing_time, created_at, updated_at 코드 모델: user_preferences 참조 (복수형 차이)

파일 경로 라인 번호 작업 내용
rb8001/app/skills/dm_skill.py 466 SELECT news_keywords WHERE user_id = :user_id
rb8001/app/skills/dm_skill.py 471 SELECT news_keywords WHERE slack_user_id = :slack_user_id
robeing-monitor/app/api/monitor.py 148-165 SELECT 쿼리
robeing-monitor/app/api/monitor.py 276-292 UPDATE 쿼리 (동적 쿼리 생성)
robeing-monitor/app/api/monitor.py 309-316 INSERT 쿼리

2.12 news 테이블 (실제 DB: news, 0건)

실제 DB 컬럼: user_id(FK), data(jsonb), created_at, updated_at 코드 참조: 확인 필요

2.13 product 테이블 (실제 DB: product, 1건)

실제 DB 컬럼: id(UUID), name, app_id, scope(json), created_at, updated_at 코드 참조: 확인 필요

파일 경로 라인 번호 작업 내용
frontend-base/backend/metrics_database.py 58-60 INSERT INTO system_metrics
frontend-base/backend/metrics_database.py 93-100 SELECT (time_bucket 사용)

3. 수정 작업 체크리스트

3.1 테이블 구조 변경 시

  • SQLAlchemy 모델 클래스 수정
  • Migration 스크립트 작성
  • 기존 데이터 마이그레이션 계획

3.2 컬럼명 변경 시

  • 모든 SELECT 쿼리 수정
  • 모든 INSERT 쿼리 수정
  • 모든 UPDATE 쿼리 수정
  • 모든 DELETE 쿼리 수정
  • SQLAlchemy 모델 속성명 수정
  • API 응답 필드명 확인

3.3 저장소별 작업

  • auth-server: SQLAlchemy 모델 + asyncpg 쿼리 수정
  • rb8001: SQLAlchemy 모델 + text() 쿼리 수정
  • rb10508_micro: asyncpg 직접 쿼리 수정
  • frontend-base: asyncpg 직접 쿼리 수정
  • robeing-gateway: SQLAlchemy 모델 + asyncpg 쿼리 수정
  • robeing-monitor: SQLAlchemy 모델 + asyncpg 쿼리 수정
  • skill-email: psycopg2 쿼리 수정

3.4 테스트 계획

  • 각 저장소별 단위 테스트
  • 통합 테스트 (API 엔드포인트)
  • 데이터 마이그레이션 테스트
  • 롤백 계획 수립

4. 위험 요소 - 치명적 불일치

  1. 테이블명 전체 불일치:

    • 코드: users, workspaces, workspace_members (복수형)
    • DB: user, company/team, workspace_member (단수형)
  2. 존재하지 않는 테이블 참조:

    • slack_user_mapping (코드 참조, DB 없음)
    • gmail_audit_logs (코드 참조, DB 없음)
    • robeing_settings (코드 참조, DB 없음)
    • workspaces (코드 참조, DB는 company+team)
  3. 구조 불일치:

    • 코드: workspace 중심 구조
    • DB: company → team → user 계층 구조
  4. 비어있는 주요 테이블 (레코드 0건):

    • conversation_log, gmail_token, news, user_preference, workspace_member

5. 작업 우선순위

  1. 긴급: 테이블명 불일치 해결 (user vs users 등)
  2. 높음: 존재하지 않는 테이블 생성 또는 코드 수정
  3. 중간: 컬럼 불일치 해결

6. 롤백 계획

  1. 변경 전 전체 데이터베이스 백업
  2. 각 테이블별 데이터 덤프
  3. 이전 버전 코드 태그 생성
  4. 단계별 배포 (테스트 환경 → 프로덕션)

주의사항:

  • 모든 변경사항은 테스트 환경(rb10508_micro)에서 먼저 검증
  • 프로덕션(rb8001) 적용은 완전한 테스트 후 진행
  • 데이터 손실 방지를 위한 백업 필수