SOL Chain of Debate 시뮬레이션 시스템 요구사항
참고: 정확도 산정 방식과 저장/집계 흐름은 “시뮬레이션 정확도 산정 가이드” 문서에서 상세히 다룹니다. 문서: simulation-accuracy.md
1. 개요
1.1 목적
본 문서는 SOL(Sleep Onset Latency) Chain of Debate 시스템의 예측 성능 검증과 개선을 위한 실제 사용자 데이터 기반 시뮬레이션 기능의 요구사항을 정의합니다.
1.2 시뮬레이션 시스템의 필요성
- 모델 검증: 실제 치료 완료 사용자의 데이터로 예측 정확도 객관적 측정
- 성능 개선: 예측 오차 패턴 분석을 통한 알고리즘 튜닝 포인트 발견
- 신뢰도 향상: 배포 전 시스템의 예측 품질 사전 검증
- 연구 지원: 치료 효과성 연구를 위한 예측 모델 성능 데이터 제공
1.3 핵심 시나리오
userId 196과 같은 실제 치료 완료 사용자의 데이터를 활용하여:
- 수면 기록이 7개 이상 축적된 시점(Day 7)부터 시뮬레이션 시작
- 매일 순차적으로 SOL 예측 수행 (Day 8, Day 9, ..., 치료 종료일)
- 각 예측값과 실제 SOL 데이터를 비교하여 정확도 측정
- 전체 치료 주기에 대한 예측 성능 지표 생성
2. 기능 요구사항
2.1 백테스팅 시뮬레이션 (Backtesting Simulation)
백엔드 요구사항
- SIM-FR-BE-001: 시스템은 완료된 치료 주기의 실제 사용자 데이터를 활용한 백테스팅 시뮬레이션을 제공해야 한다.
- 치료 완료 상태(completed)인 사용자만 시뮬레이션 대상으로 선택
- 치료 주기 시작일부터 종료일까지 전체 데이터 활용
- 실제 치료에 영향을 주지 않는 독립적인 시뮬레이션 환경
- SIM-FR-BE-002: 시스템은 TimeMachine과 통합하여 과거 특정 시점의 데이터만 사용하도록 제한해야 한다.
- 각 예측 시점에서 해당 날짜 이후의 데이터는 접근 불가
- TimeMachine의 가상 시간을 시뮬레이션 시점으로 설정
- 시뮬레이션 종료 후 TimeMachine 상태 원복
2.2 순차적 예측 시뮬레이션 (Sequential Prediction)
백엔드 요구사항
- SIM-FR-BE-003: 시스템은 수면 기록 7개 이상 축적 시점부터 매일 순차적 예측을 수행할 수 있어야 한다.
- 최소 시작 조건: Day 7 (수면 기록 7개 이상)
- 권장 시작 조건: Day 14 (수면 기록 14개 이상, 신뢰도 향상)
- 각 예측 시점에서 Chain of Debate 전체 워크플로우 실행
- 예측 결과를 시뮬레이션 전용 테이블에 저장
- SIM-FR-BE-004: 시스템은 각 예측 시점에서 해당 날짜까지의 데이터만 사용해야 한다.
- Day 8 예측 시: Day 1~7 데이터만 사용
- Day 9 예측 시: Day 1~8 데이터만 사용
- 미래 데이터 누출(Future Data Leakage) 방지
- SIM-FR-BE-005: 시스템은 시뮬레이션 도중 실제 예측 시스템에 영향을 주지 않아야 한다.
- 시뮬레이션 전용 StateGraph 워크플로우 사용
- 실제 예측 스케줄링과 독립적인 실행 환경
- 시뮬레이션 결과는 별도 데이터베이스 테이블에 저장
2.3 정확도 검증 시스템 (Accuracy Validation)
백엔드 요구사항
- SIM-FR-BE-006: 시스템은 예측값과 실제 SOL 데이터를 비교하여 정확도 지표를 생성해야 한다.
- Mean Absolute Error (MAE): |예측값 - 실제값|의 평균
- Root Mean Squared Error (RMSE): 예측 오차의 제곱근 평균
- Mean Absolute Percentage Error (MAPE): 백분율 기준 절대 오차
- Accuracy within ±15분: 15분 오차 범위 내 예측 정확도
- SIM-FR-BE-007: 시스템은 시뮬레이션 기간 동안 정확도 추이를 분석해야 한다.
- 일별 정확도 변화 추이
- 치료 초기/중기/후기별 예측 성능 비교
- 데이터 축적량에 따른 정확도 개선 패턴 분석
- SIM-FR-BE-008: 시스템은 에이전트별 예측 성능을 개별 분석해야 한다.
- 5개 전문가 에이전트의 개별 예측 정확도 (수면잠복기, 심리상태, CBT-I, 디지털환경, 멜라토닌시스템)
- 에이전트 간 의견 일치도와 최종 정확도의 상관관계
- 토론 라운드 수와 예측 품질의 관계 분석
- 멜라토닌시스템분석전문가 참여 시 예측 정확도 개선 효과 측정
2.4 시뮬레이션 세션 관리
백엔드 요구사항
- SIM-FR-BE-009: 시스템은 시뮬레이션 세션을 생성하고 관리할 수 있어야 한다.
- 시뮬레이션 세션 고유 ID 생성
- 시작 시간, 완료 시간, 진행 상태 추적
- 시뮬레이션 매개변수 저장 (시작/종료 dayIndex, 사용자 ID 등)
- SIM-FR-BE-010: 시스템은 동시 실행되는 여러 시뮬레이션을 지원해야 한다.
- 사용자별 독립적인 시뮬레이션 환경
- 시뮬레이션 큐를 통한 순차 처리
- 리소스 사용량 모니터링 및 제한 (최대 5개 동시 실행)
- SIM-FR-BE-011: 시스템은 시뮬레이션 실패 시 정확한 오류 정보를 제공해야 한다.
- 실패 시점, 실패 원인, 에러 메시지 상세 기록
- 부분 완료된 시뮬레이션 결과 보존
- 재시작 지점 식별 및 재실행 지원
2.5 성능 최적화
백엔드 요구사항
- SIM-FR-BE-012: 시스템은 시뮬레이션 실행 시간을 최적화해야 한다.
- 단일 예측당 최대 30초 제한 (실제 예측과 동일)
- 병렬 처리 가능한 단계의 최적화
- 데이터 로딩 및 전처리 캐싱
- SIM-FR-BE-013: 시스템은 대용량 시뮬레이션에 대응할 수 있어야 한다.
- 90일 치료 주기 전체 시뮬레이션 지원 (최대 83회 예측)
- 메모리 효율적인 데이터 처리
- 진행 상황 실시간 모니터링
3. 데이터 모델
3.1 시뮬레이션 세션 (SimulationSession)
interface SimulationSession {
id: string; // 시뮬레이션 세션 고유 ID
userId: string; // 대상 사용자 ID
startDayIndex: number; // 시뮬레이션 시작 dayIndex (예: 7)
endDayIndex: number; // 시뮬레이션 종료 dayIndex (예: 90)
simulationType: SimulationType; // BACKTESTING, SEQUENTIAL, BATCH
status: SimulationStatus; // PENDING, RUNNING, COMPLETED, FAILED
totalPredictions: number; // 전체 예측 횟수
completedPredictions: number; // 완료된 예측 횟수
metrics: SimulationMetrics; // 전체 시뮬레이션 지표
parameters: SimulationParams; // 시뮬레이션 실행 매개변수
createdAt: Date;
startedAt?: Date;
completedAt?: Date;
failedAt?: Date;
errorMessage?: string;
}
3.2 시뮬레이션 예측 (SimulationPrediction)
interface SimulationPrediction {
id: string; // 예측 고유 ID
sessionId: string; // 시뮬레이션 세션 ID
dayIndex: number; // 예측 대상 dayIndex
predictedSOL: number; // 예측된 SOL (분)
actualSOL?: number; // 실제 SOL (분)
accuracyMetrics: {
absoluteError: number; // 절대 오차
percentageError: number; // 백분율 오차
isWithinThreshold: boolean; // 15분 임계값 내 여부
};
confidenceScore: number; // 예측 신뢰도 점수
debateInfo: {
participantAgents: string[]; // 참여한 에이전트 목록
debateRounds: number; // 토론 라운드 수
consensusScore: number; // 합의 점수
debateDuration: number; // 토론 소요 시간 (초)
};
agentPredictions: AgentPrediction[]; // 각 에이전트별 개별 예측
executionTime: number; // 예측 실행 시간 (밀리초)
createdAt: Date;
}
3.3 시뮬레이션 지표 (SimulationMetrics)
interface SimulationMetrics {
accuracy: {
mae: number; // Mean Absolute Error
rmse: number; // Root Mean Squared Error
mape: number; // Mean Absolute Percentage Error
accuracyWithin15min: number; // 15분 내 정확도 (%)
};
performance: {
averageExecutionTime: number; // 평균 실행 시간
totalExecutionTime: number; // 전체 실행 시간
successRate: number; // 성공률 (%)
};
debate: {
averageDebateRounds: number; // 평균 토론 라운드
averageConsensusScore: number; // 평균 합의 점수
agentPerformance: AgentMetrics[]; // 에이전트별 성능
};
trends: {
accuracyTrend: DailyAccuracy[]; // 일별 정확도 추이
improvementRate: number; // 정확도 개선률
};
}
4. API 인터페이스
4.1 시뮬레이션 실행 API
// 시뮬레이션 시작
POST /api/sol-prediction/simulation/start
{
userId: string; // 대상 사용자 ID
startDayIndex: number; // 시작 dayIndex (기본값: 7)
endDayIndex?: number; // 종료 dayIndex (기본값: 사용자 치료 종료일)
simulationType: 'backtesting' | 'sequential';
parameters?: {
includeQuestionnaire: boolean; // 설문 데이터 포함 여부
agentSelection: string[]; // 특정 에이전트만 사용
};
}
Response: {
sessionId: string;
status: 'started';
estimatedDuration: number; // 예상 소요 시간 (분)
totalPredictions: number;
}
4.2 시뮬레이션 상태 조회 API
// 시뮬레이션 진행 상태
GET /api/sol-prediction/simulation/{sessionId}/status
Response: {
sessionId: string;
status: SimulationStatus;
progress: {
completed: number;
total: number;
percentage: number;
};
currentDayIndex?: number;
estimatedTimeRemaining?: number; // 남은 예상 시간 (분)
}
4.3 시뮬레이션 결과 조회 API
// 시뮬레이션 전체 결과
GET /api/sol-prediction/simulation/{sessionId}/results
Response: {
session: SimulationSession;
metrics: SimulationMetrics;
predictions: SimulationPrediction[];
charts: {
accuracyTrend: ChartData; // 정확도 추이 차트 데이터
errorDistribution: ChartData; // 오차 분포 차트 데이터
agentComparison: ChartData; // 에이전트 비교 차트 데이터
};
}
// 특정 기간 결과
GET /api/sol-prediction/simulation/{sessionId}/results?from=Day15&to=Day30&metrics=accuracy,debate
// 에이전트별 성능 비교
GET /api/sol-prediction/simulation/{sessionId}/agents/performance
4.4 배치 시뮬레이션 API
// 여러 사용자 배치 시뮬레이션
POST /api/sol-prediction/simulation/batch
{
userIds: string[]; // 대상 사용자 ID 목록
simulationConfig: {
startDayIndex: number;
endDayIndex?: number;
simulationType: 'backtesting';
};
}
Response: {
batchId: string;
sessionIds: string[]; // 각 사용자별 세션 ID
status: 'queued';
}
5. 시뮬레이션 워크플로우
5.1 시뮬레이션 실행 흐름
1. 시뮬레이션 요청 수신 (userId 입력)
↓
2. UserCycle 조회 및 날짜 매핑
a. 사용자의 가장 최근 userCycleId 조회 (status = 'COMPLETED')
b. userCycle.startedAt 조회 및 타임존 확인
c. dayIndex → 실제 날짜(YYYY-MM-DD) 매핑 테이블 생성
d. Firestore 데이터 존재 여부 검증 (최소 1개 date 필요)
↓
3. 대상 사용자 데이터 검증
↓
4. SimulationSession 생성
↓
5. TimeMachine 설정 (가상 시간)
↓
6. 순차적 예측 실행 루프:
For dayIndex = startDayIndex to endDayIndex:
a. 해당 시점까지의 데이터 로딩 (Firestore + PostgreSQL)
b. SimulationStateGraph 실행
c. 예측 결과 저장
d. 실제값과 비교하여 정확도 계산
↓
7. 전체 시뮬레이션 지표 계산
↓
8. SimulationSession 완료 처리
↓
9. TimeMachine 상태 원복
5.2 시뮬레이션 StateGraph
// 시뮬레이션 전용 워크플로우
const SimulationStateGraph = {
nodes: {
'simulation_data_prep': SimulationDataPrepNode, // 시점별 데이터 준비
'sleep_latency_analysis': SleepLatencyAnalyst, // 수면잠복기 분석
'psychological_analysis': PsychologicalExpert, // 심리상태 분석 (조건부)
'cbti_behavior_analysis': CBTIBehaviorExpert, // CBT-I 행동 분석
'digital_env_analysis': DigitalEnvironmentExpert, // 디지털 환경 분석
'melatonin_system_analysis': MelatoninSystemAnalyst, // 멜라토닌 시스템 분석 (조건부)
'debate_orchestrator': DebateOrchestrator, // 토론 진행
'simulation_result_saver': SimulationResultSaver, // 시뮬레이션 결과 저장
},
edges: [
// 시뮬레이션 전용 엣지 구성
]
};
5.3 데이터 조회 패턴 (BackTesting 구현 상세)
5.3.1 UserCycle 기반 날짜 매핑 로직
// 1. 사용자의 가장 최근 완료된 치료 주기 조회
const latestUserCycle = await userCycleRepository.findLatestCompleted(userId);
if (!latestUserCycle) {
throw new Error('완료된 치료 주기가 없습니다');
}
// 2. 치료 주기 시작일 및 타임존 정보 추출
const startDate = latestUserCycle.startedAt;
const timezone = latestUserCycle.timezoneId || 'Europe/Berlin';
// 3. dayIndex → 실제 날짜(YYYY-MM-DD) 매핑 생성
const dayIndexToDateMap = new Map<number, string>();
for (let dayIndex = 1; dayIndex <= 90; dayIndex++) {
const targetDate = addDays(startDate, dayIndex - 1);
const dateString = format(targetDate, 'yyyy-MM-dd', { timezone });
dayIndexToDateMap.set(dayIndex, dateString);
}
5.3.2 Firestore 데이터 조회 패턴
백테스팅 시 각 도메인별 데이터를 시점 제한적으로 조회해야 합니다:
// Sleep 데이터 조회 (Firestore)
const sleepDataPath = `sleep/sleepGoal/${userId}/${dateString}`;
const sleepData = await firestoreService.getDocument(sleepDataPath);
// Learning 데이터 조회 (Firestore)
const learningDataPath = `learning/progress/${userId}/${dateString}`;
const learningData = await firestoreService.getDocument(learningDataPath);
// Questionnaire 데이터 조회 (PostgreSQL)
const questionnaireData = await questionnaireRepository.findByUserAndDateRange(
userId,
startDate,
new Date(dateString)
);
5.3.3 시점별 데이터 격리 (Future Data Leakage 방지)
// Day N 예측 시: Day 1 ~ (N-1) 데이터만 사용
async function getDataForPrediction(userId: string, targetDayIndex: number, dayIndexMap: Map<number, string>) {
const availableData = {
sleep: [],
questionnaire: [],
learning: []
};
// targetDayIndex 이전 데이터만 조회
for (let dayIndex = 1; dayIndex < targetDayIndex; dayIndex++) {
const dateString = dayIndexMap.get(dayIndex);
if (!dateString) continue;
// 각 도메인별 데이터 수집
const sleepData = await getSleepData(userId, dateString);
const learningData = await getLearningData(userId, dateString);
if (sleepData) availableData.sleep.push(sleepData);
if (learningData) availableData.learning.push(learningData);
}
// Questionnaire는 기간별 조회
const questionnaireData = await getQuestionnaireDataBefore(userId, targetDayIndex);
availableData.questionnaire = questionnaireData;
return availableData;
}
5.3.4 최소 데이터 요구사항 검증
async function validateMinimumDataRequirements(userId: string, userCycleId: string): Promise<boolean> {
// 최소 1개 이상의 sleep/sleepGoal 데이터 존재 확인
const sleepGoalCount = await firestoreService.countDocuments(`sleep/sleepGoal/${userId}`);
if (sleepGoalCount === 0) {
throw new InsufficientDataException('백테스팅을 위한 최소 수면 목표 데이터가 없습니다');
}
// 추가 데이터 완성도 검증
const dataCompleteness = {
sleepGoalDays: sleepGoalCount,
hasQuestionnaire: await hasQuestionnaireData(userId),
hasLearningData: await hasLearningData(userId)
};
return dataCompleteness.sleepGoalDays >= 1; // 최소 조건
}
6. 비기능 요구사항
6.1 성능 요구사항
- SIM-NFR-001: 단일 사용자 90일 치료주기 시뮬레이션을 4시간 이내에 완료해야 한다.
- 평균 예측 시간 30초 × 83회 예측 ≈ 45분 + 오버헤드
- SIM-NFR-002: 동시에 최대 5개의 시뮬레이션을 실행할 수 있어야 한다.
- SIM-NFR-003: 시뮬레이션 진행 상황을 실시간으로 업데이트해야 한다 (5초 간격).
6.2 신뢰성 요구사항
- SIM-NFR-004: 시뮬레이션 실패 시 부분 결과를 보존하고 재시작 지점을 제공해야 한다.
- SIM-NFR-005: TimeMachine 상태 변경 실패 시 자동 롤백을 수행해야 한다.
6.3 보안 요구사항
- SIM-NFR-006: 시뮬레이션 데이터는 실제 예측 데이터와 동일한 암호화 수준을 적용해야 한다.
- SIM-NFR-007: 시뮬레이션 결과 접근 권한을 관리자 및 연구진으로 제한해야 한다.
7. 제약사항
7.1 데이터 제약사항
- SIM-CON-001: 시뮬레이션 대상은 치료 완료 상태의 사용자로 제한된다.
- SIM-CON-002: 최소 14일 이상의 수면 기록이 있는 사용자만 시뮬레이션 가능하다.
- SIM-CON-003: 시뮬레이션 시 미래 데이터 누출을 방지해야 한다.
7.2 시스템 제약사항
- SIM-CON-004: 시뮬레이션은 실제 예측 시스템에 영향을 주지 않아야 한다.
- SIM-CON-005: TimeMachine 상태 변경 시 다른 사용자에게 영향을 주지 않아야 한다.
7.3 비즈니스 제약사항
- SIM-CON-006: 시뮬레이션 결과는 연구 및 개선 목적으로만 사용되어야 한다.
- SIM-CON-007: 개인정보 보호를 위해 시뮬레이션 결과 익명화를 적용해야 한다.
8. 변경 이력
| 버전 | 날짜 | 작성자 | 변경 내용 |
|---|---|---|---|
| 1.0.0 | 2025-09-01 | bok@weltcorp.com | 최초 작성 - 실제 사용자 데이터 기반 시뮬레이션 시스템 요구사항 정의 |
| 1.1.0 | 2025-09-05 | bok@weltcorp.com | 멜라토닌시스템분석전문가 추가 - 5번째 전문가 에이전트, 시뮬레이션 성능 분석 확장 |