303 lines
9.9 KiB
Plaintext
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
|
|
} |