[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입니다.
목차
- erdcloud url (https://www.erdcloud.com/d/LAfibuDQkjAm43J27)
- 테이블 관계도 요약
- Enum 값 정의
- 테이블 상세 명세
- 3-1. ai_job
- 3-2. build_sessions
- 3-3. build_items
- 3-4. persona
- 3-5. persona_trait
- 3-6. ai_simulation_session
- 3-7. ai_simulation_message
- 3-8. ai_simulation_report
- 3-9. ai_practice_session
- 3-10. ai_practice_chat
- 3-11. chat_delegation
- 3-12. face_analysis
- 3-13. face_analysis_result
- 3-14. face_compatibility
- 3-15. saju_analysis
- 3-16. saju_analysis_result
- 3-17. saju_compatibility
- 3-18. photo_verification
- 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_idFK가 없으므로 추가 검토 필요
연관 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 |
- |