Software Design Document (SDD)
SleepQ 디지털 치료기기의 소프트웨어 상세 설계 문서입니다.
1. 시스템 설계 개요
1.1 설계 목적
본 문서는 SleepQ 시스템의 상세 설계 명세를 정의하여 개발팀이 일관성 있게 구현할 수 있도록 가이드를 제공합니다.
1.2 설계 원칙
- 모듈성: 독립적이고 재사용 가능한 컴포넌트 설계
- 테스트 가능성: 단위 테스트 및 통합 테스트 용이성
- 유지보수성: 명확한 인터페이스 및 문서화
- 성능: 효율적인 알고리즘 및 데이터 구조 사용
2. 모듈 상세 설계
SleepQ는 안전성 등급 A에 해당하는 소프트웨어 의료기기로서 주요 기능에 대해서만 상세 설계를 진행한다.
2.1 사용자 관리 모듈
2.1.1 인증 서비스 (AuthService)
액세스 코드 검증 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 액세스 코드 검증 |
| 소속 클래스 | AuthService, AccessCodeValidator |
| 관련 Endpoint | POST /auth/access-code/validate |
| 입력 데이터 | - accessCode: string (8자리 일회용 코드) - email: string (선택사항) - deviceInfo: object (기기 정보) |
| 출력 데이터 | - isValid: boolean - accessToken: string (JWT) - user: UserProfile - expiresIn: number |
| 주요 알고리즘 | - 액세스 코드 유효성 검증 - 사용 기한 및 횟수 확인 - 사용자 계정 생성 또는 연결 - JWT 토큰 생성 (RS256) |
| 예외 처리 | - 잘못된 코드: 400 Bad Request - 만료된 코드: 410 Gone - 이미 사용된 코드: 409 Conflict |
| 테스트 조건 | - 유효한 액세스 코드 입력 → 토큰 발급 성공 - 만료된 코드 입력 → 오류 반환 - 형식 오류 코드 → 검증 실패 |
| 호출 구조 | Mobile App → Load Balancer → API Server → AuthService → AccessCodeValidator → Database |
| 로그 처리 | - 인증 시도 기록 (info) - 실패 사유 기록 (warn) - 토큰 발급 이벤트 (info) |
JWT 토큰 갱신 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | JWT 토큰 갱신 |
| 소속 클래스 | AuthService, TokenManager |
| 관련 Endpoint | POST /auth/token/refresh |
| 입력 데이터 | - refreshToken: string (갱신용 토큰) |
| 출력 데이터 | - accessToken: string (새 JWT) - expiresIn: number (만료 시간) |
| 주요 알고리즘 | - Refresh 토큰 유효성 검증 - 토큰 블랙리스트 확인 - 새 Access 토큰 생성 - 토큰 로테이션 처리 |
| 예외 처리 | - 유효하지 않은 토큰: 401 Unauthorized - 만료된 토큰: 401 Unauthorized - 블랙리스트 토큰: 403 Forbidden |
| 테스트 조건 | - 유효한 Refresh 토큰 → 새 토큰 발급 - 만료된 토큰 → 재로그인 요구 - 동시 갱신 요청 → 동시성 제어 확인 |
| 호출 구조 | Client → Load Balancer → AuthService → Redis Cache → TokenManager |
| 로그 처리 | - 토큰 갱신 요청 (debug) - 갱신 성공/실패 (info/warn) - 보안 이벤트 기록 (audit log) |
2.1.2 사용자 프로필 서비스 (UserProfileService)
사용자 프로필 업데이트 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 사용자 프로필 업데이트 |
| 소속 클래스 | UserProfileService, UserValidator |
| 관련 Endpoint | PUT /users/profile |
| 입력 데이터 | - firstName: string - lastName: string - timezone: string - language: string - preferences: object |
| 출력 데이터 | - user: UserProfile (업데이트된 프로필) - updatedFields: string[] (변경된 필드 목록) |
| 주요 알고리즘 | - 입력 데이터 유효성 검증 - 변경 사항 추적 - 개인정보 암호화 (AES-256) - 데이터베이스 트랜잭션 처리 |
| 예외 처리 | - 유효하지 않은 데이터: 400 Bad Request - 권한 부족: 403 Forbidden - 사용자 없음: 404 Not Found |
| 테스트 조건 | - 정상 업데이트 → 성공 응답 - 잘못된 시간대 → 검증 실패 - 동시 업데이트 → 최신 우선 적용 |
| 호출 구조 | Mobile App → Load Balancer → API Server → UserProfileService → UserValidator → Database |
| 로그 처리 | - 프로필 변경 이벤트 (info) - 변경 전후 값 기록 (audit) - 검증 실패 사유 (warn) |
동의서 관리 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 동의서 버전 관리 |
| 소속 클래스 | UserProfileService, ConsentManager |
| 관련 Endpoint | PUT /users/current/consent |
| 입력 데이터 | - consentType: string (privacy/terms/marketing) - version: string - accepted: boolean - timestamp: datetime |
| 출력 데이터 | - consentId: string - status: string (accepted/rejected) - effectiveDate: datetime |
| 주요 알고리즘 | - 동의서 버전 확인 - 이전 동의 이력 조회 - 법적 요구사항 검증 - 동의 철회 가능 여부 확인 |
| 예외 처리 | - 필수 동의 거부: 422 Unprocessable Entity - 잘못된 버전: 400 Bad Request - 이미 처리됨: 409 Conflict |
| 테스트 조건 | - 신규 동의 → 기록 생성 - 동의 철회 → 서비스 제한 확인 - 버전 업데이트 → 재동의 요청 |
| 호출 구조 | Client → Load Balancer → API Server → ConsentManager → Audit Service → Database |
| 로그 처리 | - 동의 상태 변경 (audit) - 법적 준수 기록 (compliance) - 타임스탬프 기록 (info) |
2.2 치료 플로우 모듈
2.2.1 학습 컨텐츠 서비스 (LearningService)
학습 콘텐츠 번들 조회 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 학습 콘텐츠 번들 조회 |
| 소속 클래스 | LearningService, BundleManager |
| 관련 Endpoint | GET /v1/learning/bundles/{bundleId} |
| 입력 데이터 | - bundleId: string (번들 ID) - language: string (언어 코드: ko-KR, de-DE, en-US) - includeLessons: boolean (레슨 포함 여부) - includeQuizzes: boolean (퀴즈 포함 여부) |
| 출력 데이터 | - bundleId: string - version: string - sessions: Session[] (세션 및 레슨 정보) - quizzes: Quiz[] (퀴즈 정보) - language: string (응답 언어) |
| 주요 알고리즘 | - 번들 캐시 확인 및 업데이트 - 언어별 콘텐츠 번역 처리 - 세션-레슨 계층 구조 구성 - 효율적인 캐싱을 위한 번들 ID 기반 관리 |
| 예외 처리 | - 번들 없음: 404 Not Found - 잘못된 언어 코드: 400 Bad Request - 권한 부족: 403 Forbidden |
| 테스트 조건 | - 신규 번들 조회 → 전체 데이터 반환 - 동일 번들 재조회 → 캐시 활용 - 언어 변경 → 번역된 콘텐츠 제공 |
| 호출 구조 | Mobile App → Load Balancer → API Server → LearningService → BundleManager → Cache/Database |
| 로그 처리 | - 번들 조회 요청 (info) - 캐시 히트/미스 (debug) - 번들 버전 정보 (info) |
일일 콘텐츠 조회 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 일일 추천 콘텐츠 조회 |
| 소속 클래스 | LearningService, DailyContentService |
| 관련 Endpoint | GET /v1/learning/daily/content |
| 입력 데이터 | - userId: string - date: string (YYYY-MM-DD, 선택) - timezone: string (사용자 시간대) |
| 출력 데이터 | - date: string (조회 날짜) - recommendedLesson: Lesson (추천 레슨) - alternativeLessons: Lesson[] (대체 레슨) - dayIndex: number (치료 일차) - completionStatus: string |
| 주요 알고리즘 | - dayIndex 기반 레슨 매칭 - 사용자 진행 상태 확인 - 45일 프로그램 label 매핑 - 대체 콘텐츠 추천 로직 |
| 예외 처리 | - 사용자 없음: 404 Not Found - 치료 기간 외: 204 No Content - 잘못된 날짜: 400 Bad Request |
| 테스트 조건 | - 정상 일차 → 해당 레슨 추천 - 이미 완료 → 다음 레슨 추천 - 치료 종료 → 빈 응답 |
| 호출 구조 | Mobile App → Load Balancer → API Server → DailyContentService → UserCycleService → Database |
| 로그 처리 | - 일일 콘텐츠 요청 (info) - 추천 레슨 ID (info) - dayIndex 매핑 (debug) |
학습 진행률 조회 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 전체 학습 진행률 조회 |
| 소속 클래스 | LearningService, ProgressService |
| 관련 Endpoint | GET /v1/learning/progress |
| 입력 데이터 | - userId: string (사용자 ID) |
| 출력 데이터 | - completedLessons: number - totalLessons: number (42개) - progressPercentage: number - lastCompletedAt: timestamp - currentDay: number |
| 주요 알고리즘 | - 완료 레슨 수 계산 - 진행률 백분율 계산 - 현재 치료 일차 확인 - 최근 학습 시간 추적 |
| 예외 처리 | - 사용자 없음: 404 Not Found - 학습 기록 없음: 200 OK (0% 진행률) |
| 테스트 조건 | - 신규 사용자 → 0% 진행률 - 일부 완료 → 정확한 백분율 - 전체 완료 → 100% 진행률 |
| 호출 구조 | Mobile App → Load Balancer → API Server → ProgressService → Database |
| 로그 처리 | - 진행률 조회 (info) - 완료 레슨 수 (debug) |
레슨 완료 처리 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 레슨 완료 처리 |
| 소속 클래스 | LearningService, CompletionService |
| 관련 Endpoint | POST /v1/learning/lessons/{lessonId}/complete |
| 입력 데이터 | - lessonId: string (레슨 ID) - completedAt: timestamp (완료 시간) |
| 출력 데이터 | - success: boolean - nextLessonId: string (다음 해금된 레슨) - unlockedAt: timestamp - totalProgress: number |
| 주요 알고리즘 | - 레슨 완료 상태 업데이트 - 다음 레슨 자동 해금 처리 - 46번 레슨 특별 처리 (90일 후 해금) - 진행률 재계산 |
| 예외 처리 | - 이미 완료됨: 400 Bad Request - 레슨 미해금: 403 Forbidden - 레슨 없음: 404 Not Found |
| 테스트 조건 | - 정상 완료 → 다음 레슨 해금 - 45번 완료 → 46번 90일 대기 - 중복 완료 → 오류 반환 |
| 호출 구조 | Mobile App → Load Balancer → API Server → CompletionService → UnlockService → Database |
| 로그 처리 | - 레슨 완료 이벤트 (info) - 다음 레슨 해금 (info) - 진행률 업데이트 (debug) |
퀴즈 응답 제출 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 퀴즈 응답 제출 |
| 소속 클래스 | LearningService, QuizService |
| 관련 Endpoint | POST /v1/learning/quiz/{quizId}/answers |
| 입력 데이터 | - quizId: string (퀴즈 ID) - answer: string (사용자 답변) - lessonId: string (관련 레슨) - timeSpent: number (소요 시간) |
| 출력 데이터 | - isCorrect: boolean - correctAnswer: string - explanation: string (해설) - score: number - attemptCount: number |
| 주요 알고리즘 | - 정답 검증 처리 - 점수 계산 및 저장 - 재시도 횟수 추적 - 학습 통계 업데이트 |
| 예외 처리 | - 퀴즈 없음: 404 Not Found - 잘못된 답변 형식: 400 Bad Request - 제한 초과: 429 Too Many Requests |
| 테스트 조건 | - 정답 입력 → 점수 획득 - 오답 입력 → 해설 제공 - 여러 시도 → 기록 누적 |
| 호출 구조 | Mobile App → Load Balancer → API Server → QuizService → Database → Analytics |
| 로그 처리 | - 퀴즈 응답 제출 (info) - 정답 여부 (info) - 퀴즈 통계 업데이트 (debug) |
2.2.2 수면 일기 서비스 (SleepDiaryService)
수면 기록 생성 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 수면 기록 생성 (당일 일차) |
| 소속 클래스 | SleepDiaryService, SleepValidator |
| 관련 Endpoint | POST /v1/sleep/logs/day-index |
| 입력 데이터 | - dayIndex: number (당일 일차) - dns: boolean (전혀 못 잤는지) - lot: timestamp (잠자리에 든 시각, 18:00 이후) - aet: timestamp (일어난 시각) - sleepQuality: number (1-5) - solMinutes: number (입면 지연 시간) - wasoMinutes: number (중간 각성 시간) - pill: boolean (수면제 복용) - napMinutes: number (낮잠 시간) - negativeFactorIds: array - positiveFactorIds: array |
| 출력 데이터 | - sleepLog: object (생성된 수면 기록) - tstMinutes: number (총 수면 시간) - sleepEfficiency: number (수면 효율) - goalAdherence: object (목표 달성 여부) - date: string (YYYY-MM-DD) |
| 주요 알고리즘 | - 당일 일차만 생성/수정 가능 검증 - LOT 18:00 이후 검증 - 5분 단위 시간 검증 - TST 자동 계산 (TIB - SOL - WASO) - 수면 효율 계산 (TST/TIB) - 목표 달성 여부 평가 |
| 예외 처리 | - 당일 아님: 400 DATE_VALIDATION_FAILED - 시간 오류: 400 SLEEP_TIME_VALIDATION_FAILED - 중복 기록: 409 SLEEP_LOG_ALREADY_EXISTS - 치료 정지: 403 TREATMENT_SUSPENDED - DNS=true일 때 수면 데이터: 400 UNEXPECTED_SLEEP_DATA |
| 테스트 조건 | - 당일 일차 → 저장 성공 - 과거 일차 → 오류 반환 - LOT 18:00 이전 → 검증 실패 - DNS=true → 수면 데이터 제외 |
| 호출 구조 | Mobile App → Load Balancer → API Server → SleepDiaryService → Validator → Database → GoalAdherence |
| 로그 처리 | - 수면 기록 생성 (info) - 일차 검증 (debug) - TST/효율 계산 (debug) - 목표 달성 평가 (info) |
수면 목표 조회 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 수면 목표 조회 (일차별) |
| 소속 클래스 | SleepGoalService, GoalManager |
| 관련 Endpoint | GET /v1/sleep/goals/day-index/{dayIndex} |
| 입력 데이터 | - dayIndex: number (조회할 일차) - userId: string (인증 토큰에서 추출) |
| 출력 데이터 | - id: string (목표 ID) - targetDayIndex: number - targetLOT: timestamp (목표 취침 시각) - targetAET: timestamp (목표 기상 시각) - rTIBMinutes: number (권장 침대 체류 시간) - goalType: string (RTIB_ALGORITHM/USER/SYSTEM) |
| 주요 알고리즘 | - 일차별 목표 조회 - rTIB 적용 여부 확인 - 사용자 설정 목표 확인 - 시스템 기본값 적용 - 목표 타입 구분 (rTIB 알고리즘/사용자 설정/시스템) |
| 예외 처리 | - 목표 없음: 404 SLEEP_GOAL_NOT_FOUND - 잘못된 일차: 400 INVALID_DAY_INDEX - 권한 없음: 403 INSUFFICIENT_PERMISSIONS |
| 테스트 조건 | - rTIB 처방 후 → rTIB 목표 반환 - 사용자 설정 → USER 타입 반환 - 목표 없음 → 404 오류 |
| 호출 구조 | Mobile App → Load Balancer → API Server → GoalManager → Database → Cache |
| 로그 처리 | - 목표 조회 요청 (info) - 목표 타입 (debug) - 캐시 히트/미스 (debug) |
rTIB 계산 및 조회 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | rTIB 계산 및 조회 |
| 소속 클래스 | RTIBService, RTIBCalculator |
| 관련 Endpoint | GET /v1/sleep/rtib/day-index/{dayIndex} |
| 입력 데이터 | - dayIndex: number (rTIB 처방 일차) - userId: string (인증 토큰에서 추출) |
| 출력 데이터 | - id: string (rTIB ID) - dayIndex: number - date: string (YYYY-MM-DD) - rTIB: number (권장 침대 체류 시간, 분) - calculationBasis: object (계산 근거) - avgTstMinutes: number (평균 총 수면 시간) - avgSe: number (평균 수면 효율) - validLogCount: number (유효 기록 수) - isFirstRtib: boolean - calculatedOnSleepLogCreation: boolean |
| 주요 알고리즘 | - 직전 7일 수면 기록 수집 - DNS 제외한 유효 기록 필터링 - 평균 TST 계산 - rTIB = avgTST / 0.9 (목표 효율 90%) - 최소 4개 이상 기록 필요 - 7일차마다 자동 계산 |
| 예외 처리 | - 데이터 부족: 400 INSUFFICIENT_DATA - rTIB 없음: 404 RTIB_RECOMMENDATION_NOT_FOUND - 계산 실패: 500 STATISTICS_CALCULATION_FAILED |
| 테스트 조건 | - 7일 전체 기록 → 정상 계산 - 4-6개 기록 → 부분 계산 - 4개 미만 → 계산 불가 - 첫 rTIB → isFirstRtib: true |
| 호출 구조 | Mobile App → Load Balancer → API Server → RTIBCalculator → Database → Pub/Sub |
| 로그 처리 | - rTIB 계산 시작 (info) - 유효 기록 수 (debug) - 계산 결과 (info) - 처방 생성 이벤트 (info) |
목표 기상 시각 설정 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 목표 기상 시각 설정 (rTIB 처방일) |
| 소속 클래스 | SleepGoalService, WakeTimeManager |
| 관련 Endpoint | PATCH /v1/sleep/goals/target-wake-time |
| 입력 데이터 | - targetAET: string (HH:MM 형식) - targetDayIndex: number (다음 일차) - targetDate: string (YYYY-MM-DD) |
| 출력 데이터 | - id: string (목표 ID) - targetDayIndex: number - targetDate: string - targetLOT: timestamp (계산된 취침 시각) - targetAET: timestamp (설정된 기상 시각) - rTIBInMinutes: number - goalType: string (USER) - timezoneId: string - timezoneOffset: number |
| 주요 알고리즘 | - rTIB 처방 당일 검증 - 다음 일차 목표 설정 - targetLOT = targetAET - rTIB - 목표 타입을 USER로 변경 - 시간대 정보 적용 |
| 예외 처리 | - 처방일 아님: 400 TARGET_WAKE_TIME_CHANGE_NOT_ALLOWED - 잘못된 시간: 400 INVALID_FORMAT - 잘못된 시간대: 400 INVALID_TIMEZONE |
| 테스트 조건 | - rTIB 처방일 → 설정 성공 - 비처방일 → 오류 반환 - LOT 자동 계산 검증 - 다음 일차 검증 |
| 호출 구조 | Mobile App → Load Balancer → API Server → WakeTimeManager → Database → Scheduler |
| 로그 처리 | - 기상 시각 설정 (info) - 취침 시각 계산 (debug) - 스케줄러 등록 (info) |
2.3 모바일 앱 관리 모듈
2.3.1 앱 강제 업데이트 처리
앱 버전 검증 및 강제 업데이트 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 앱 강제 업데이트 기능 |
| 소속 클래스 | VersionMiddleware, AppConfigService |
| 관련 Endpoint | GET /mobile/app-settings (모든 API 요청 시 헤더 검증) |
| 입력 데이터 | - 앱 플랫폼 (iOS/Android) - 앱 버전 - 사용 중단 여부 설정 값 |
| 출력 데이터 | - 허용 여부 (200 OK or 426 Upgrade Required) - 업데이트 안내 메시지 |
| 주요 알고리즘 | - 요청 헤더의 앱 버전 확인 - 플랫폼별 최소 허용 버전과 비교 - 강제 업데이트 설정 여부 판단 |
| 예외 처리 | - 버전 없음: 400 Bad Request - 낮은 버전: 426 Upgrade Required 반환 + 업데이트 안내 |
| 테스트 조건 | - 최소 허용 버전 미만 → 업데이트 강제 확인 - 정상 버전 → 통과 확인 |
| 호출 구조 | 모든 API 요청에 VersionMiddleware가 선행 적용 업데이트 필요 시 요청 차단 |
| 로그 처리 | - 차단된 요청, 버전 불일치 기록 (warn, info) |
2.4 설문 및 평가 모듈
2.4.1 설문 관리 서비스 (QuestionnaireService)
설문 응답 제출 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 설문 응답 데이터 제출 및 평가 |
| 소속 클래스 | QuestionnaireService, ScoreCalculator |
| 관련 Endpoint | POST /questionnaires/{id}/responses |
| 입력 데이터 | - questionnaireId: string - responses: Answer[] - completedAt: datetime - round: number |
| 출력 데이터 | - submissionId: string - score: ScoreResult - interpretation: string - severity: string |
| 주요 알고리즘 | - 응답 완전성 검증 - 설문별 점수 계산 (ISI, PHQ-9, GAD-7 등) - 임상적 해석 생성 - 심각도 평가 |
| 예외 처리 | - 불완전한 응답: 422 Unprocessable Entity - 잘못된 설문 ID: 404 Not Found - 중복 제출: 409 Conflict |
| 테스트 조건 | - 모든 문항 응답 → 점수 계산 - 부분 응답 → 검증 실패 - 점수별 해석 정확성 확인 |
| 호출 구조 | Mobile App → Load Balancer → API Server → QuestionnaireService → ScoreCalculator → Database |
| 로그 처리 | - 설문 제출 기록 (info) - 점수 및 평가 결과 (info) - 임상적 알림 필요 시 (warn) |
2.5 이완 및 치료 모듈
2.5.1 이완 컨텐츠 서비스 (RelaxationService)
이완 세션 기록 기능 상세 설계
| 항목 | 내용 |
|---|---|
| SRS ID | |
| 기능 명칭 | 이완 세션 사용 기록 및 효과 평가 |
| 소속 클래스 | RelaxationService, SessionRecorder |
| 관련 Endpoint | POST /relaxation/sessions |
| 입력 데이터 | - contentId: string - sessionDuration: number - completionStatus: string - effectivenessRating: number (1-10) - technique: string |
| 출력 데이터 | - sessionId: string - insights: SessionInsights - recommendations: string[] - achievements: Achievement[] |
| 주요 알고리즘 | - 세션 완료율 계산 - 효과성 추세 분석 - 선호 기법 파악 - 다음 컨텐츠 추천 |
| 예외 처리 | - 잘못된 컨텐츠 ID: 404 Not Found - 비정상 세션 시간: 400 Bad Request - 서버 오류: 500 Internal Server Error |
| 테스트 조건 | - 정상 완료 → 기록 저장 - 중단된 세션 → 부분 기록 - 반복 사용 → 패턴 분석 |
| 호출 구조 | Client → Load Balancer → API Server → RelaxationService → Database → Analytics |
| 로그 처리 | - 세션 시작/종료 (info) - 효과성 평가 기록 (info) - 사용 패턴 분석 (debug) |
3. 데이터베이스 설계
3.1 데이터베이스 스키마 구조
SleepQ 시스템은 PostgreSQL 데이터베이스를 사용하며, 데이터 보안과 규정 준수를 위해 다음과 같은 스키마로 분리됩니다:
- private 스키마: 개인정보(PII) 및 민감 데이터 저장 (GDPR 준수)
- auth 스키마: 인증 관련 시스템 설정 데이터
- sleep 스키마: 수면 요인 등 비개인정보 설정 데이터
- learning 스키마: 학습 콘텐츠, 세션, 퀴즈 등 시스템 데이터
- questionnaire 스키마: 설문 정의, 문항, 점수 계산 규칙
- mobile 스키마: 모바일 앱 설정 및 버전 관리
- operation 스키마: 내부 운영자 및 의료진 데이터
3.2 도메인별 엔티티 관계 다이어그램 (ERD)
3.2.1 Auth 도메인 ERD
3.2.2 User 도메인 ERD
3.2.3 Sleep 도메인 ERD
3.2.4 Learning 도메인 ERD
3.2.5 Questionnaire 도메인 ERD
3.2.6 Mobile 도메인 ERD
3.2.7 Relaxation 도메인 ERD
3.2.8 IAM 도메인 ERD
3.2.9 Agent 도메인 ERD
3.2.10 관계형 데이터 구조 요약
- 사용자 중심 설계: User 엔티티를 중심으로 모든 도메인이 연결
- 치료 주기 관리: UserCycle이 Sleep, Learning, Questionnaire, Relaxation 도메인과 연동
- 권한 관리: IAM 도메인의 Role-Permission 모델로 세밀한 접근 제어
- 다중 스키마 분리: 개인정보(private), 시스템 데이터(각 도메인 스키마), 운영 데이터(operation)의 명확한 분리
- 이력 관리: 주요 엔티티별 변경 이력 추적 (UserStatusHistory, AppSettingsHistory, AgentConversation 등)
- 다국어 지원: Translation 테이블을 통한 다국어 콘텐츠 관리 (Learning, Questionnaire, Relaxation)
- Agent 기반 상호작용: AI 에이전트를 통한 개인화된 치료 지원
3.3 데이터 저장 전략
3.3.1 인덱싱 전략
주요 인덱스 설계
-
User 테이블
- UNIQUE INDEX:
email(로그인 조회) - INDEX:
status, userType(사용자 필터링) - INDEX:
createdAt DESC(최신 가입자 조회)
- UNIQUE INDEX:
-
SleepLog 테이블
- INDEX:
userId, userCycleId, date DESC(사용자별 수면 기록 조회) - INDEX:
userCycleId, dayIndex(치료 주기별 일차 조회) - INDEX:
createdAt DESC(최신 기록 조회)
- INDEX:
-
QuestionnaireResponse 테이블
- INDEX:
userId, questionnaireType, roundNumber(사용자별 설문 조회) - INDEX:
completedAt DESC(최근 완료 설문 조회)
- INDEX:
-
LearningProgress 테이블
- INDEX:
userId, userCycleId, status(학습 진도 조회) - INDEX:
lessonId, completedAt(레슨별 완료 통계)
- INDEX:
복합 인덱스 최적화
- 카디널리티가 높은 컬럼을 앞에 배치
- WHERE 절에 자주 사용되는 컬럼 우선 배치
- ORDER BY 절에 사용되는 컬럼 포함
3.3.2 파티셔닝 전략
날짜 기반 파티셔닝
- SleepLog: 월별 파티션 (3개월 이상 데이터 아카이빙)
- AuditLog: 월별 파티션 (6개월 이상 데이터 BigQuery 이관)
- AgentConversation: 분기별 파티션
사용자 기반 샤딩 (확장 시)
- 사용자 ID 해시 기반 수평 분할
- 지역별 데이터 로컬리티 고려
3.3.3 캐싱 전략
Redis 캐싱 계층
- 사용자 프로필: TTL 1시간
- 수면 목표: TTL 24시간
- 학습 진도: TTL 30분
- 설문 번들: TTL 7일
- 이완 콘텐츠 메타데이터: TTL 24시간
캐시 무효화 정책
- Write-through 캐싱: 데이터 변경 시 즉시 캐시 업데이트
- 이벤트 기반 무효화: Pub/Sub 통한 캐시 동기화
3.3.4 데이터 무결성
제약 조건
- 외래 키 제약: CASCAde/RESTRICT 정책 적용
- CHECK 제약:
- SleepLog:
lot < aet(취침 시각 < 기상 시각) - SleepEfficiency:
0 <= value <= 1 - SleepQuality:
1 <= value <= 5
- SleepLog:
- UNIQUE 제약:
- User.email
- Group.name
- Role.name
트랜잭션 관리
- ACID 특성 보장을 위한 트랜잭션 래핑
- Optimistic Locking: version 컬럼 활용
- 데드락 방지를 위한 일관된 잠금 순서
트리거 및 스토어드 프로시저
updatedAt자동 업데이트 트리거- 수면 효율 자동 계산 트리거
- 데이터 정합성 검증 프로시저
4. API 설계
4.1 주요 API 엔드포인트 목록
4.1.1 인증 및 세션 관리 (Auth Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 액세스 코드 검증 | POST | /auth/access-code/validate | 일회성 액세스 코드 유효성 검증 |
| 사용자 로그인 | POST | /auth/login | 사용자 인증 및 JWT 토큰 발급 |
| 토큰 갱신 | POST | /auth/token/refresh | JWT 토큰 갱신 |
| 로그아웃 | POST | /auth/logout | 사용자 로그아웃 및 세션 무효화 |
| 앱 보안 인증 | POST | /auth/app/challenge | 앱 무결성 검증을 위한 챌린지 생성 |
| 앱 인증 완료 | POST | /auth/app/complete-challenge | 앱 보안 인증 완료 처리 |
4.1.2 사용자 관리 (User Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 사용자 프로필 조회 | GET | /users/profile | 사용자 프로필 정보 조회 |
| 프로필 업데이트 | PUT | /users/profile | 사용자 프로필 정보 수정 |
| 현재 사용자 정보 | GET | /users/current | 현재 사용자 상태 및 치료 정보 |
| 동의서 업데이트 | PUT | /users/current/consent | 사용자 동의서 상태 업데이트 |
| 서비스 일시중단 | POST | /users/suspend | 치료 서비스 일시 중단 |
| 서비스 재개 | POST | /users/resume | 치료 서비스 재개 |
4.1.3 수면 관리 (Sleep Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 수면 목표 설정 | POST | /sleep/goals | 사용자별 수면 목표 설정 |
| 수면 기록 제출 | POST | /sleep/logs | 일일 수면 기록 데이터 제출 |
| 수면 기록 조회 | GET | /sleep/logs | 기간별 수면 기록 조회 |
| 현재 수면 기록 | GET | /sleep/logs/current | 오늘 수면 기록 조회 |
| 수면 기록 수정 | PUT | /sleep/logs/{id} | 기존 수면 기록 수정 |
4.1.4 설문 관리 (Questionnaire Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 현재 설문 조회 | GET | /questionnaires/current | 현재 라운드 설문 조회 |
| 설문 응답 제출 | POST | /questionnaires/{id}/responses | 설문 응답 데이터 제출 |
| 응답 이력 조회 | GET | /questionnaires/responses | 설문 응답 이력 조회 |
4.1.5 학습 컨텐츠 (Learning Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 학습 컨텐츠 조회 | GET | /learning/content | 개인별 맞춤 학습 컨텐츠 목록 |
| 학습 진도 기록 | POST | /learning/progress | 학습 컨텐츠 진도 기록 |
| 진도 현황 조회 | GET | /learning/progress | 학습 진도 현황 조회 |
4.1.6 이완 컨텐츠 (Relaxation Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 이완 컨텐츠 조회 | GET | /relaxation/content | 이완 기법별 컨텐츠 목록 |
| 이완 세션 기록 | POST | /relaxation/sessions | 이완 세션 사용 기록 |
4.1.7 권한 관리 (IAM Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 사용자 권한 조회 | GET | /iam/permissions | 현재 사용자 권한 정보 |
4.1.8 모바일 설정 (Mobile Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 앱 설정 조회 | GET | /mobile/app-settings | 앱 설정 및 피처 플래그 조회 |
| 설정 업데이트 | POST | /mobile/settings/update | 모바일 설정 업데이트 |
4.1.9 AI 치료 관리 (Agent Treatment Flow Domain)
| API | 메서드 | 경로 | 설명 |
|---|---|---|---|
| 치료 단계 조회 | GET | /agent-treatment-flow/current-stage | 현재 치료 단계 및 진행 상태 |
| 대화 세션 시작 | POST | /agent-treatment-flow/sessions | AI 상담 대화 세션 시작 |
| AI 상담 기록 | GET | /agent-board/conversations | AI 상담 대화 기록 조회 |
4.2 API 공통 규칙
4.2.1 인증 헤더
- Authorization:
Bearer <JWT_TOKEN>(모든 인증 필요 API) - Content-Type:
application/json - X-Client-Version:
<APP_VERSION>(앱 버전) - X-Device-ID:
<DEVICE_ID>(기기 식별자)
4.2.2 표준 HTTP 상태 코드
- 200 OK: 성공적인 요청 처리
- 201 Created: 리소스 생성 성공
- 400 Bad Request: 잘못된 요청 데이터
- 401 Unauthorized: 인증 실패
- 403 Forbidden: 권한 부족
- 404 Not Found: 리소스 없음
- 429 Too Many Requests: 요청 제한 초과
- 500 Internal Server Error: 서버 오류
4.2.3 에러 응답 형식
- error.code: 오류 식별 코드
- error.message: 사용자 친화적 오류 메시지
- error.details: 상세 오류 정보 (선택사항)
- timestamp: 오류 발생 시간
- path: 요청 API 경로
- correlationId: 추적용 상관관계 ID
4.2.4 페이지네이션
- page: 페이지 번호 (기본값: 1)
- limit: 페이지당 항목 수 (기본값: 20, 최대: 100)
- sortBy: 정렬 기준 필드
- sortOrder: 정렬 순서 (asc/desc)
4.3 실시간 통신 (WebSocket)
- treatment-stage-changed: 치료 단계 변경 알림
- sleep-reminder: 수면 관련 리마인더
- goal-achievement: 목표 달성 알림
- agent-message: AI 에이전트 메시지
- system-notification: 시스템 공지사항
5. 핵심 알고리즘 설계
5.1 수면 효율성 계산 알고리즘
목적: 사용자의 수면 품질을 정량적으로 측정
계산 방식:
- 침대에 있던 총 시간 = 취침 시간부터 기상 시간까지의 총 시간
- 실제 수면 시간 = 총 시간 - 수면 잠복기 - 야간 각성 시간
- 수면 효율성 = (실제 수면 시간 / 침대에 있던 총 시간) × 100
임계값 기준:
- 85% 이상: 양호한 수면 효율성
- 75-84%: 보통 수면 효율성
- 75% 미만: 개선 필요한 수면 효율성
5.2 개인화 추천 알고리즘
목적: 사용자 수면 패턴 분석을 통한 맞춤형 치료 권장사항 제공
추천 기준:
5.2.1 수면 효율성 기반 추천
- 85% 미만: 수면 제한 요법 권장 (우선순위: 높음)
- 75% 미만: 자극 제어 기법 추가 권장 (우선순위: 높음)
5.2.2 수면 잠복기 기반 추천
- 30분 이상: 이완 기법 훈련 권장 (우선순위: 중간)
- 45분 이상: 인지 재구성 기법 권장 (우선순위: 높음)
5.2.3 야간 각성 기반 추천
- 주 3회 이상: 수면 위생 교육 강화 권장
- 매일 발생: 의료진 상담 권장
5.3 치료 진행도 평가 알고리즘
목적: 사용자의 치료 진행 상태를 종합적으로 평가
평가 요소:
- 수면 기록 완성도: 주간 기록률 × 25%
- 학습 컨텐츠 진도: 완료율 × 25%
- 설문 응답 성실도: 응답 완전성 × 25%
- 수면 개선도: 효율성 향상 정도 × 25%
단계 전환 기준:
- 종합 점수 80% 이상: 다음 단계 진행 가능
- 종합 점수 60-79%: 현재 단계 연장
- 종합 점수 60% 미만: 개별 상담 필요
6. 오류 처리 및 안전성 설계
6.1 오류 분류 체계
오류 카테고리:
- VALIDATION: 입력 데이터 유효성 검증 오류
- AUTHENTICATION: 인증 관련 오류
- AUTHORIZATION: 권한 부족 오류
- BUSINESS_LOGIC: 비즈니스 로직 처리 오류
- SYSTEM: 시스템 내부 오류
- EXTERNAL_SERVICE: 외부 서비스 연동 오류
6.2 오류 처리 원칙
- 사용자 친화적 메시지: 기술적 세부사항 숨김
- 상세 로깅: 디버깅을 위한 내부 로그 기록
- 안전한 실패: 시스템 다운보다는 기능 제한
- 추적 가능성: 고유 상관관계 ID를 통한 오류 추적
6.3 복구 메커니즘
- 자동 재시도: 일시적 네트워크 오류 대응
- Graceful Degradation: 부분 기능 장애 시 핵심 기능 유지
- 백업 데이터: 기본값 또는 캐시된 데이터 제공
7. 성능 최적화 설계
7.1 캐싱 전략
Redis 캐싱 계층:
- 사용자 프로필: 1시간 TTL, 로그인 시 갱신
- 수면 분석 결과: 30분 TTL, 새 데이터 입력 시 무효화
- 학습 컨텐츠: 24시간 TTL, 관리자 업데이트 시 갱신
- 설문 스코어: 1시간 TTL, 응답 완료 시 갱신
7.2 데이터베이스 최적화
파티셔닝 전략:
- 월별 파티셔닝: 수면 기록 데이터를 월 단위로 분할
- 읽기 복제본: 분석 쿼리는 읽기 전용 복제본으로 라우팅
- 인덱스 최적화: 자주 사용되는 쿼리 패턴에 맞춘 복합 인덱스
7.3 API 성능 최적화
- 응답 압축: Gzip 압축을 통한 전송 데이터 크기 최소화
- 페이지네이션: 대용량 데이터 조회 시 페이지 단위 분할
- 비동기 처리: 시간이 오래 걸리는 작업은 백그라운드 처리
8. 보안 설계
8.1 데이터 보호
암호화 전략:
- 전송 중 암호화: TLS 1.2+ 프로토콜 사용
- 저장 중 암호화: AES-256-GCM 알고리즘 적용
- 개인정보 암호화: 이름, 연락처 등 민감 정보 별도 암호화
- 키 관리: Google Cloud Secret Manager 활용
8.2 접근 제어
인증 및 권한:
- 다단계 인증: JWT + 앱 보안 인증 조합
- 최소 권한 원칙: 필요한 최소한의 권한만 부여
- 세션 관리: 자동 토큰 만료 및 갱신
- API 키 보안: 키 순환 및 접근 로그 모니터링
8.3 입력 검증
데이터 유효성 검사:
- 형식 검증: 날짜, 시간, 이메일 등 형식 확인
- 범위 검증: 수면 품질 점수 1-10 범위 확인
- SQL 주입 방지: 매개변수화된 쿼리 사용
- XSS 방지: 사용자 입력 데이터 이스케이프 처리
9. 품질 보증 설계
9.1 테스트 전략
테스트 계층:
- 단위 테스트: 개별 함수 및 메서드 테스트
- 통합 테스트: API 엔드포인트 전체 플로우 테스트
- 시스템 테스트: 전체 시스템 기능 검증
- 성능 테스트: 부하 및 스트레스 테스트
9.2 테스트 시나리오
핵심 테스트 케이스:
- 수면 효율성 계산: 다양한 수면 패턴에 대한 정확성 검증
- 개인화 추천: 사용자 프로필별 적절한 권장사항 생성
- 데이터 무결성: 동시 접근 시 데이터 일관성 확인
- 오류 처리: 예외 상황에서의 안전한 동작 확인
9.3 자동화 테스트
- CI/CD 파이프라인: 코드 커밋 시 자동 테스트 실행
- 회귀 테스트: 새 기능 추가 시 기존 기능 영향도 확인
- 데이터 검증: 실제 운영 데이터를 활용한 검증
10. 운영 및 배포 설계
10.1 환경 관리
환경별 구성:
- Development: 개발 및 초기 테스트 환경
- Staging: 실제 운영과 동일한 검증 환경
- Production: 실제 서비스 운영 환경
10.2 배포 전략
안전한 배포:
- Blue-Green 배포: 무중단 서비스 전환
- 카나리 배포: 소수 사용자 대상 사전 검증
- 롤백 계획: 문제 발생 시 이전 버전으로 즉시 복구
10.3 설정 관리
- 환경 변수: 민감 정보는 환경 변수로 관리
- 설정 검증: 배포 전 설정 값 유효성 확인
- 변경 추적: 설정 변경 이력 기록 및 승인 프로세스
11. 모니터링 및 관찰성 설계
11.1 성능 메트릭
주요 지표:
- 응답 시간: P95, P99, 평균 응답 시간
- 처리량: 초당 요청 수 (RPS)
- 오류율: 전체 요청 대비 오류 비율
- 활성 사용자: 동시 접속 사용자 수
11.2 비즈니스 메트릭
치료 효과 지표:
- 수면 개선도: 치료 시작 대비 수면 효율성 개선 정도
- 앱 사용률: 일일/주간 활성 사용자 비율
- 컨텐츠 완주율: 학습 모듈 완료 비율
- 설문 응답률: 정기 설문 참여 비율
11.3 알람 및 대응
임계값 기반 알람:
- 응답 시간 > 2초: 성능 저하 경고
- 오류율 > 1%: 시스템 안정성 경고
- DB 연결 실패: 즉시 긴급 알람
- 수면 효율성 계산 오류: 핵심 기능 장애 알람
11.4 로그 관리
- 구조화된 로깅: JSON 형태의 일관된 로그 포맷
- 중앙집중 수집: Cloud Logging → BigQuery 파이프라인
- 보존 정책: 개인정보 관련 로그 자동 삭제 주기 설정
- 검색 최적화: 로그 분석 및 트러블슈팅 지원
12. 변경 이력
| 버전 | 날짜 | 작성자 | 변경 내용 |
|---|---|---|---|
| 0.1.0 | 2025-08-07 | bok@weltcorp.com | 최초 작성 |