HealthSync_BE/design/내부 시퀀스 설계서 - Health Service.txt

179 lines
8.3 KiB
Plaintext

!theme mono
skinparam sequenceArrowThickness 2
skinparam sequenceParticipantBorderThickness 2
skinparam sequenceActorBorderThickness 2
skinparam sequenceGroupBorderThickness 2
title Health Service 내부 시퀀스 다이어그램 (역설계 - 정상치 기준 비교 포함)
participant "HealthController" as HealthCtrl
participant "CheckupSyncUseCase" as SyncUC
participant "CheckupQueryUseCase" as QueryUC
participant "FileUploadUseCase" as FileUC
participant "HealthProfileDomainService" as HealthDomainSvc
participant "CheckupAnalysisDomainService" as AnalysisDomainSvc
participant "NormalRangeDomainService" as NormalDomainSvc
participant "HealthRepository" as HealthRepo
participant "HealthCheckupRawRepository" as RawRepo
participant "NormalRangeRepository" as NormalRepo
participant "UserServiceAdapter" as UserAdapter
participant "BlobStorageAdapter" as BlobAdapter
participant "CacheAdapter" as CacheAdapter
participant "EventPublisherAdapter" as EventAdapter
participant "PostgreSQL" as PostgreSQL
participant "Redis Cache" as Redis
participant "Azure Blob Storage" as BlobStorage
participant "Azure Service Bus" as ServiceBus
== 1. POST /api/health/checkup/sync (건강검진 결과 연동) ==
HealthCtrl -> SyncUC: syncCheckupData(userId)
SyncUC -> UserAdapter: getUserInfo(userId)
UserAdapter -> SyncUC: UserInfo 응답 (memberSerialNumber, gender 포함)
SyncUC -> RawRepo: findNhisCheckupDataByMemberSerial(memberSerialNumber)
RawRepo -> PostgreSQL: SELECT * FROM health_checkup_raw WHERE member_serial_number = ? ORDER BY reference_year DESC
PostgreSQL -> RawRepo: 건강보험공단 건강검진 원본 데이터
SyncUC -> HealthRepo: findByMemberSerialNumber(memberSerialNumber)
PostgreSQL -> HealthRepo: 기존 가공 데이터 조회
alt 기존 데이터가 없거나 더 최신 원본 데이터가 있는 경우
SyncUC -> NormalRepo: getNormalRangesByGender(userGender)
NormalRepo -> PostgreSQL: SELECT * FROM health_normal_ranges WHERE gender_code IN (0, ?) ORDER BY item_code
note right: 성별별 + 공통 정상치 기준 조회
PostgreSQL -> NormalRepo: 성별별/공통 정상치 기준 데이터
SyncUC -> AnalysisDomainSvc: transformAndAnalyzeCheckupData(rawData, normalRanges, userGender)
AnalysisDomainSvc -> AnalysisDomainSvc: validateAndConvertData(rawData)
note right: 건강보험공단 데이터 검증 및 단위 변환
AnalysisDomainSvc -> NormalDomainSvc: compareWithNormalRanges(checkupData, normalRanges)
NormalDomainSvc -> NormalDomainSvc: evaluateEachIndicator(indicators, ranges)
note right: **각 지표별 정상/주의/위험 판정**\n- BMI, 혈압, 혈당, 콜레스테롤 등\n- 성별별 기준 적용
NormalDomainSvc -> NormalDomainSvc: calculateOverallRiskLevel(indicatorResults)
note right: **종합 위험도 레벨 계산**\n- 정상: 80-100점\n- 주의: 60-79점\n- 위험: 0-59점
NormalDomainSvc -> NormalDomainSvc: identifyAbnormalIndicators(indicatorResults)
note right: 이상 항목 식별 및 JSON 배열 생성
NormalDomainSvc -> AnalysisDomainSvc: NormalRangeAnalysisResult 반환
AnalysisDomainSvc -> AnalysisDomainSvc: createHealthCheckupEntity(transformedData, analysisResult)
AnalysisDomainSvc -> SyncUC: 변환된 HealthCheckupEntity (정상치 비교 결과 포함)
SyncUC -> HealthRepo: saveOrUpdateHealthCheckup(healthCheckupEntity)
HealthRepo -> PostgreSQL: INSERT/UPDATE health_checkups
note right: 정상치 비교 결과도 함께 저장\n- abnormal_indicators: JSON 배열\n- health_score: 0-100점\n- risk_level: normal/caution/danger
PostgreSQL -> HealthRepo: 저장 완료
end
SyncUC -> CacheAdapter: invalidateUserHealthCache(userId)
CacheAdapter -> Redis: DEL health:history:{userId} health:normal:{userId}
SyncUC -> EventAdapter: publishHealthDataSyncedEvent(userId, syncResult)
EventAdapter -> ServiceBus: 건강데이터 동기화 이벤트 발행
SyncUC -> HealthCtrl: HealthSyncResponse 반환
note right: {syncedRecords, newRecords, updatedRecords, skippedRecords, lastSyncedCheckup, message}
== 2. GET /api/health/checkup/history (건강검진 이력 조회) ==
HealthCtrl -> QueryUC: getHealthCheckupHistory(userId, limit)
QueryUC -> CacheAdapter: getCachedHealthHistory(userId)
CacheAdapter -> Redis: GET health:history:{userId}
Redis -> CacheAdapter: 캐시된 데이터 또는 null
alt 캐시 미스인 경우
QueryUC -> HealthRepo: findCheckupHistoryWithDetails(userId, limit)
HealthRepo -> PostgreSQL: SELECT * FROM health_checkups WHERE user_id = ? ORDER BY reference_year DESC LIMIT ?
PostgreSQL -> HealthRepo: 건강검진 이력 데이터 (정상치 비교 결과 포함)
QueryUC -> AnalysisDomainSvc: calculateTrendAnalysis(checkupHistory)
AnalysisDomainSvc -> AnalysisDomainSvc: analyzeTrendsByIndicator(historyData)
note right: **트렌드 분석**\n- 연도별 변화 추이\n- 개선/악화 항목 식별\n- 평균 건강점수 계산
QueryUC -> CacheAdapter: cacheHealthHistory(userId, analysisResult)
CacheAdapter -> Redis: SETEX health:history:{userId} 3600 {data}
note right: 1시간 TTL로 캐싱
end
QueryUC -> HealthCtrl: HealthHistoryResponse 반환
note right: {checkupHistory, totalRecords, averageHealthScore, trendAnalysis, normalRangeReference}
== 3. POST /api/health/checkup/upload (건강검진 파일 업로드) ==
HealthCtrl -> FileUC: uploadCheckupFile(uploadRequest)
note right: {userId, fileName, fileType, fileContent}
FileUC -> FileUC: validateFileFormat(fileType, fileContent)
note right: 파일 형식 및 크기 검증 (최대 10MB)
FileUC -> BlobAdapter: uploadToAzureBlob(fileName, fileContent)
BlobAdapter -> BlobStorage: Azure Blob Storage Upload
BlobStorage -> BlobAdapter: 업로드 완료 응답
FileUC -> HealthRepo: saveFileMetadata(fileMetadata)
HealthRepo -> PostgreSQL: INSERT INTO health_files (user_id, file_name, file_url, file_type, upload_status)
PostgreSQL -> HealthRepo: 파일 메타데이터 저장 완료
FileUC -> HealthCtrl: FileUploadResponse 반환
note right: {fileId, uploadUrl, status, message}
== 4. GET /api/health/normal-ranges (정상치 기준 조회) ==
HealthCtrl -> QueryUC: getNormalRangesByGender(genderCode)
QueryUC -> CacheAdapter: getCachedNormalRanges(genderCode)
CacheAdapter -> Redis: GET normal:ranges:{genderCode}
Redis -> CacheAdapter: 캐시된 정상치 기준 또는 null
alt 캐시 미스인 경우
QueryUC -> NormalRepo: getNormalRangesByGender(genderCode)
NormalRepo -> PostgreSQL: SELECT * FROM health_normal_ranges WHERE gender_code IN (0, ?) ORDER BY item_code
PostgreSQL -> NormalRepo: 성별별/공통 정상치 기준 데이터
QueryUC -> CacheAdapter: cacheNormalRanges(genderCode, normalRanges)
CacheAdapter -> Redis: SETEX normal:ranges:{genderCode} 86400 {data}
note right: 24시간 TTL로 캐싱 (변경 빈도 낮음)
end
QueryUC -> HealthCtrl: NormalRangeResponse 반환
note right: {normalRanges: [{itemCode, itemName, genderCode, normalMin, normalMax, cautionMin, cautionMax, dangerMin, dangerMax, unit}]}
== 예외 처리 (정상치 관련 추가) ==
alt 정상치 기준 데이터 없음
NormalRepo -> AnalysisDomainSvc: NoNormalRangeFoundException
AnalysisDomainSvc -> SyncUC: 기본 정상치 기준 사용
note right: 하드코딩된 기본값으로 대체
end
alt 정상치 비교 실패
NormalDomainSvc -> AnalysisDomainSvc: NormalRangeComparisonException
AnalysisDomainSvc -> SyncUC: 정상치 비교 없이 기본 저장
note right: 기본 건강검진 데이터만 저장
end
alt 파일 업로드 실패
BlobAdapter -> FileUC: BlobStorageException
FileUC -> HealthRepo: updateUploadStatus(fileId, "FAILED")
FileUC -> HealthCtrl: 500 Internal Server Error
end
== 캐싱 전략 (정상치 관련 추가) ==
note over QueryUC, CacheAdapter
**확장된 캐싱 전략**
- 건강검진 이력 + 정상치 비교: 1시간 캐시
- 정상치 기준 데이터: 24시간 캐시 (변경 빈도 낮음)
- 건강 점수 계산 결과: 포함 (이력과 함께)
- 트렌드 분석 결과: 포함 (이력과 함께)
- 파일 메타데이터: 30분 캐시
- 정상치 기준 업데이트 시 관련 캐시 무효화
end note