!theme mono skinparam classAttributeIconSize 0 skinparam classFontSize 12 skinparam classAttributeFontSize 11 title HealthSync 역설계 - User Service 데이터 설계서 package "User Service Database Schema" as user_db #lightgreen { entity "users" as user { * member_serial_number : BIGINT <> -- * google_id : VARCHAR(255) <> * name : VARCHAR(100) * birth_date : DATE * occupation : VARCHAR(50) <> * created_at : TIMESTAMP * updated_at : TIMESTAMP * last_login_at : TIMESTAMP -- + 인덱스: idx_google_id + 인덱스: idx_occupation + 인덱스: idx_created_at } entity "occupation_types" as occupation_type { * occupation_code : VARCHAR(20) <> -- * occupation_name : VARCHAR(100) * category : VARCHAR(50) * is_active : BOOLEAN * created_at : TIMESTAMP * updated_at : TIMESTAMP -- + 인덱스: idx_occupation_name + 인덱스: idx_category } note right of user **사용자 테이블 특징** • Google OAuth 기반 인증 • member_serial_number는 건강보험공단 데이터 연동 키 • occupation은 직업 코드 참조 • 소프트 삭제 미적용 (물리 삭제) end note note right of occupation_type **직업 유형 테이블 특징** • 표준 직업 분류 기반 • 카테고리별 그룹핑 • 활성/비활성 상태 관리 • 마스터 데이터 성격 end note } package "관계 정의" as relationships { user ||--o{ occupation_type : occupation note as n1 **외래키 관계** users.occupation → occupation_types.occupation_code **참조 무결성** • CASCADE 업데이트 • RESTRICT 삭제 (직업 유형 삭제 시 제한) **데이터 정합성** • occupation 필드는 NULL 허용 (프로필 미완성 상태) • birth_date는 NOT NULL (필수 정보) • google_id는 UNIQUE 제약 (중복 가입 방지) end note } package "데이터 타입 및 제약조건" as constraints { note as n2 **users 테이블 제약조건** • member_serial_number: AUTO_INCREMENT • google_id: UNIQUE, NOT NULL • name: NOT NULL, 최대 100자 • birth_date: NOT NULL, 1900-01-01 이후 • occupation: NULL 허용, 최대 50자 • created_at: DEFAULT CURRENT_TIMESTAMP • updated_at: ON UPDATE CURRENT_TIMESTAMP • last_login_at: NULL 허용 **occupation_types 테이블 제약조건** • occupation_code: PRIMARY KEY, 최대 20자 • occupation_name: UNIQUE, NOT NULL, 최대 100자 • category: NOT NULL, 최대 50자 • is_active: DEFAULT TRUE • created_at: DEFAULT CURRENT_TIMESTAMP • updated_at: ON UPDATE CURRENT_TIMESTAMP end note } package "초기 데이터" as initial_data { note as n3 **occupation_types 초기 데이터 예시** | occupation_code | occupation_name | category | |----------------|----------------|----------| | OFF001 | 사무직 | 사무관리 | | MFG001 | 제조업 생산직 | 제조생산 | | SVC001 | 서비스업 | 서비스 | | EDU001 | 교육직 | 전문직 | | MED001 | 의료진 | 전문직 | | IT001 | IT개발자 | 전문직 | | SAL001 | 영업직 | 영업마케팅 | | DRV001 | 운전직 | 운송 | | CON001 | 건설업 | 건설 | | FRE001 | 프리랜서 | 기타 | **카테고리 분류** • 사무관리: 앉아서 일하는 직종 • 제조생산: 신체 활동이 많은 직종 • 서비스: 고객 응대 직종 • 전문직: 전문 지식 요구 직종 • 영업마케팅: 외부 활동 직종 • 운송: 이동이 많은 직종 • 건설: 육체 노동 직종 • 기타: 분류하기 어려운 직종 end note } package "성능 및 운영 고려사항" as performance { note as n4 **인덱스 전략** • users.google_id: 로그인 시 빠른 조회 • users.occupation: 직업별 통계 조회 • users.created_at: 가입 일자별 조회 • occupation_types.occupation_name: 직업명 검색 **파티셔닝** • 현재 단계에서는 미적용 • 사용자 수 증가 시 created_at 기준 월별 파티셔닝 고려 **백업 및 복구** • users: 매일 풀백업 (개인정보 보호) • occupation_types: 주간 백업 (마스터 데이터) **모니터링 지표** • 신규 가입자 수 (일별/월별) • 활성 사용자 수 (last_login_at 기준) • 직업별 사용자 분포 • 평균 프로필 완성률 end note } package "데이터 보안" as security { note as n5 **개인정보 보호** • name: 암호화 저장 고려 (실명) • birth_date: 날짜 정보 마스킹 • google_id: 해시 처리 또는 암호화 **접근 제어** • 개인정보 조회 시 로그 기록 • 관리자 접근 시 승인 프로세스 • API 호출 시 사용자 본인 확인 **데이터 보존** • 회원 탈퇴 시 개인정보 즉시 삭제 • 로그인 기록 90일 보존 • 감사 로그 1년 보존 **GDPR/개인정보보호법 준수** • 데이터 처리 목적 명시 • 동의 철회 시 데이터 삭제 • 데이터 이동권 지원 end note }