HealthSync_BE/design/데이터설계서 - Health Service.txt

303 lines
9.9 KiB
Plaintext

!theme mono
skinparam classAttributeIconSize 0
skinparam classFontSize 12
skinparam classAttributeFontSize 11
title HealthSync 역설계 - Health Service 데이터 설계서
package "Health Service Database Schema" as health_db #lightblue {
entity "health_checkups" as health_checkup {
* id : BIGINT <<PK>>
--
* user_id : VARCHAR(50)
* member_serial_number : BIGINT
* raw_id : BIGINT <<FK>>
* reference_year : INTEGER
* height_cm : DECIMAL(5,2)
* weight_kg : DECIMAL(5,2)
* waist_cm : DECIMAL(5,2)
* bmi : DECIMAL(4,2)
* visual_acuity_left : DECIMAL(3,1)
* visual_acuity_right : DECIMAL(3,1)
* hearing_avg : DECIMAL(4,1)
* systolic_bp : INTEGER
* diastolic_bp : INTEGER
* fasting_glucose : INTEGER
* total_cholesterol : INTEGER
* triglyceride : INTEGER
* hdl_cholesterol : INTEGER
* ldl_cholesterol : INTEGER
* hemoglobin : DECIMAL(4,1)
* urine_protein : INTEGER
* serum_creatinine : DECIMAL(4,1)
* ast : INTEGER
* alt : INTEGER
* gamma_gtp : INTEGER
* smoking_status : INTEGER
* drinking_status : INTEGER
* risk_level : VARCHAR(20)
* abnormal_indicators : JSON
* health_score : INTEGER
* created_at : TIMESTAMP
* updated_at : TIMESTAMP
--
+ 인덱스: idx_user_id_year
+ 인덱스: idx_member_serial_number
+ 인덱스: idx_risk_level
+ 인덱스: idx_health_score
}
entity "health_checkup_raw" as health_checkup_raw {
* raw_id : BIGINT <<PK>>
--
* member_serial_number : BIGINT
* reference_year : INTEGER
* birth_date : DATE
* name : VARCHAR(50)
* region_code : INTEGER
* gender_code : INTEGER
* age : INTEGER
* height : INTEGER
* weight : INTEGER
* waist_circumference : INTEGER
* visual_acuity_left : DECIMAL(3,1)
* visual_acuity_right : DECIMAL(3,1)
* hearing_left : INTEGER
* hearing_right : INTEGER
* systolic_bp : INTEGER
* diastolic_bp : INTEGER
* fasting_glucose : INTEGER
* total_cholesterol : INTEGER
* triglyceride : INTEGER
* hdl_cholesterol : INTEGER
* ldl_cholesterol : INTEGER
* hemoglobin : DECIMAL(4,1)
* urine_protein : INTEGER
* serum_creatinine : DECIMAL(4,1)
* ast : INTEGER
* alt : INTEGER
* gamma_gtp : INTEGER
* smoking_status : INTEGER
* drinking_status : INTEGER
* created_at : TIMESTAMP
--
+ 인덱스: idx_member_serial_year
+ 인덱스: idx_name_birthdate
+ 인덱스: idx_gender_age
}
entity "health_normal_ranges" as health_normal_range {
* item_code : VARCHAR(20) <<PK>>
* gender_code : INTEGER <<PK>>
--
* item_name : VARCHAR(100)
* normal_min : DECIMAL(10,2)
* normal_max : DECIMAL(10,2)
* caution_min : DECIMAL(10,2)
* caution_max : DECIMAL(10,2)
* danger_min : DECIMAL(10,2)
* danger_max : DECIMAL(10,2)
* unit : VARCHAR(20)
* description : TEXT
* is_active : BOOLEAN
* created_at : TIMESTAMP
* updated_at : TIMESTAMP
--
+ 인덱스: idx_item_code
+ 인덱스: idx_gender_code
}
entity "health_files" as health_file {
* file_id : VARCHAR(50) <<PK>>
--
* user_id : VARCHAR(50)
* file_name : VARCHAR(255)
* file_type : VARCHAR(50)
* file_url : VARCHAR(500)
* file_size : BIGINT
* upload_status : VARCHAR(20)
* uploaded_at : TIMESTAMP
* processed_at : TIMESTAMP
--
+ 인덱스: idx_user_id
+ 인덱스: idx_upload_status
+ 인덱스: idx_uploaded_at
}
note right of health_checkup
**가공된 건강검진 데이터**
• User Service의 사용자와 연결
• 정상치 기준과 비교 분석 완료
• 건강 점수 및 위험도 계산 결과
• 이상 항목을 JSON 배열로 저장
• 1명당 1개 레코드 (최신 데이터만)
end note
note right of health_checkup_raw
**건강보험공단 원본 데이터**
• 연도별 검진 데이터 보관
• 가공 전 원본 데이터 유지
• 개인정보 포함 (이름, 생년월일)
• 성별/나이별 통계 분석 용도
• 여러 연도 데이터 보관 가능
end note
note right of health_normal_range
**건강검진 정상치 기준**
• 성별별 정상치 기준 관리
• gender_code: 0(공통), 1(남성), 2(여성)
• 정상/주의/위험 3단계 범위
• 의료진 검토 후 업데이트
• 마스터 데이터 성격
end note
note right of health_file
**업로드된 건강검진 파일**
• Azure Blob Storage 연동
• PDF, 이미지 파일 지원
• 업로드 상태 추적
• OCR 처리 결과 연동 준비
end note
}
package "관계 정의" as relationships {
health_checkup ||--|| health_checkup_raw : raw_id
health_checkup }|--|| health_normal_range : 정상치_비교
health_file }|--|| health_checkup : 파일_연동
note as n1
**외래키 관계**
health_checkups.raw_id → health_checkup_raw.raw_id
**논리적 관계**
• health_checkups ↔ health_normal_ranges (정상치 비교)
• health_files ↔ health_checkups (파일-데이터 연결)
• User Service users ↔ health_checkups (사용자별 데이터)
**참조 무결성**
• raw_id는 NOT NULL (원본 데이터 필수)
• user_id는 User Service와 일관성 유지
• member_serial_number로 건보공단 데이터 연결
end note
}
package "데이터 타입 및 제약조건" as constraints {
note as n2
**health_checkups 제약조건**
• id: AUTO_INCREMENT
• user_id: 최대 50자, NOT NULL
• member_serial_number: User Service와 일치
• reference_year: 1990~현재년도
• bmi: 계산값, 10.0~50.0 범위
• blood pressure: systolic > diastolic
• risk_level: 'normal', 'caution', 'danger'
• health_score: 0~100 점수
• abnormal_indicators: JSON 배열 형태
**health_checkup_raw 제약조건**
• raw_id: AUTO_INCREMENT
• member_serial_number: NOT NULL
• reference_year: NOT NULL
• gender_code: 1(남성), 2(여성)
• age: 0~120 범위
• 모든 수치 데이터: 음수 불가
**health_normal_ranges 제약조건**
• 복합 기본키: (item_code, gender_code)
• gender_code: 0(공통), 1(남성), 2(여성)
• normal_min ≤ normal_max
• caution 범위는 normal 범위 밖
• danger 범위는 caution 범위 밖
**health_files 제약조건**
• file_id: UUID 형태
• file_type: 'pdf', 'jpg', 'png' 등
• file_size: 바이트 단위, 최대 10MB
• upload_status: 'uploading', 'completed', 'failed'
end note
}
package "정상치 기준 예시 데이터" as normal_ranges_data {
note as n3
**주요 항목별 정상치 기준 (성인 남성 기준)**
| item_code | normal_range | caution_range | danger_range |
|-----------|-------------|---------------|--------------|
| BMI | 18.5~24.9 | 25.0~29.9 또는 <18.5 | ≥30.0 |
| SYSTOLIC_BP | 90~119 | 120~139 | ≥140 |
| DIASTOLIC_BP | 60~79 | 80~89 | ≥90 |
| FASTING_GLUCOSE | 70~99 | 100~125 | ≥126 |
| TOTAL_CHOLESTEROL | <200 | 200~239 | ≥240 |
| HDL_CHOLESTEROL | ≥40 | 35~39 | <35 |
| LDL_CHOLESTEROL | <130 | 130~159 | ≥160 |
| TRIGLYCERIDE | <150 | 150~199 | ≥200 |
| AST | <40 | 40~80 | >80 |
| ALT | <40 | 40~80 | >80 |
| GAMMA_GTP | <60 | 60~100 | >100 |
| HEMOGLOBIN | 13.0~17.0 | 12.0~12.9 | <12.0 |
**성별 차이**
• 여성은 HDL 콜레스테롤 ≥50, 혈색소 12.0~15.0
• 임신 가능 연령대 여성은 별도 기준 적용
end note
}
package "성능 및 운영 고려사항" as performance {
note as n4
**인덱스 전략**
• health_checkups: (user_id, reference_year) 복합 인덱스
• health_checkup_raw: (member_serial_number, reference_year) 복합 인덱스
• health_normal_ranges: item_code 단일 인덱스
• health_files: (user_id, uploaded_at) 복합 인덱스
**파티셔닝**
• health_checkup_raw: reference_year 기준 연도별 파티셔닝
• health_files: uploaded_at 기준 월별 파티셔닝
**아카이빙**
• 5년 이상 된 raw 데이터는 별도 아카이브 테이블로 이관
• 업로드 실패 파일은 30일 후 자동 삭제
**캐싱 전략**
• health_normal_ranges: Redis에 전체 캐싱 (24시간)
• 사용자별 최신 건강검진: Redis 캐싱 (1시간)
• 건강 점수 계산 결과: Redis 캐싱 (6시간)
**모니터링 지표**
• 정상치 기준 업데이트 빈도
• 평균 건강 점수 추이
• 위험군 사용자 비율
• 파일 업로드 성공률
end note
}
package "데이터 보안 및 규정 준수" as security {
note as n5
**개인정보 보호**
• health_checkup_raw.name: 암호화 저장
• health_checkup_raw.birth_date: 마스킹 처리
• 의료 데이터 접근 시 감사 로그 기록
**의료정보 보안**
• 의료법 및 개인정보보호법 준수
• 건강검진 데이터 3년 보존 의무
• 개인식별정보와 건강정보 분리 저장
**접근 제어**
• 의료진만 정상치 기준 수정 가능
• 사용자 본인 데이터만 조회 가능
• 관리자 접근 시 의료진 승인 필요
**데이터 무결성**
• 건강검진 데이터 변조 방지
• 원본 데이터 불변성 보장
• 정상치 기준 변경 시 이력 관리
**백업 및 복구**
• 건강검진 데이터 일일 백업
• 정상치 기준 변경 전 백업
• 재해 복구 시 의료진 검증 필수
end note
}