Search
🧧

테이블 구성

CATI 서비스 데이터베이스 설계 문서

목차

1. 설문 관리

surveys

설명: 설문지의 기본 정보를 저장하는 메인 테이블
컬럼명
타입
설명
idx
INT
기본키 (Auto Increment)
survey_uuid
VARCHAR(255)
설문 고유 식별자
ver
INT
설문 버전
title
JSON
설문 제목 (다국어 지원)
survey_type
VARCHAR(255)
설문 유형
translation
JSON
번역 데이터
logicflow
JSON
로직 플로우 정의
design
JSON
디자인 설정
setting
JSON
설문 설정
enabled
TINYINT
활성화 여부 (1: 활성, 0: 비활성)
category
VARCHAR(255)
카테고리
subcategory
VARCHAR(255)
서브카테고리
category_id
VARCHAR(255)
카테고리 ID
created_at
TIMESTAMP
생성일시
주요 인덱스:
unique_survey_uuid_ver: survey_uuid + ver 조합의 유일성 보장
idx_survey_uuid: survey_uuid 검색 최적화

survey_question

설명: 각 설문에 속한 질문들을 저장
컬럼명
타입
설명
idx
INT
기본키 (Auto Increment)
survey_id
INT
surveys 테이블 참조 (FK)
id
VARCHAR(255)
질문 고유 ID
title
JSON
질문 제목 (다국어 지원)
description
JSON
질문 설명
addinfo
JSON
추가 정보
question_type
ENUM
질문 유형 ('short-text', 'single-choice')
question_list
JSON
선택지 리스트 (single-choice용)
options
JSON
질문 옵션 설정
attachments
JSON
첨부파일 정보
sort_order
INT
질문 순서
created_at
TIMESTAMP
생성일시
is_unique
TINYINT(1)
고유성 체크 (computed column)
주요 인덱스:
unique_id_with_survey: 동일 설문 내 질문 ID 중복 방지
외래키:
survey_idsurveys(survey_id) ON DELETE CASCADE

survey_session

설명: 실제 통화 세션 정보를 관리
컬럼명
타입
설명
id
INT
기본키 (Auto Increment)
session_key
VARCHAR(255)
세션 고유 키
campaign_uuid
CHAR(36)
캠페인 UUID (NULL 가능)
target_uuid
CHAR(36)
타겟 UUID (NULL 가능)
phone_number
VARCHAR(20)
호출된 전화번호
survey_uuid
VARCHAR(255)
설문 UUID
ver
INT
설문 버전
useridx
INT
사용자 인덱스 (NULL 가능)
progress
VARCHAR(150)
현재 진행 상태
history_stack
JSON
질문 이동 히스토리
status
ENUM
세션 상태 ('in-progress', 'completed', 'expired', 'initiated', 'terminated', 'failed')
started_at
TIMESTAMP
시작 시각
completed_at
TIMESTAMP
완료 시각
call_duration_seconds
INT
통화 시간 (초)
termination_reason
VARCHAR(255)
종료 사유
last_activity_at
TIMESTAMP
마지막 활동 시각
created_at
TIMESTAMP
생성일시
주요 인덱스:
unique_session_key: 세션 키 유일성 보장
idx_campaign_uuid: 캠페인별 세션 조회
idx_phone_number: 전화번호별 조회

2. 전화번호 관리

contact_groups

설명: 전화번호를 그룹으로 관리
컬럼명
타입
설명
group_id
INT
기본키 (Auto Increment)
group_uuid
CHAR(36)
그룹 고유 식별자
name
VARCHAR(255)
그룹명
description
TEXT
그룹 설명
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
사용 예시:
"VIP 고객"
"신규 회원"
"재구매 타겟"

contacts

설명: 개별 전화번호 정보를 저장
컬럼명
타입
설명
contact_id
INT
기본키 (Auto Increment)
contact_uuid
CHAR(36)
연락처 고유 식별자
phone_number
VARCHAR(20)
전화번호
name
VARCHAR(255)
이름 (선택)
metadata
JSON
추가 메타데이터 (예: 나이, 지역 등)
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
주요 인덱스:
idx_phone_number: 전화번호 검색 최적화

contact_group_members

설명: 그룹과 연락처의 N:N 관계 매핑
컬럼명
타입
설명
id
INT
기본키 (Auto Increment)
group_uuid
CHAR(36)
그룹 UUID (FK)
contact_uuid
CHAR(36)
연락처 UUID (FK)
created_at
TIMESTAMP
생성일시
주요 인덱스:
unique_group_contact: 동일 그룹 내 중복 연락처 방지
외래키:
group_uuidcontact_groups(group_uuid) ON DELETE CASCADE
contact_uuidcontacts(contact_uuid) ON DELETE CASCADE

3. 캠페인 관리

survey_campaigns

설명: 설문 캠페인의 기본 정보 관리
컬럼명
타입
설명
campaign_id
INT
기본키 (Auto Increment)
campaign_uuid
CHAR(36)
캠페인 고유 식별자
survey_uuid
VARCHAR(255)
대상 설문 UUID
name
VARCHAR(255)
캠페인명
status
ENUM
캠페인 상태 ('scheduled', 'running', 'paused', 'completed', 'cancelled')
scheduled_at
TIMESTAMP
예약 시각
started_at
TIMESTAMP
시작 시각
completed_at
TIMESTAMP
완료 시각
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
워크플로우:
1.
scheduled → running
2.
running → paused (일시정지 가능)
3.
paused → running (재개)
4.
running → completed (정상 완료)
5.
→ cancelled (중단)

campaign_targets

설명: 캠페인별 실제 호출 대상 목록 (스냅샷)
컬럼명
타입
설명
target_id
INT
기본키 (Auto Increment)
target_uuid
CHAR(36)
타겟 고유 식별자
campaign_uuid
CHAR(36)
캠페인 UUID (FK)
contact_uuid
CHAR(36)
연락처 UUID (FK)
phone_number
VARCHAR(20)
전화번호 (스냅샷)
name
VARCHAR(255)
이름 (스냅샷)
status
ENUM
호출 상태 ('pending', 'calling', 'completed', 'failed', 'skipped')
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
참고:
캠페인 생성 시 contacts 데이터를 복사하여 저장
이후 contacts 변경되어도 캠페인 데이터는 영향받지 않음
외래키:
campaign_uuidsurvey_campaigns(campaign_uuid) ON DELETE CASCADE
contact_uuidcontacts(contact_uuid) ON DELETE CASCADE

campaign_call_queue

설명: 호출 대기열 및 순서 관리
컬럼명
타입
설명
queue_id
INT
기본키 (Auto Increment)
campaign_uuid
CHAR(36)
캠페인 UUID (FK)
target_uuid
CHAR(36)
타겟 UUID (FK)
priority
INT
우선순위 (높을수록 우선)
status
ENUM
큐 상태 ('queued', 'processing', 'completed', 'failed')
retry_count
INT
재시도 횟수
max_retry
INT
최대 재시도 횟수 (기본 3)
next_retry_at
TIMESTAMP
다음 재시도 시각
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
주요 인덱스:
idx_campaign_status: 캠페인별 상태 조회
idx_next_retry: 재시도 스케줄링
외래키:
campaign_uuidsurvey_campaigns(campaign_uuid) ON DELETE CASCADE
target_uuidcampaign_targets(target_uuid) ON DELETE CASCADE

4. 응답 데이터 & 호출 관리

survey_responses

설명: 설문 응답 전체 정보
컬럼명
타입
설명
response_id
INT
기본키 (Auto Increment)
response_uuid
CHAR(36)
응답 고유 식별자
session_key
VARCHAR(255)
세션 키
survey_uuid
VARCHAR(255)
설문 UUID
ver
INT
설문 버전
is_completed
TINYINT
완료 여부 (1: 완료, 0: 미완료)
completed_at
TIMESTAMP
완료일시
created_at
TIMESTAMP
생성일시
주요 인덱스:
idx_session_key: 세션별 응답 조회
idx_survey_uuid_ver: 설문별 응답 집계

response_answers

설명: 각 질문별 개별 답변
컬럼명
타입
설명
answer_id
INT
기본키 (Auto Increment)
answer_uuid
CHAR(36)
답변 고유 식별자
response_uuid
CHAR(36)
응답 UUID (FK)
question_id
VARCHAR(255)
질문 ID
answer_text
TEXT
답변 텍스트 (최종 정제된 답변)
answer_value
VARCHAR(500)
답변 값 (선택지 ID 등)
stt_raw_text
TEXT
STT 원본 텍스트 (검증용)
answered_at
TIMESTAMP
답변일시
데이터 예시:
{ "question_id": "q1", "answer_text": "매우 만족", "answer_value": "choice_1", "stt_raw_text": "저는 매우 만족했어요" }
JSON
복사
외래키:
response_uuidsurvey_responses(response_uuid) ON DELETE CASCADE

call_logs

설명: 개별 호출 시도 이력
컬럼명
타입
설명
log_id
INT
기본키 (Auto Increment)
session_key
VARCHAR(255)
세션 키 (성공 시)
campaign_uuid
CHAR(36)
캠페인 UUID (FK)
target_uuid
CHAR(36)
타겟 UUID (FK)
phone_number
VARCHAR(20)
호출 전화번호
call_status
ENUM
호출 결과 ('success', 'failed', 'no_answer', 'busy', 'rejected')
failure_reason
VARCHAR(500)
실패 사유
call_duration_seconds
INT
통화 시간 (초)
created_at
TIMESTAMP
호출 시각
활용:
호출 성공/실패 통계
실패 원인 분석
재시도 전략 수립
외래키:
campaign_uuidsurvey_campaigns(campaign_uuid) ON DELETE CASCADE
target_uuidcampaign_targets(target_uuid) ON DELETE CASCADE

call_retry_queue

설명: 실패한 호출의 재시도 관리
컬럼명
타입
설명
retry_id
INT
기본키 (Auto Increment)
target_uuid
CHAR(36)
타겟 UUID (FK)
campaign_uuid
CHAR(36)
캠페인 UUID (FK)
phone_number
VARCHAR(20)
전화번호
retry_count
INT
현재 재시도 횟수
max_retry
INT
최대 재시도 횟수 (기본 3)
last_attempt_at
TIMESTAMP
마지막 시도 시각
next_retry_at
TIMESTAMP
다음 시도 예정 시각
status
ENUM
재시도 상태 ('pending', 'processing', 'exhausted')
created_at
TIMESTAMP
생성일시
재시도 로직:
1.
호출 실패 시 → status='pending'
2.
retry_count < max_retry → 재시도 스케줄링
3.
retry_count >= max_retry → status='exhausted'
외래키:
campaign_uuidsurvey_campaigns(campaign_uuid) ON DELETE CASCADE
target_uuidcampaign_targets(target_uuid) ON DELETE CASCADE

5. TTS 캐시 & 음성 설정

tts_cache

설명: TTS 음성 파일 캐싱 시스템
컬럼명
타입
설명
cache_id
INT
기본키 (Auto Increment)
cache_uuid
CHAR(36)
캐시 고유 식별자
survey_uuid
VARCHAR(255)
설문 UUID
question_id
VARCHAR(255)
질문 ID
text_content
TEXT
원본 텍스트
text_hash
CHAR(64)
텍스트 해시 (중복 방지)
voice_profile_uuid
CHAR(36)
음성 프로필 UUID
audio_file_path
VARCHAR(500)
음성 파일 경로
audio_format
VARCHAR(10)
파일 포맷 (기본: mp4)
duration_ms
INT
재생 시간 (밀리초)
file_size_bytes
INT
파일 크기 (바이트)
created_at
TIMESTAMP
생성일시
캐싱 전략:
1.
설문 생성/수정 시 모든 질문 TTS 사전 생성
2.
text_hash로 동일 텍스트 재사용
3.
실시간 TTS 생성 없이 캐시 파일 직접 재생
주요 인덱스:
idx_text_hash: 중복 텍스트 확인
idx_survey_question: 설문-질문 조합 조회

voice_profiles

설명: 음성 커스터마이징 프로필
컬럼명
타입
설명
profile_id
INT
기본키 (Auto Increment)
profile_uuid
CHAR(36)
프로필 고유 식별자
survey_uuid
VARCHAR(255)
설문 UUID (NULL이면 전역)
name
VARCHAR(255)
프로필명
speed
DECIMAL(3,1)
재생 속도 (0.5 ~ 2.0)
gender
ENUM
성별 ('male', 'female')
voice_type
ENUM
음성 타입 ('conversational', 'narration', 'educational')
is_default
TINYINT
기본 프로필 여부
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
설정 예시:
{ "name": "친근한 여성 음성", "speed": 1.0, "gender": "female", "voice_type": "conversational" }
JSON
복사
주요 인덱스:
idx_is_default: 기본 프로필 빠른 조회

session_logs

설명: 세션 중 발생하는 모든 이벤트 로깅
컬럼명
타입
설명
log_id
INT
기본키 (Auto Increment)
session_key
VARCHAR(255)
세션 키
event_type
ENUM
이벤트 타입 ('question_played', 'answer_received', 'retry', 'no_response', 'error', 'terminated')
question_id
VARCHAR(255)
질문 ID (관련 질문이 있는 경우)
event_data
JSON
이벤트 상세 데이터
created_at
TIMESTAMP
발생일시
이벤트 예시:
{ "event_type": "retry", "question_id": "q3", "event_data": { "retry_count": 2, "reason": "no_response", "wait_time_seconds": 10 } }
JSON
복사
활용:
사용자 행동 패턴 분석
문제 질문 식별
시스템 오류 추적
주요 인덱스:
idx_session_key: 세션별 로그 조회
idx_event_type: 이벤트 유형별 분석

6. Security & Analytics

question_logic_rules

설명: 조건부 질문 분기 로직 (Phase 2)
컬럼명
타입
설명
rule_id
INT
기본키 (Auto Increment)
rule_uuid
CHAR(36)
규칙 고유 식별자
survey_uuid
VARCHAR(255)
설문 UUID
source_question_id
VARCHAR(255)
조건 판단 질문 ID
condition_type
ENUM
조건 타입 ('equals', 'contains', 'greater_than', 'less_than', 'in_range')
condition_value
JSON
조건 값
target_question_id
VARCHAR(255)
이동할 질문 ID
action
ENUM
실행 액션 ('show', 'skip', 'jump_to')
priority
INT
우선순위 (높을수록 우선)
is_active
TINYINT
활성화 여부
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
로직 예시:
{ "source_question_id": "q1", "condition_type": "equals", "condition_value": {"answer": "yes"}, "target_question_id": "q2", "action": "jump_to" }
JSON
복사
시나리오:
Q1: 제품을 사용해보셨나요? → "예" 선택
→ Q2로 이동: 만족도를 평가해주세요
Q1: 제품을 사용해보셨나요? → "아니오" 선택
→ Q3로 이동: 관심 있으신 이유는?

pii_masking_rules

설명: 개인정보 자동 마스킹 규칙
컬럼명
타입
설명
rule_id
INT
기본키 (Auto Increment)
rule_uuid
CHAR(36)
규칙 고유 식별자
rule_name
VARCHAR(255)
규칙명
pattern
VARCHAR(500)
정규식 패턴
mask_type
ENUM
마스킹 타입 ('phone', 'ssn', 'card', 'email', 'custom')
replacement
VARCHAR(100)
대체 문자열 (기본: ***)
is_active
TINYINT
활성화 여부
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
마스킹 예시:
원본: "제 전화번호는 010-1234-5678입니다" 마스킹: "제 전화번호는 010-****-****입니다" 원본: "카드번호 1234-5678-9012-3456으로 결제했어요" 마스킹: "카드번호 ****-****-****-3456으로 결제했어요"
Plain Text
복사
주요 인덱스:
idx_mask_type: 타입별 규칙 조회

profanity_filters

설명: 욕설 및 부적절한 언어 필터
컬럼명
타입
설명
filter_id
INT
기본키 (Auto Increment)
filter_uuid
CHAR(36)
필터 고유 식별자
word
VARCHAR(255)
필터링 단어
severity
ENUM
심각도 ('low', 'medium', 'high')
language
VARCHAR(10)
언어 코드 (기본: ko)
is_active
TINYINT
활성화 여부
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
심각도 정책:
low: 경고 로그만 기록
medium: 응답 재요청
high: 세션 즉시 종료
주요 인덱스:
unique_word_language: 언어별 단어 중복 방지

survey_analytics

설명: 일별 설문/캠페인 통계
컬럼명
타입
설명
analytics_id
INT
기본키 (Auto Increment)
survey_uuid
VARCHAR(255)
설문 UUID
campaign_uuid
CHAR(36)
캠페인 UUID (NULL 가능)
date
DATE
통계 날짜
total_calls
INT
총 호출 수
successful_calls
INT
성공 호출 수
failed_calls
INT
실패 호출 수
completed_surveys
INT
완료된 설문 수
avg_duration_seconds
DECIMAL(10,2)
평균 통화 시간 (초)
completion_rate
DECIMAL(5,2)
완료율 (%)
created_at
TIMESTAMP
생성일시
updated_at
TIMESTAMP
수정일시
계산 공식:
completion_rate = (completed_surveys / successful_calls) * 100
Plain Text
복사
주요 인덱스:
unique_survey_campaign_date: 날짜별 중복 방지
idx_date: 기간별 조회

system_metrics

설명: 시스템 성능 지표 측정
컬럼명
타입
설명
metric_id
INT
기본키 (Auto Increment)
metric_type
ENUM
측정 타입 ('tts_latency', 'stt_latency', 'llm_latency', 'total_turn_time', 'error_rate')
avg_value_ms
DECIMAL(10,2)
평균 값 (밀리초)
min_value_ms
DECIMAL(10,2)
최소 값 (밀리초)
max_value_ms
DECIMAL(10,2)
최대 값 (밀리초)
sample_count
INT
샘플 수
measured_at
TIMESTAMP
측정 시각
목표 지표:
Metric
Target
TTS 재생
< 100ms
STT 처리
< 500ms
LLM 응답 검증
< 2000ms
전체 턴 시간
< 2초
주요 인덱스:
idx_metric_type: 타입별 조회
idx_measured_at: 시계열 분석

ERD 관계도 요약

surveys (1) ──< (N) survey_question surveys (1) ──< (N) survey_session surveys (1) ──< (N) survey_campaigns contact_groups (1) ──< (N) contact_group_members (N) ──> (1) contacts survey_campaigns (1) ──< (N) campaign_targets survey_campaigns (1) ──< (N) campaign_call_queue survey_campaigns (1) ──< (N) call_logs survey_session (1) ──< (1) survey_responses (1) ──< (N) response_answers survey_campaigns (1) ──< (N) survey_session campaign_targets (1) ──< (N) survey_session
Plain Text
복사

인덱싱 전략

성능 최적화를 위한 주요 인덱스

1.
UUID 인덱스: 모든 UUID 컬럼에 인덱스 설정
2.
복합 인덱스: 자주 함께 조회되는 컬럼 (survey_uuid + ver)
3.
상태 인덱스: ENUM 타입의 상태 컬럼
4.
시간 인덱스: created_at, measured_at 등 시계열 데이터
5.
외래키 인덱스: JOIN 성능 향상

추가 할일

1. 파티셔닝

대용량 데이터 처리를 위해 다음 테이블은 파티셔닝 고려:
session_logs: created_at 기준 월별 파티셔닝
call_logs: created_at 기준 월별 파티셔닝
system_metrics: measured_at 기준 일별 파티셔닝

2. 아카이빙

오래된 데이터는 별도 아카이브 테이블로 이동:
6개월 이상 된 session_logs
1년 이상 된 call_logs

3. 백업 전략

일별 전체 백업
시간별 증분 백업
중요 테이블 (surveys, survey_responses) 실시간 복제
최종 수정일: 2025-12-23