본문으로 건너뛰기

P1 초기 평가 - 구현 가이드

1. 개요

1.1 실행 시점

  • Day 8, 오전 9시
  • 수면기록 최소 4일 이상 존재 시

1.2 목적

  • 1주일간의 수면 패턴 종합 분석
  • 핵심 문제 파악 및 초기 가설 수립
  • 환자와의 치료적 동맹 형성

목적: 서비스 시작 후 7일째, 사용자의 불면증 상태를 종합적으로 평가하고 추가 정보 수집을 위한 맞춤형 질문을 생성합니다.

역할: 수면 인지행동치료(CBT-I) 전문가로서, 환자의 초기 수면 일지 및 설문 데이터를 기반으로 환자의 수면 문제를 파악하고, 임상적으로 유의미하며 환자 중심적인 개방형 질문을 설계하여 초기 면담을 효과적으로 지원합니다.

트리거 조건:

  • Day 7, 오전 9시
  • 수면기록 최소 4일 이상 존재 (diary_entry_count >= 4)
  • 1회차 설문 완료

결과물:

  1. 🔍 수면 요약 (환자 및 임상가용)
  2. 💬 면담 질문 2-4개 (환자용)
  3. 시스템 처리용 구조화 데이터 (P2-P5 활용)

2. 대화 정책 및 경계 설정

P1은 초기 평가 단계이지만, 향후 P2-P5에서의 실시간 대화를 위한 기본 정책을 설정합니다:

  • 적용 상황: 사용자 발화가 불면과 간접적 연관성이 있을 때 (예: 스트레스, 대인관계)
  • 처리 방법:
    1. 감정을 인정(Validate): "스트레스가 많으신 상황이군요"
    2. 수면 문제와 연결(Link): "스트레스가 수면에도 영향을 주고 있을 수 있어요"
    3. 수면 주제로 재초점화(Redirect): "스트레스로 인해 잠들기 어려우신 적이 있으신가요?"

2.2 R-R (Reaffirm Role-Redirect)

  • 적용 상황: 연관성이 없는 무해한 질문 (예: 요리법, 날씨)
  • 처리 방법:
    1. 역할 재확인(Reaffirm Role): "저는 수면 전문 코치입니다"
    2. 수면 주제로 재초점화(Redirect): "수면과 관련해서 도움드릴 수 있는 부분이 있을까요?"

2.3 Block & Guide

  • 적용 상황: 부적절하거나 유해한 발화
  • 처리 방법:
    1. 중립적 어조로 차단(Block): "그런 내용은 다룰 수 없습니다"
    2. 건설적 목표 안내(Guide): "수면 개선을 위해 함께 노력해보아요"

3. 수면일지 주요 항목

P1 분석에서 활용하는 수면일지의 주요 데이터 항목들입니다:

3.1 시간 관련 지표

  • 취침 시각 (lights off time): 불을 끄고 잠들려고 누운 시각
  • 잠든 시각 (asleep time): 실제로 잠든 시각
  • 기상 시각 (wake up time): 아침에 깬 시각

3.2 수면 측정 지표

  • 총 수면 시간 (TST, Total Sleep Time): 실제로 잠든 시간
  • 잠들기까지 걸린 시간 (SOL, Sleep Onset Latency): 누워서 잠들 때까지의 시간
  • 도중에 깬 시간 총합 (WASO, Wake After Sleep Onset): 수면 중 깨어있던 시간
  • 수면 효율 (SE, Sleep Efficiency): (TST / 침대에 있던 시간) × 100

3.3 주관적 평가

  • 수면 중 겪은 문제: 복수 선택 가능 (예: 잠들기 어려움, 자주 깸, 일찍 깸)
  • 수면에 영향을 준 요인: 복수 선택 가능 (예: 스트레스, 음주, 소음, 걱정)
  • 수면의 질: 주관적 평가 (1-5점 척도)

3.4 기타 정보

  • 수면제 복용 여부: 있음/없음
  • 낮잠 여부 및 시간: 낮잠 시간(분)

3.5 설문 평가 도구

  • ISI (Insomnia Severity Index): 불면증 심각도 (0-28점)
  • PHQ-9: 우울감 평가 (0-27점)
  • GAD-7: 불안 평가 (0-21점)
  • ESS (Epworth Sleepiness Scale): 주간 졸림 (0-24점)
  • DBAS-16: 수면에 대한 역기능적 신념 (0-10점)

4. 필요한 MCP 도구

4.1 Sleep Tools

// 수면 일지 데이터 조회
- getSleepRecords
입력: userId, startDayIndex, endDayIndex
출력: [{
dayIndex: number,
sleepEfficiency: number | null,
totalSleepTime: number | null,
sleepOnsetLatency: number | null,
wakeAfterSleepOnset: number | null,
lightsOffTime: string | null,
wakeUpTime: string | null,
sleepQuality: number | null,
problems: string[],
factors: string[],
medication: boolean
}]

4.2 Agent Data Tools

// 종합 컨텍스트 조회
- getComprehensiveUserContext
입력: userId, dateRange: '7days'
출력: {
sleepPatterns: LLM 친화적 수면 패턴,
psychologicalState: 심리 상태 해석,
learningEngagement: 학습 참여도,
riskFactors: 위험 요인 분석,
medicationUse: 수면제 복용 정보
}

4.3 Learning Tools

// 학습 진도 및 패턴
- getLearningProgress
입력: userId, userCycleId
출력: completedLessons, progressPercentage, lastActivityAt

- getLearningPattern
입력: userId
출력: preferredTimeOfDay, averageSessionDuration, frequencyPerWeek

- getLearningHistory
입력: userId, startDate, endDate
출력: 레슨별 시작/종료 시간, 소요 시간

4.4 Questionnaire Tools

// 1회차 설문 분석
- analyzeISIScore
입력: userId, roundNumber: 'FIRST'
출력: score (0-28), severity, feedback

- analyzePHQ9Score
입력: userId, roundNumber: 'FIRST'
출력: score (0-27), level, recommendation

- analyzeGAD7Score
입력: userId, roundNumber: 'FIRST'
출력: score (0-21), anxietyLevel, clinicalSignificance

- analyzePSSScore
입력: userId, roundNumber: 'FIRST'
출력: score (0-40), stressLevel

- analyzeDBAS16Score
입력: userId, roundNumber: 'FIRST'
출력: averageScore (0-10), dysfunctionalBeliefs[]

5. Flowise 플로우 구성

5.1 플로우 다이어그램

5.2 노드별 상세 설정

Schedule Trigger Node

Type: Schedule Trigger
Settings:
- Schedule: "0 9 * * *" (매일 오전 9시)
- Condition: dayIndex === 8
- Output: { userId, dayIndex, timestamp }

Custom MCP Node 1 - Sleep Records

Name: "Get Sleep Records"
Tool: getSleepRecords
Parameters:
- userId: {{trigger.userId}}
- startDayIndex: 1
- endDayIndex: 7
Output Variable: sleepRecords

Custom MCP Node 2 - Agent Data

Name: "Get Comprehensive Context"
Tool: getComprehensiveUserContext
Parameters:
- userId: {{trigger.userId}}
- dateRange: "7days"
- includeOptions:
- sleepPatterns: true
- psychologicalState: true
- learningEngagement: true
- riskFactors: true
Output Variable: agentDataContext

Custom MCP Node 3 - Learning

Name: "Get Learning Data"
Parallel Tools:
- getLearningProgress:
userId: {{trigger.userId}}
- getLearningPattern:
userId: {{trigger.userId}}
- getLearningHistory:
userId: {{trigger.userId}}
startDate: {{dateUtils.daysAgo(7)}}
endDate: {{dateUtils.now()}}
Output Variable: learningData

Custom MCP Node 4 - Questionnaire

Name: "Get Questionnaire Scores"
Parallel Tools:
- analyzeISIScore:
userId: {{trigger.userId}}
roundNumber: "FIRST"
- analyzePHQ9Score:
userId: {{trigger.userId}}
roundNumber: "FIRST"
- analyzeGAD7Score:
userId: {{trigger.userId}}
roundNumber: "FIRST"
- analyzePSSScore:
userId: {{trigger.userId}}
roundNumber: "FIRST"
- analyzeDBAS16Score:
userId: {{trigger.userId}}
roundNumber: "FIRST"
Output Variable: questionnaireData

Data Aggregator Node

Type: Data Transformer
Input Variables:
- trigger (Schedule Trigger 출력)
- sleepRecords (Sleep MCP 도구 출력)
- questionnaireData (Questionnaire MCP 도구 출력)
- agentDataContext (Agent Data MCP 도구 출력)
- learningData (Learning MCP 도구 출력)
Transform Function: |
// 수면 일지 데이터 집계
const sleepDiary = [];
const validRecords = sleepRecords.filter(record => record.SE !== null);
const diaryEntryCount = validRecords.length;

// 각 날짜별 수면 데이터 포맷팅
sleepRecords.forEach(record => {
if (record.SE !== null) {
sleepDiary.push({
dayIndex: record.dayIndex,
SE: record.sleepEfficiency,
SOL: record.sleepOnsetLatency,
TST: record.totalSleepTime,
WASO: record.wakeAfterSleepOnset,
lightsOff: record.lightsOffTime,
wakeUp: record.wakeUpTime
});
}
});

// 자가보고 요인 추출
const reportedFactors = agentDataContext.riskFactors?.behaviors?.join(', ') || '';

// 수면제 복용 여부
const medicationUse = agentDataContext.medicationUse || '없음';

return {
userId: inputs.trigger.userId,
dayIndex: 8,
diaryEntryCount: diaryEntryCount,
sleepDiary: sleepDiary,
questionnaireData: inputs.questionnaireData,
medicationUse: medicationUse,
reportedFactors: reportedFactors,
comprehensiveData: {
...inputs.agentDataContext,
learning: inputs.learningData
},
timestamp: new Date()
};
Output Variable: aggregatedData

LLM Chain Node

Model: gpt-4-turbo
Temperature: 0.7
System Prompt: |
당신은 수면 인지행동치료(CBT-I) 전문가로서, 환자의 초기(1주일 사용 후) 수면 일지 및 설문 데이터를 기반으로 환자의 수면 문제를 파악하고, 임상적으로 유의미하며 환자 중심적인 개방형 질문을 설계하여 초기 면담을 효과적으로 지원하는 역할을 맡고 있습니다. 모든 질문은 환자가 편안하게 자신의 이야기를 할 수 있도록 부드럽고 간결한 어투로 작성되어야 합니다.

# 목표
당신은 수면 인지행동치료(CBT-I) 전문가로서, 환자의 초기 수면 일지 및 설문 데이터를 기반으로 다음을 수행합니다:

1. (내부적 또는 임상가 참고용) 주요 임상 관찰 사항 식별: 환자의 수면 문제 및 주요 특이사항을 식별하여, 질문 생성의 근거로 활용하거나 임상가에게 간략한 정보를 제공합니다. (이 요약은 최종 출력물에 포함될 🔍 수면 요약의 기반이 됩니다.)

2. 초기 면담을 위한 핵심 질문 생성: 환자와의 초기 면담(1주차 DTx 사용 후, TIB 설정 전)에 적합한 2~4개의 핵심적인 개방형 질문을 생성합니다. 이 질문들은 환자의 자기 표현을 유도하고, 주관적 어려움을 명확히 하며, 분석된 주요 사항들을 부드럽게 탐색하는 데 초점을 맞춥니다.

3. 질문의 임상적 근거 제시: 생성된 각 질문에 대해, 해당 질문이 어떤 임상적 관찰, 가설, 또는 탐색 전략에 기반하는지 그 근거를 (임상가 또는 시스템 검토를 위해) 간략히 설명합니다.

# 대화 정책 및 경계 설정 (Conversation Policy & Boundary Setting)
당신은 모든 사용자 입력에 대해 다음의 단계별 정책을 따라야 합니다.

1. V-L-R (Validate-Link-Redirect): 사용자의 발화가 불면과 간접적 연관성(예: 스트레스, 대인관계)이 있다면, 먼저 감정을 **인정(Validate)**하고, 수면 문제와 **연결(Link)**시킨, 다시 수면 관련 주제로 대화를 **재초점화(Redirect)**합니다.

2. R-R (Reaffirm Role-Redirect): 사용자의 발화가 연관성이 전혀 없는 무해한 질문(예: 요리법, 날씨)이라면, 당신의 역할을 **'수면 전문 코치'로 재확인(Reaffirm Role)**하고, 다시 수면 관련 주제로 대화를 **재초점화(Redirect)**합니다.

3. Block & Guide: 사용자의 발화가 명백히 부적절하거나 유해하다면, 단호하지만 중립적인 어조로 **대화를 차단(Block)**하고, 앱의 **건설적인 목표를 안내(Guide)**합니다.

# 수면일지에 포함된 주요 항목
- 취침 시각 (lights off time)
- 잠든 시각 (asleep time)
- 기상 시각 (wake up time)
- 총 수면 시간 (total sleep time, TST)
- 잠들기까지 걸린 시간 (sleep onset latency, SOL)
- 도중에 깬 시간 총합 (wake after sleep onset, WASO)
- 수면 효율 (sleep efficiency, SE)
- 수면 중 겪은 문제 (복수 선택 가능)
- 수면에 영향을 준 요인 (복수 선택 가능)
- 수면제 복용 여부
- 낮잠 여부 및 시간
- 수면의 질 (주관적 평가)

또한 다음과 같은 설문 항목도 포함됩니다:
- ISI (Insomnia Severity Index)
- PHQ-9 (우울감)
- GAD-7 (불안)
- ESS (주간 졸림)
- DBAS-16 (수면에 대한 인지적 왜곡 정도)

# 분석 가이드: 단계별 임상 추론 및 질문 생성
주어진 수면 일지 및 설문 데이터를 분석하여 환자의 수면 문제를 깊이 있게 파악하고, 임상적으로 유의미한 질문을 생성하기 위해 다음의 분기 처리 방식을 따르십시오.

## [핵심] 1. 처리 경로 분기: 데이터 유효성 우선 검사
가장 먼저 사용자 입력에서 diary_entry_count 값을 확인하십시오. 이 값에 따라 아래의 두 가지 경로 중 오직 하나만을 선택하여 지침을 따라야 합니다. 두 경로의 지침을 절대로 혼합해서는 안 됩니다.

### 경로 A: 데이터가 불충분할 경우 (diary_entry_count 값이 1, 2, 또는 3 중 하나일 경우)
이 경로를 따를 경우, 당신의 유일한 목표는 **'데이터 작성의 장벽을 탐색'**하는 것입니다. 상세 임상 분석을 수행하지 마십시오.

1. 임상 가설 수립 중단: 모든 임상 가설 수립 및 분석 활동을 즉시 중단합니다.
2. 공감적 질문 생성: 환자의 부담을 덜어주는 공감적 어조로, 수면일지 작성의 어려움이나 작성하지 못한 이유를 부드럽게 묻는 1~2개의 질문만 생성합니다.
3. 지정된 형식으로 출력: 최종 출력물은 아래 형식에 맞춰 생성합니다.
- for_human_review:
- summary_title: "수면 기록 확인"
- summary_content: "수면일지 기록이 아직 충분하지 않은 것 같아요. 정확한 분석을 위해 조금 더 기록이 필요합니다." 와 같이 데이터가 부족함을 알리는 안내 메시지를 포함합니다.
- questions: 위 2번 항목에서 생성한 1~2개의 질문과 그 근거('일지 작성의 어려움을 파악하고 격려하기 위함')를 포함합니다.
- for_system_processing:
- data_status: INSUFFICIENT 로 설정합니다.
- initial_hypothesis: DATA_INSUFFICIENT 로 설정합니다.
- key_observations: null 또는 빈 배열 [] 로 설정합니다.

### 경로 B: 데이터가 충분할 경우 (diary_entry_count 값이 4, 5, 6, 또는 7 중 하나일 경우)
이 경로를 따를 경우에만, 아래의 전체 임상 추론 및 질문 생성 절차를 시작합니다.

## 2. 주요 관찰 사항 식별 (Observation Identification)

### 가. 전반적인 추세 및 일관성 분석 (Overall Trend and Consistency Analysis)
- 먼저, 제공된 수면일지 데이터(예: SE, TST, SOL, WASO, 취침/기상 시간 등)의 시간 경과에 따른 전반적인 추세, 안정성, 또는 변동성을 간략히 기술하십시오.
- 환자의 데이터 기록 성실성이나 패턴(예: 누락된 데이터, 규칙적인 기록 등)에 대한 관찰도 포함될 수 있습니다.
- 설문 점수(ISI, PHQ-9, GAD-7, ESS, DBAS-16)의 전반적인 수준을 함께 언급하며, 이들 간의 대략적인 관계나 시사점을 간략히 언급할 수 있습니다.

### 나. 추세 내 두드러지는 특징 또는 예외사항 식별 (Identification of Salient Features or Exceptions within Trends)
- 위 '가'에서 파악된 전반적인 추세의 맥락 안에서, 또는 그 추세와 대조적으로, 특별히 두드러지거나, 예상과 다르거나, 임상적으로 중요하다고 판단되는 구체적인 패턴, 개별 데이터 포인트, 또는 데이터 간의 모순점을 1~2가지 구체적으로 식별하고 기술하십시오.

## 3. 가능한 임상적 가설 설정 (Hypothesis Generation)
- 위 2. 주요 관찰 사항 식별 (특히 '가. 전반적인 추세 분석'과 '나. 추세 내 특징/예외사항 식별'에서 종합적으로 기술된 내용)을 근거로 하여, 환자의 현재 상태, 주된 어려움, 또는 불면의 핵심적인 기여 요인에 대한 가장 가능성이 높고 임상적으로 유의미한 가설을 1~3가지 구체적으로 설정하십시오.
- 각 가설은 어떤 구체적인 관찰 사항(들)에 근거하는지 명시적으로 연결하고, 해당 가설이 왜 타당한지에 대한 간략한 임상적 추론 과정을 포함해야 합니다.
- 설정된 가설은 이후의 4. 추가 탐색을 위한 핵심 영역 및 질문 전략 수립 단계와 직접적으로 연결되어야 합니다.

## 4. 추가 탐색을 위한 핵심 영역 및 질문 전략 수립 (Exploration Strategy - 1주차 DTx 사용 후, TIB 설정 전 초기 면담용)
3. 가능한 임상적 가설 설정에서 도출된 가설들을 참고하되, 초기 면담임을 감안하여 환자의 방어감을 낮추고 자연스러운 내러티브를 유도하는 데 초점을 맞춘 탐색 전략을 수립하십시오. 다음 우선순위를 고려하여 탐색 영역과 질문 접근 방식을 구체화합니다.

가. 환자의 주된 호소 및 현재 수면 양상 명확화 (개방형 접근 우선):
- 환자가 현재 자신의 수면 문제 중 무엇을 가장 불편하게 느끼는지 자신의 언어로 표현하도록 유도.
- 수면일지에 나타난 전반적인 수면 양상(예: 짧은 TST, 간헐적 긴 SOL, 이른 기상 등)에 대한 환자의 주관적 경험 확인.

나. 생리적/행동적 측면 확인 (사실 기반 질문):
- 'Short sleeper' 가능성을 염두에 두고, 평소의 일반적인 수면 시간 및 패턴에 대해 질문.
- EMA가 관찰될 경우, 기상 후 행동 및 재입면 노력 여부 등 구체적 경험 탐색.

다. 환자 보고 영향 요인 탐색 (개방형 질문으로 시작하여 구체화):
- 환자가 일지나 설문에서 언급한 수면 영향 요인(예: 스트레스, 걱정, 소음, 음주)에 대해 개방적으로 질문하여 환자가 자발적으로 이야기하도록 유도.
- 답변 내용에 따라 해당 요인이 수면에 미치는 구체적인 영향, 빈도, 맥락 등을 자연스럽게 추가 질문.

라. 심리적 요인(불안, 인지왜곡)에 대한 간접적 탐색 (초기에는 최소화):
- 높은 불안/DBAS 점수 등의 가설이 있더라도, 초기에는 직접적인 질문을 피하고, 환자의 내러티브에서 자연스럽게 드러나는 생각이나 감정에 주목.
- 필요한 경우, "잠자리에 누워 잠이 안 올 때 보통 어떤 생각이나 느낌이 드시나요?" 정도의 일반적이고 비위협적인 질문 고려.

마. 이번 회기 탐색 범위 설정:
- 심층적인 과거력, 삶의 전반적인 영향, 복잡한 심리적 문제 등은 추후 회기에 다룰 수 있음을 인지하고, 이번 회기에는 현재의 수면 문제를 파악하고 TIB 설정을 위한 정보 수집에 집중한다.

## 5. 면담 질문 생성 (Question Generation - 초기 면담용)
위의 1, 2, 3, 4단계 분석 및 전략 수립 내용을 종합적으로 고려하여, 환자와의 초기 면담(1주차 DTx 사용 후, TIB 설정 전)에 적합한 2~4개의 핵심적인 개방형 질문을 생성하십시오.

- 각 질문은 환자의 내러티브를 유도하고, 방어감을 낮추며, 현재 상태 파악 및 TIB 설정을 위한 핵심 정보 수집에 초점을 맞추어야 합니다.
- 질문은 명확하고 간결하게, 그리고 환자가 편안함을 느낄 수 있도록 부드럽고 친근한 어투로 구성하십시오. 딱딱하거나 너무 길어서 환자가 답변하기 어렵게 느껴지지 않도록 주의해야 합니다.
- 초기 면담의 특성상 대부분 기본적인 개방형 질문 또는 부드러운 탐색 질문이 될 것입니다. 다만, 환자가 직접 언급했거나 데이터에서 시사되는 특정 요인(예: 스트레스)과 그것이 수면에 미치는 구체적인 영향 사이의 연결고리를 탐색할 때는, 환자가 그 연결고리를 명확히 인지하지 못할 가능성을 고려하여, '혹시 이런 경험이 있으신가요?' 또는 '예를 들어 이런 식으로 영향이 있나요?'와 같이 흔한 경험이나 가능한 경로를 부드럽게 제시하며 환자의 답변을 유도하는 방식도 효과적입니다.
- 생성된 각 질문 옆에는 해당 질문을 하는 임상적 근거 (어떤 관찰/가설/탐색 전략에 기반하며, 무엇을 확인/이해하기 위함인지)를 간략히 명시하십시오.

User Prompt Template: |
사용자 ID: {{aggregatedData.userId}}
평가 일차: Day {{aggregatedData.dayIndex}}
diary_entry_count: {{aggregatedData.diaryEntryCount}}

=== 설문 데이터 ===
ISI: {{questionnaireData.isi.score}}
PHQ-9: {{questionnaireData.phq9.score}}
GAD-7: {{questionnaireData.gad7.score}}
ESS: {{questionnaireData.ess.score}}
DBAS-16: {{questionnaireData.dbas16.averageScore}}

=== 수면 일지 데이터 ===
{{#each aggregatedData.sleepDiary}}
Day {{this.dayIndex}}: SE={{this.SE}}%, SOL={{this.SOL}}min, TST={{this.TST}}min, WASO={{this.WASO}}min, LightsOff={{this.lightsOff}}, WakeUp={{this.wakeUp}}
{{/each}}

=== 기타 정보 ===
수면제 복용: {{aggregatedData.medicationUse}}
Self-reported factors: {{aggregatedData.reportedFactors}}

=== 학습 및 컨텍스트 데이터 ===
{{json aggregatedData.comprehensiveData}}

Output Format: |
{
"for_human_review": {
"summary_title": "🔍 수면 요약",
"summary_content": "환자의 수면 패턴 요약 (데이터 부족 시 안내 메시지)",
"questions": [
{
"type": "질문 유형",
"question": "생성된 질문",
"rationale": "임상적 근거"
}
]
},
"for_system_processing": {
"data_status": "SUFFICIENT 또는 INSUFFICIENT",
"initial_hypothesis": "초기 가설 또는 DATA_INSUFFICIENT",
"key_observations": ["관찰 사항 배열"],
"p1_generated_questions_for_p2": ["생성된 질문 목록"]
}
}

Output Variable: llmResponse

Output Parser Node

Type: JSON Parser
Input: {{llmResponse}}
Parse Rules:
- Extract: for_human_review
- summary_title
- summary_content
- questions[]
- Extract: for_system_processing
- data_status
- initial_hypothesis
- key_observations[]
- p1_generated_questions_for_p2[]
Validation:
- for_human_review.questions.length >= 1 && <= 4
- for_system_processing.data_status in ['SUFFICIENT', 'INSUFFICIENT']
- if data_status === 'INSUFFICIENT' then initial_hypothesis === 'DATA_INSUFFICIENT'
Output Variable: parsedOutput

Agent Board API Node

Type: HTTP Request
Method: POST
URL: {{env.AGENT_BOARD_API}}/messages
Headers:
- Authorization: Bearer {{env.API_TOKEN}}
Body: |
{
"userId": "{{aggregatedData.userId}}",
"messageType": "P1_INITIAL_ASSESSMENT",
"content": {
"title": "{{parsedOutput.for_human_review.summary_title}}",
"summary": "{{parsedOutput.for_human_review.summary_content}}",
"questions": {{json parsedOutput.for_human_review.questions}},
"metadata": {
"dayIndex": 8,
"phase": "P1",
"dataStatus": "{{parsedOutput.for_system_processing.data_status}}",
"hypothesis": "{{parsedOutput.for_system_processing.initial_hypothesis}}",
"observations": {{json parsedOutput.for_system_processing.key_observations}}
}
}
}
Error Handling:
- Retry: 3 times with exponential backoff
- Fallback: Queue for later delivery
- If data_status === 'INSUFFICIENT', schedule retry for Day 14

6. 실제 데이터 활용 예시

6.1 데이터 처리 경로 분기

경로 A: 데이터 불충분 (diary_entry_count < 4)

// 예: userId 409의 경우 - 3일 데이터만 존재
{
"diary_entry_count": 3,
"sleepDiary": [
{ "dayIndex": 5, "SE": null, "SOL": null, "TST": null }, // 미기록
{ "dayIndex": 6, "SE": 32.6, "SOL": 180, "TST": 145, "WASO": 120 },
{ "dayIndex": 7, "SE": null, "SOL": null, "TST": null } // 미기록
]
}

// LLM 응답 예시
{
"for_human_review": {
"summary_title": "수면 기록 확인",
"summary_content": "수면일지 기록이 아직 충분하지 않은 것 같아요. 정확한 분석을 위해 조금 더 기록이 필요합니다.",
"questions": [
{
"type": "기본 질문",
"question": "수면일지를 작성하시면서 불편했던 점이나 어려웠던 점이 있으셨나요?",
"rationale": "일지 작성의 어려움을 파악하고 격려하기 위함"
}
]
},
"for_system_processing": {
"data_status": "INSUFFICIENT",
"initial_hypothesis": "DATA_INSUFFICIENT",
"key_observations": []
}
}

경로 B: 데이터 충분 (diary_entry_count >= 4)

6.2 충분한 데이터 입력 예시

// Agent Data Context
{
"sleepPatterns": {
"averageSleepEfficiency": 75,
"averageTST": 390, // 6.5시간
"interpretation": "수면 효율이 낮고 입면 지연이 관찰됩니다",
"trend": "deteriorating"
},
"psychologicalState": {
"summary": "중간 수준의 우울과 불안이 동반되어 있습니다",
"primaryConcern": "depression",
"riskLevel": "moderate"
},
"learningEngagement": {
"status": "low",
"lastActive": "3 days ago",
"completionRate": 25
},
"riskFactors": {
"behaviors": ["늦은 카페인 섭취", "불규칙한 수면 시간"],
"immediateIntervention": false
}
}

// Learning Data
{
"progress": {
"progressPercentage": 25,
"completedLessons": 2,
"totalLessons": 8
},
"pattern": {
"preferredTimeOfDay": "evening",
"averageSessionDuration": 12,
"frequencyPerWeek": 3
},
"history": [
{
"lessonId": "basic-sleep-hygiene",
"startedAt": "2024-01-01T22:15:00",
"duration": 15,
"completed": true
}
]
}

// Questionnaire Data
{
"isi": {
"score": 18,
"severity": "중간",
"feedback": "임상적으로 유의미한 불면증"
},
"phq9": {
"score": 12,
"level": "중등도 우울",
"recommendation": "정신건강 전문가 상담 고려"
},
"gad7": {
"score": 9,
"anxietyLevel": "경미한 불안",
"clinicalSignificance": "모니터링 필요"
},
"pss": {
"score": 25,
"stressLevel": "high"
},
"dbas16": {
"averageScore": 5.2,
"dysfunctionalBeliefs": [
"잠을 못 자면 다음날 일을 제대로 할 수 없다",
"8시간은 자야 한다"
]
}
}

6.3 LLM 생성 결과 예시

예시 1: 김*자 (352nvz7r) - 6일 데이터, 변동폭 큰 수면 효율

{
"for_human_review": {
"summary_title": "🔍 수면 요약",
"summary_content": "환자는 1일차를 제외하고 6일간 일지를 비교적 성실하게 기록하였으며, 다음과 같은 특징을 보입니다:\n\n**객관적 수면 지표**: 수면 효율(SE)은 넓은 변동폭(37% ~ 97%)을 보이며 평균적으로 중간 수준(약 75%)입니다. 잠들기까지 걸린 시간(SOL)은 10분~80분으로 편차가 크며, 2일차(80분), 4일차(60분)에서 길어졌습니다. 총 수면 시간(TST)은 평균 약 273분(4.5시간)으로 전반적으로 짧은 편입니다.\n\n**주관적 평가 및 설문 결과**: ISI(15): 임상적으로 중등도 수준의 불면증 자각, PHQ-9(2), GAD-7(1): 우울 및 불안 수준은 매우 낮음, ESS(0): 주간 졸림은 전혀 없음, DBAS-16(2.88): 수면에 대한 인지적 왜곡 정도는 비교적 낮음\n\n**기타**: 수면제는 복용하지 않았습니다. 취침 시각은 대부분 새벽 00:20-01:30 사이로 늦은 편이며, 기상 시각은 05:40-07:55로 일관된 편입니다.",
"questions": [
{
"type": "기본 질문 (Open-ended)",
"question": "수면일지를 기록해 보시니, 요즘 잠에 대해 스스로 어떤 점이 가장 불편하게 느껴지셨나요?",
"rationale": "환자의 언어로 주관적 고충을 유도하여 면담의 초점을 맞추고, 낮은 불안/우울 수준에도 불구하고 불면을 호소하는 주된 이유를 파악하려는 목적"
},
{
"type": "탐색 질문 (Initial Probing)",
"question": "최근 주무시는 시간이 대체로 4~5시간 정도였는데, 이 정도 수면 시간이 평소에도 익숙하신가요? 아니면 요즘 들어 줄어든 것 같다고 느끼시나요?",
"rationale": "단시간 수면이 생리적 습관인지 최근 변화인지를 탐색하여 short sleeper 가능성과 행동적 불면을 구분하기 위한 질문"
},
{
"type": "탐색 질문 (Guided Probing)",
"question": "대체로 새벽 1시쯤 잠드시는 편인데, 혹시 취침 시간이 자연스럽게 늦어지는 특별한 이유가 있으신가요?",
"rationale": "늦은 취침 시간이 수면 위생 또는 행동 요인과 관련 있는지를 파악하고, 행동적 불면 가능성을 평가하기 위한 질문"
}
]
},
"for_system_processing": {
"data_status": "SUFFICIENT",
"initial_hypothesis": "환자는 심리적 불편감이 낮고, 인지적 왜곡도 크지 않음에도 불구하고, 총 수면 시간(TST)이 전반적으로 짧고(평균 4.5시간), 입면 지연 및 야간 각성으로 인해 수면 효율(SE)에 기복이 큰 양상을 보인다. 이는 불규칙한 취침 시간 또는 수면 압력 저하, 행동적 요인(늦은 취침 습관 등)에 의해 유발된 불면일 가능성이 있다.",
"key_observations": [
"수면 효율(SE)의 넓은 변동폭(37% ~ 97%)과 평균 75% 수준",
"총 수면 시간(TST) 평균 4.5시간으로 짧으나 주간 졸림(ESS=0) 없음",
"낮은 심리적 불편감(PHQ-9=2, GAD-7=1)에도 중등도 불면증 자각(ISI=15)"
],
"p1_generated_questions_for_p2": [
"수면일지를 기록해 보시니, 요즘 잠에 대해 스스로 어떤 점이 가장 불편하게 느껴지셨나요?",
"최근 주무시는 시간이 대체로 4~5시간 정도였는데, 이 정도 수면 시간이 평소에도 익숙하신가요?",
"대체로 새벽 1시쯤 잠드시는 편인데, 혹시 취침 시간이 자연스럽게 늦어지는 특별한 이유가 있으신가요?"
]
}
}

예시 2: 높은 심리적 불편감을 동반한 경우

{
"for_human_review": {
"summary_title": "🔍 수면 요약",
"summary_content": "환자는 7일간 수면일지를 성실히 작성하였으며, 다음과 같은 특징을 보입니다:\n\n**객관적 수면 지표**: 수면 효율(SE)은 평균 65%로 낮은 편이며, 잠들기까지 걸린 시간(SOL)은 평균 45분으로 입면 지연이 관찰됩니다. 야간 각성 시간(WASO)은 평균 60분으로 수면 유지의 어려움이 있습니다. 총 수면 시간(TST)은 평균 5시간으로 부족한 편입니다.\n\n**주관적 평가 및 설문 결과**: ISI(22): 중증 불면증, PHQ-9(18): 중등도-중증 우울, GAD-7(15): 중등도 불안, ESS(12): 경미한 주간 졸림, DBAS-16(7.2): 수면에 대한 역기능적 신념이 매우 높음\n\n**기타**: 스트레스, 걱정, 불안이 주요 수면 방해 요인으로 보고되었으며, 간헐적으로 수면제를 복용하고 있습니다.",
"questions": [
{
"type": "기본 질문 (Open-ended)",
"question": "지난 일주일 동안 수면일지를 작성하시면서, 잠과 관련해서 가장 힘드셨던 부분은 무엇인가요?",
"rationale": "높은 심리적 불편감을 보이는 환자가 자신의 주관적 경험을 편안하게 표현할 수 있도록 유도"
},
{
"type": "탐색 질문 (Empathetic Probing)",
"question": "잠자리에 누워도 잠이 오지 않을 때, 보통 어떤 생각이나 느낌이 드시나요? 혹시 특별히 반복되는 생각이나 걱정이 있으신가요?",
"rationale": "높은 GAD-7과 DBAS-16 점수를 고려하여, 인지적 각성과 반추 패턴을 부드럽게 탐색"
},
{
"type": "탐색 질문 (Behavioral Focus)",
"question": "한밤중에 깨서 다시 잠들기 어려우실 때는 주로 어떻게 하시나요? 그리고 수면제는 어떤 상황에서 드시게 되시나요?",
"rationale": "WASO가 높고 간헐적 수면제 사용을 보고한 점을 고려하여, 수면 유지 어려움에 대한 대처 방식과 약물 의존 패턴 파악"
}
]
},
"for_system_processing": {
"data_status": "SUFFICIENT",
"initial_hypothesis": "환자는 높은 수준의 우울과 불안(PHQ-9=18, GAD-7=15)을 경험하고 있으며, 이로 인한 인지적 과각성이 입면 지연(SOL=45분)과 수면 유지 어려움(WASO=60분)을 야기하고 있을 가능성이 높다. 수면에 대한 역기능적 신념(DBAS-16=7.2)이 매우 높아 수면 노력 역설과 예기 불안이 불면을 악화시키는 악순환 구조를 형성했을 것으로 추정된다.",
"key_observations": [
"낮은 수면 효율(65%)과 높은 WASO(60분)로 수면 유지 어려움 확인",
"높은 심리적 불편감(PHQ-9=18, GAD-7=15)과 불면증 심각도(ISI=22)의 상관",
"매우 높은 DBAS-16(7.2) 점수와 간헐적 수면제 사용 패턴"
],
"p1_generated_questions_for_p2": [
"지난 일주일 동안 수면일지를 작성하시면서, 잠과 관련해서 가장 힘드셨던 부분은 무엇인가요?",
"잠자리에 누워도 잠이 오지 않을 때, 보통 어떤 생각이나 느낌이 드시나요?",
"한밤중에 깨서 다시 잠들기 어려우실 때는 주로 어떻게 하시나요?"
]
}
}

7. 구현 체크리스트

7.1 Flowise 노드 구성

  • Schedule Trigger 설정 (Day 8 체크 로직)
  • MCP 노드 4개 병렬 구성
  • 조건부 분기 노드 (기록 개수)
  • LLM Chain 2개 (정상/부족)
  • Output Parser & Validator
  • Error Handler 노드

7.2 테스트

  • 단위 테스트
    • 각 MCP 도구 호출 테스트
    • Data aggregation 테스트
    • LLM response parsing 테스트
  • 통합 테스트
    • 전체 플로우 실행
    • 다양한 사용자 시나리오 테스트
    • 에러 상황 시뮬레이션
  • 성능 테스트
    • 동시 사용자 처리
    • LLM 응답 시간 측정

8. 테스트 시나리오

시나리오 1: 정상 경로 (수면기록 7개)

Given:
- User ID: user123
- Day 8 오전 9시
- 수면기록: 7개 (매일 작성)
- ISI: 18점
Expected:
- 3가지 출력물 모두 생성
- 질문 3-4개 포함
- 심층 분석 결과

시나리오 2: 데이터 부족 경로 (수면기록 3개)

Given:
- User ID: user456
- Day 8 오전 9시
- 수면기록: 3개만 존재
- ISI: 15점
Expected:
- 간소화된 요약만 생성
- 질문 1-2개 (데이터 수집 독려)
- 의료진 보고서 간략

시나리오 3: 에러 상황

Given:
- User ID: user789
- Day 8 오전 9시
- LLM API 타임아웃
Expected:
- 템플릿 기반 폴백
- 기본 질문 세트 제공
- 에러 로깅 및 알림

9. 모니터링 및 로깅

9.1 핵심 메트릭

Success Metrics:
- P1 실행 성공률: > 99%
- LLM 응답 시간: < 5초
- 질문 생성 품질 점수: > 4.0/5.0

Error Tracking:
- MCP 도구 호출 실패
- LLM timeout/error
- Agent Board API 실패
- 데이터 불충분 케이스

9.2 로그 구조

{
"processId": "P1",
"userId": "user123",
"dayIndex": 8,
"timestamp": "2024-01-08T09:00:00Z",
"status": "success",
"metrics": {
"mcpCallDuration": 1200,
"llmResponseTime": 3500,
"totalDuration": 5200
},
"generatedQuestions": 3,
"errors": []
}

10. 트러블슈팅 가이드

문제 1: MCP 도구 호출 실패

증상: "MCP tool timeout" 에러
원인:
1. MCP 서버 다운
2. 네트워크 지연
3. 대용량 데이터 처리
해결:
1. MCP 서버 상태 확인
2. Timeout 설정 증가 (5s → 10s)
3. 데이터 범위 축소 (7days → 5days)

문제 2: LLM 응답 파싱 실패

증상: "Invalid JSON response" 에러
원인:
1. LLM 프롬프트 불명확
2. Output format 지시 부족
해결:
1. 프롬프트에 JSON 예시 추가
2. Retry with refined prompt
3. Fallback to template questions

문제 3: 질문 품질 저하

증상: 생성된 질문이 일반적이거나 부적절
원인:
1. 컨텍스트 데이터 부족
2. LLM 프롬프트 개선 필요
해결:
1. 더 많은 컨텍스트 데이터 수집
2. Few-shot examples 추가
3. 질문 검증 로직 강화

11. 개선 아이디어

11.1 단기 개선

  • 질문 pool 사전 생성하여 LLM 부하 감소
  • 캐싱 전략으로 반복 호출 최적화
  • A/B 테스트로 질문 효과성 측정

11.2 장기 개선

  • ML 모델로 질문 효과성 예측
  • 사용자 응답률 기반 질문 최적화
  • 다국어 지원

12. 참고 자료