[AI] ERD 테이블 명세 - 100-hours-a-week/KTB4-17th-wiki GitHub Wiki

작성일 : 2026년 09월 08일 작성자 : yuta.jeong

[!NOTE] 이 문서는 AI 서버 전용 PostgreSQL ERD의 테이블 명세입니다. ERDCloud 임포트용 DDL 파일: ai-server-erdcloud.sql 백엔드 RDB와는 별도 스키마이며, member_id 등 외부 참조는 논리적 FK입니다.


목차

  1. erdcloud url (https://www.erdcloud.com/d/LAfibuDQkjAm43J27)
  2. 테이블 관계도 요약
  3. Enum 값 정의
  4. 테이블 상세 명세
  5. API-테이블 매핑

1. 테이블 관계도 요약

ai_job ─────────────────────────┐
                                │ job_id
                         ┌──────┴──────┐
                   face_analysis   saju_analysis
                         │                │
                face_analysis_result  saju_analysis_result
                    ┌────┴────┐       ┌────┴────┐
              face_compatibility   saju_compatibility


build_sessions ──┬── build_items
                 │
               persona ──┬── persona_trait
                         │
                         └── ai_practice_session ── ai_practice_chat

ai_simulation_report (session_id는 Spring 세션 논리 ID)


chat_delegation (독립)

[AI PostgreSQL 제외 · Spring 전용 참고]
ai_simulation_session ── ai_simulation_message
photo_verification

2. Enum 값 정의

ERDCloud에서는 CREATE TYPE을 지원하지 않아 VARCHAR로 대체했습니다. 실제 허용 값은 아래와 같습니다.

필드 용도 허용 값 사용 테이블
비동기 작업 상태 QUEUED, PROCESSING, COMPLETED, FAILED, CANCELED ai_job.status
작업 리소스 타입 FACE_ANALYSIS, SAJU_ANALYSIS, STYLE_EXTRACTION ai_job.resource_type
빌드 세션 상태 IN_PROGRESS, COMPLETED, FAILED build_sessions.status
시뮬레이션 세션 상태 READY, RUNNING, ENDED, CANCELED, FAILED ai_simulation_session.status
시뮬레이션 발화자 MY_PERSONA, TARGET_PERSONA ai_simulation_message.speaker
연습 대화 메시지 상태 GENERATING, COMPLETED, FAILED ai_practice_chat.status
분석 작업 상태 PENDING, PROCESSING, COMPLETED, FAILED face_analysis.status, saju_analysis.status
위임 상태 REQUESTED, IN_PROGRESS, COMPLETED, FAILED chat_delegation.status
성별 FEMALE, MALE saju_analysis.gender

3. 테이블 상세 명세

3-1. ai_job

관상·사주·말투 추출 비동기 작업의 상태를 관리하는 테이블. 작업 접수 시 QUEUED로 생성되며 모델 추론 완료 후 COMPLETED로 전환된다.

컬럼 타입 제약 설명
job_id VARCHAR(100) PK 비동기 작업 ID (예: job_face_4001)
resource_type VARCHAR(20) NOT NULL 작업 대상 리소스 종류 (FACE_ANALYSIS / SAJU_ANALYSIS / STYLE_EXTRACTION)
resource_id BIGINT NOT NULL 백엔드가 생성한 리소스 ID
status VARCHAR(20) NOT NULL, DEFAULT QUEUED 작업 상태
progress SMALLINT NOT NULL, DEFAULT 0 진행률 (0~100)
result JSON 완료 시 결과 데이터 (FaceAnalysisResult, SajuReadingResult, CommunicationStyle 전용 모델)
error_code VARCHAR(100) 실패 시 에러 코드
error_message TEXT 실패 시 에러 메시지
created_at TIMESTAMP NOT NULL 작업 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각

연관 API: GET /ai/api/v1/jobs/{jobId}


3-2. build_sessions

페르소나 온보딩 문답 세션. 사용자가 10단계 질문에 답변하는 과정을 추적한다.

컬럼 타입 제약 설명
id UUID PK 빌드 세션 ID
member_id BIGINT NOT NULL 회원 ID (백엔드 Member 참조)
status VARCHAR(20) NOT NULL, DEFAULT IN_PROGRESS 세션 상태
current_step INT NOT NULL, DEFAULT 1 현재 진행 중인 질문 단계 (1~10)
created_at TIMESTAMP NOT NULL 세션 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각
completed_at TIMESTAMP 세션 완료 시각

연관 API: POST /ai/api/v1/personas/{buildId}/build


3-3. build_items

빌드 세션의 개별 질문-답변 항목. 각 단계(step)마다 AI가 생성한 질문과 사용자의 답변을 저장한다.

컬럼 타입 제약 설명
id BIGSERIAL PK 자동 증가 ID
session_id UUID NOT NULL, FK → build_sessions.id 소속 빌드 세션
step INT NOT NULL 질문 단계 번호
question TEXT AI가 생성한 질문
answer TEXT 사용자 답변
created_at TIMESTAMP NOT NULL 항목 생성 시각
answered_at TIMESTAMP 답변 완료 시각

관계: build_sessions 1 : N build_items


3-4. persona

빌드 세션이 완료된 후 생성되는 사용자 페르소나. 시스템 프롬프트와 성향 요약을 포함한다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
member_id BIGINT NOT NULL 회원 ID
build_session_id UUID NOT NULL, FK → build_sessions.id 생성 근거가 된 빌드 세션
system_prompt TEXT NOT NULL LLM용 시스템 프롬프트
personality_summary JSON 4축 성향 요약 (relationshipPace, conflictStyle, leisureStyle, contactFrequency)
created_at TIMESTAMP NOT NULL 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각

관계: build_sessions 1 : 1 persona

연관 API: POST /ai/api/v1/personas/{buildId}/build, POST /ai/api/v1/personas/{personaId}/style-extractions


3-5. persona_trait

페르소나에 누적되는 성향 특성. 문답 요약(build)에서 생성된다. trait-extractions 폐기로 연습 대화 경유 생성 경로 제거됨.

컬럼 타입 제약 설명
id BIGSERIAL PK 자동 증가 ID
persona_id BIGINT NOT NULL, FK → persona.id 소속 페르소나
category VARCHAR(30) NOT NULL 특성 카테고리 (예: COMMUNICATION, INTEREST)
label VARCHAR(20) NOT NULL 특성 라벨 (예: 직접대화형, 전시관람)
observation_count SMALLINT NOT NULL, DEFAULT 1 관찰 횟수 (누적)
created_at TIMESTAMP NOT NULL 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각

관계: persona 1 : N persona_trait 유니크 제약: (persona_id, category, label) 조합은 중복 불가

연관 API: POST /ai/api/v1/personas/{buildId}/build


3-6. ai_simulation_session

두 페르소나 간의 가상 소개팅 세션. SSE 스트리밍으로 대화가 진행된다. API 정본에서 AI 서버 저장이 취소됨. 아래 컬럼은 Spring 스키마 참고용이며 AI PostgreSQL 마이그레이션 대상이 아니다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
member_id BIGINT NOT NULL 요청 회원 ID
status VARCHAR(20) NOT NULL, DEFAULT READY 세션 상태
max_rounds SMALLINT NOT NULL, DEFAULT 8 현재 서버 정책으로 고정된 라운드 수 (8)
target_id BIGINT NOT NULL 상대 회원 ID
message_count INT NOT NULL, DEFAULT 0 완성된 메시지 수
started_at TIMESTAMP 대화 시작 시각
finished_at TIMESTAMP 대화 종료 시각
created_at TIMESTAMP NOT NULL 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각

개념 관계(Spring): persona 1 : N ai_simulation_session (my/target 각각)

연관 API: POST /ai/api/v1/simulation-sessions/{sessionId}/runs


3-7. ai_simulation_message

가상 소개팅에서 완성된 개별 발화. LLM 토큰 스트림은 내부 버퍼링 후 발화 단위로 저장한다. API 정본에서 AI 서버 저장이 취소됨. 아래 컬럼은 Spring 스키마 참고용이며 AI PostgreSQL 마이그레이션 대상이 아니다.

컬럼 타입 제약 설명
id BIGSERIAL PK 자동 증가 ID
session_id BIGINT NOT NULL, FK → ai_simulation_session.id 소속 세션
sequence_no INT NOT NULL 발화 순서 번호 (1부터 시작)
speaker VARCHAR(20) NOT NULL 발화자 (MY_PERSONA / TARGET_PERSONA)
content TEXT NOT NULL 발화 내용
created_at TIMESTAMP NOT NULL 생성 시각

개념 관계(Spring): ai_simulation_session 1 : N ai_simulation_message 유니크 제약: (session_id, sequence_no) 조합은 중복 불가


3-8. ai_simulation_report

가상 소개팅 대화를 분석한 궁합 리포트. 점수, 요약, 4개 등급 평가를 포함한다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
session_id BIGINT NOT NULL Spring이 관리하는 분석 대상 세션의 논리 ID (AI DB FK 없음)
overall_score INT 종합 점수 (정수 0~100)
summary TEXT 요약문
conversation_flow_grade CHAR(1) 대화 흐름 등급 (A~F)
question_exchange_grade CHAR(1) 질문 교환 등급
interest_expression_grade CHAR(1) 관심 표현 등급
initiative_balance_grade CHAR(1) 주도권 균형 등급
detail_result JSON 상세 분석 결과 (키 미확정)
created_at TIMESTAMP NOT NULL 생성 시각
completed_at TIMESTAMP 분석 완료 시각

논리 관계: Spring의 simulation_session 1 : 1 ai_simulation_report (session_id로 연결, DB FK 없음)

연관 API: POST /ai/api/v1/simulation-sessions/{sessionId}/reports


3-9. ai_practice_session

사용자가 상대 페르소나와 연습 대화를 진행하는 세션.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
member_id BIGINT NOT NULL 회원 ID
target_id BIGINT NOT NULL 대화 상대 회원 ID
status VARCHAR(20) NOT NULL, DEFAULT ACTIVE 세션 상태
created_at TIMESTAMP NOT NULL 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각

관계: persona 1 : N ai_practice_session


3-10. ai_practice_chat

연습 대화의 개별 메시지. 사용자 메시지와 AI 응답을 한 쌍으로 저장한다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
session_id BIGINT NOT NULL, FK → ai_practice_session.id 소속 세션
user_message VARCHAR(500) NOT NULL 사용자 메시지 (최대 500자)
ai_response TEXT AI 응답 (생성 중일 때 NULL)
status VARCHAR(20) NOT NULL, DEFAULT GENERATING 메시지 상태
is_retry BOOLEAN NOT NULL, DEFAULT FALSE 재시도 여부
created_at TIMESTAMP NOT NULL 생성 시각
completed_at TIMESTAMP 응답 완료 시각

관계: ai_practice_session 1 : N ai_practice_chat

연관 API: POST /ai/api/v1/practice-sessions/{sessionId}/messages


3-11. chat_delegation

관계 종료 메시지 위임. AI가 초안 3개를 생성하고 사용자가 선택한 후 최종 메시지를 확정한다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
chat_room_id BIGINT 채팅방 ID (FK 추가 검토 필요)
requester_member_id BIGINT NOT NULL 위임 요청 회원 ID
status VARCHAR(20) NOT NULL, DEFAULT REQUESTED 위임 상태
end_type VARCHAR(10) NOT NULL 종료 유형 (GENTLE / DIRECT / CASUAL)
ending_messages TEXT[] 초안 3건 또는 선택된 초안 목록
final_message TEXT AI가 보정한 최종 메시지
end_reason VARCHAR(30) 종료 사유 (예: AI_DELEGATION_COMPLETED)
created_at TIMESTAMP NOT NULL 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각
completed_at TIMESTAMP 위임 완료 시각

[!WARNING] 백엔드 ERD에 ChatDelegation.chat_room_id FK가 없으므로 추가 검토 필요

연관 API: POST /ai/api/v1/chat-rooms/{roomId}/exit-delegations/{delegationId}/drafts, POST /ai/api/v1/chat-rooms/{roomId}/exit-delegations/{delegationId}/messages


3-12. face_analysis

관상 분석 작업. 비동기 Job으로 처리되며 ai_job과 연결된다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
member_id BIGINT NOT NULL 회원 ID
profile_image_id BIGINT NOT NULL 프로필 사진 ID (백엔드 ProfileImage 참조)
status VARCHAR(20) NOT NULL, DEFAULT PENDING 분석 상태
job_id VARCHAR(100) FK → ai_job.job_id 비동기 Job ID
created_at TIMESTAMP NOT NULL 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각

관계: ai_job 1 : 1 face_analysis

연관 API: POST /ai/api/v1/face-analyses

[!NOTE] 얼굴 계측값(measurements)은 요청 시에만 사용하고 저장하지 않음


3-13. face_analysis_result

관상 분석 결과. 분석 작업 완료 시 생성된다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
face_analysis_id BIGINT NOT NULL, FK → face_analysis.id 분석 작업 ID
summary TEXT NOT NULL 관상 분석 요약문
created_at TIMESTAMP NOT NULL 생성 시각

관계: face_analysis 1 : 1 face_analysis_result


3-14. face_compatibility

두 관상 분석 결과를 비교한 궁합 리포트. AI가 3문단으로 문장화한다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
member_result_id BIGINT NOT NULL, FK → face_analysis_result.id 요청자 관상 분석 결과
target_result_id BIGINT NOT NULL, FK → face_analysis_result.id 상대방 관상 분석 결과
score INT NOT NULL 궁합 점수 (정수 0~100)
detail_report JSON 3문단 리포트 포함 (키 미확정)
created_at TIMESTAMP NOT NULL 생성 시각

관계: face_analysis_result 1 : N face_compatibility (member/target 각각)

연관 API: POST /ai/api/v1/face-compatibility-reports


3-15. saju_analysis

사주 분석 작업. 비동기 Job으로 처리되며 ai_job과 연결된다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
member_id BIGINT NOT NULL 회원 ID
birth_date DATE NOT NULL 생년월일
birth_time VARCHAR(20) 출생 시각 (예: 14:30)
gender VARCHAR(10) NOT NULL 성별 (FEMALE / MALE)
status VARCHAR(20) NOT NULL, DEFAULT PENDING 분석 상태
calendar_type VARCHAR(10) NOT NULL, DEFAULT SOLAR 양력/음력 (SOLAR / LUNAR)
is_leap_month BOOLEAN NOT NULL, DEFAULT FALSE 윤달 여부 (음력일 때만 유의미)
birth_place VARCHAR(100) 출생지 (시간대 보정용)
input_snapshot JSON 요청 시점 생년월일시/성별 스냅샷
job_id VARCHAR(100) FK → ai_job.job_id 비동기 Job ID
created_at TIMESTAMP NOT NULL 생성 시각
updated_at TIMESTAMP NOT NULL 마지막 수정 시각

관계: ai_job 1 : 1 saju_analysis

연관 API: POST /ai/api/v1/saju-readings


3-16. saju_analysis_result

사주 풀이 결과. 분석 작업 완료 시 생성된다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
saju_analysis_id BIGINT NOT NULL, FK → saju_analysis.id 분석 작업 ID
summary TEXT NOT NULL 사주 풀이 요약문
detail_result JSON 사주 풀이 상세 (키 미확정)
created_at TIMESTAMP NOT NULL 생성 시각

관계: saju_analysis 1 : 1 saju_analysis_result


3-17. saju_compatibility

두 사주 분석 결과를 비교한 궁합 리포트. AI가 3문단으로 문장화한다.

컬럼 타입 제약 설명
id BIGINT PK 백엔드 선발급 ID
requester_result_id BIGINT NOT NULL, FK → saju_analysis_result.id 요청자 사주 분석 결과
target_result_id BIGINT NOT NULL, FK → saju_analysis_result.id 상대방 사주 분석 결과
score INT NOT NULL 궁합 점수 (정수 0~100)
detail_result JSON 3문단 리포트 포함 (키 미확정)
created_at TIMESTAMP NOT NULL 생성 시각

관계: saju_analysis_result 1 : N saju_compatibility (requester/target 각각)

연관 API: POST /ai/api/v1/saju-compatibility-reports


3-18. photo_verification

프로필 사진 정면 판정 결과. AI Vision으로 관상 분석에 적합한 정면 사진인지 판별한다. API 정본에서 AI 서버 저장이 취소됨. 아래 컬럼은 Spring 스키마 참고용이며 AI PostgreSQL 마이그레이션 대상이 아니다.

컬럼 타입 제약 설명
id BIGSERIAL PK 자동 증가 ID
profile_image_id BIGINT NOT NULL 프로필 사진 ID (백엔드 ProfileImage 참조)
member_id BIGINT NOT NULL 회원 ID
is_frontal BOOLEAN NOT NULL 정면 사진 여부
confidence DECIMAL(3,2) NOT NULL 판정 신뢰도 (0.00~1.00)
reason TEXT 비정면 판정 시 사유
created_at TIMESTAMP NOT NULL 생성 시각

연관 API: POST /ai/api/v1/profile-images/{profileImageId}/verifications


4. API-테이블 매핑

API 엔드포인트 입력 테이블 결과 저장 테이블
POST /personas/{buildId}/build build_sessions, build_items build_sessions, build_items, persona, persona_trait
POST /personas/{personaId}/trait-extractions ai_practice_session, ai_practice_chat persona_trait (폐기됨)
POST /personas/{personaId}/style-extractions persona persona, ai_job
POST /profile-images/{id}/verifications - - (AI DB 미저장, Spring 전용)
POST /simulation-sessions/{id}/runs persona - (SSE 발화는 Spring 저장)
POST /simulation-sessions/{id}/reports 요청 본문 message ai_simulation_report
POST /practice-sessions/{id}/messages ai_practice_session, persona ai_practice_chat
POST /chat-rooms/{id}/exit-delegations/{id}/drafts chat_delegation chat_delegation
POST /chat-rooms/{id}/exit-delegations/{id}/messages chat_delegation chat_delegation
POST /face-analyses - face_analysis, ai_job
POST /saju-readings - saju_analysis, ai_job
POST /face-compatibility-reports face_analysis_result face_compatibility
POST /saju-compatibility-reports saju_analysis_result saju_compatibility
GET /jobs/{jobId} ai_job -