| name | healthcare-phi-compliance |
| description | 헬스케어 애플리케이션을 위한 PHI/PII 컴플라이언스 패턴입니다. 데이터 분류, 접근 제어, 감사 추적, 암호화, 흔한 유출 경로를 다룹니다. |
| origin | Health1 Super Speciality Hospitals — contributed by Dr. Keyur Patel |
| version | 1.0.0 |
Healthcare PHI/PII Compliance Patterns
헬스케어 애플리케이션에서 환자 데이터, 의료진 데이터, 금융 데이터를 보호하기 위한 패턴입니다. HIPAA(미국), DISHA(인도), GDPR(EU), 일반적인 의료 데이터 보호 전반에 적용됩니다.
사용 시점
- 환자 기록을 다루는 기능을 만들 때
- 임상 시스템의 접근 제어 또는 인증을 구현할 때
- 헬스케어 데이터베이스 스키마를 설계할 때
- 환자 또는 의료진 데이터를 반환하는 API를 만들 때
- 감사 추적이나 로깅을 구현할 때
- 데이터 노출 취약점 관점에서 코드를 리뷰할 때
- 멀티테넌트 헬스케어 시스템에 Row-Level Security를 설정할 때
동작 방식
헬스케어 데이터 보호는 세 층에서 동작합니다.
- classification: 무엇이 민감한가
- access control: 누가 볼 수 있는가
- audit: 누가 실제로 봤는가
데이터 분류
PHI (Protected Health Information) 는 환자를 식별할 수 있고 건강과 관련된 모든 데이터입니다. 환자 이름, 생년월일, 주소, 전화번호, 이메일, 주민/국가 식별번호, 의무기록번호, 진단, 약물, 검사 결과, 영상, 보험 정보, 예약 및 입원 기록 등이 포함됩니다.
PII (비환자 민감 데이터) 는 의료진/직원 개인정보, 의사 수수료와 정산 금액, 직원 급여와 계좌 정보, 벤더 지급 정보 등을 포함합니다.
접근 제어: Row-Level Security
ALTER TABLE patients ENABLE ROW LEVEL SECURITY;
CREATE POLICY "staff_read_own_facility"
ON patients FOR SELECT TO authenticated
USING (facility_id IN (
SELECT facility_id FROM staff_assignments
WHERE user_id = auth.uid() AND role IN ('doctor','nurse','lab_tech','admin')
));
CREATE POLICY "audit_insert_only" ON audit_log FOR INSERT
TO authenticated WITH CHECK (user_id = auth.uid());
CREATE POLICY "audit_no_modify" ON audit_log FOR UPDATE USING (false);
CREATE POLICY "audit_no_delete" ON audit_log FOR DELETE USING (false);
감사 추적
모든 PHI 접근과 수정은 로그로 남겨야 합니다.
interface AuditEntry {
timestamp: string;
user_id: string;
patient_id: string;
action: 'create' | 'read' | 'update' | 'delete' | 'print' | 'export';
resource_type: string;
resource_id: string;
changes?: { before: object; after: object };
ip_address: string;
session_id: string;
}
흔한 유출 경로
에러 메시지: 클라이언트에 환자 식별 데이터를 넣지 않습니다.
콘솔 출력: 전체 환자 객체를 로그로 남기지 않습니다. 이름이나 MRN 대신 불투명한 내부 ID를 사용합니다.
URL 파라미터: 로그나 브라우저 히스토리에 남을 수 있는 쿼리 문자열/경로 세그먼트에 PHI를 넣지 않습니다.
브라우저 저장소: PHI를 localStorage나 sessionStorage에 저장하지 않습니다. 메모리에만 두고 필요 시 가져옵니다.
서비스 role 키: 클라이언트 코드에서 service_role 키를 쓰지 않습니다. anon/publishable 키만 사용하고 RLS가 접근을 강제하게 둡니다.
로그 및 모니터링: 전체 환자 기록을 남기지 않습니다. 에러 추적 서비스로 보내기 전에 스택 트레이스를 정제합니다.
데이터베이스 스키마 태깅
COMMENT ON COLUMN patients.name IS 'PHI: patient_name';
COMMENT ON COLUMN patients.dob IS 'PHI: date_of_birth';
COMMENT ON COLUMN patients.aadhaar IS 'PHI: national_id';
COMMENT ON COLUMN doctor_payouts.amount IS 'PII: financial';
배포 체크리스트
배포 전:
- 에러 메시지나 스택 트레이스에 PHI 없음
console.log나 console.error에 PHI 없음
- URL 파라미터에 PHI 없음
- 브라우저 저장소에 PHI 없음
- 클라이언트 코드에 service_role 키 없음
- 모든 PHI/PII 테이블에 RLS 적용
- 모든 데이터 수정에 감사 추적 존재
- 세션 타임아웃 설정
- 모든 PHI 엔드포인트에 API 인증
- 시설 간 데이터 격리 검증
예시
예시 1: 안전한 에러 처리 vs 위험한 에러 처리
throw new Error(`Patient ${patient.name} not found in ${patient.facility}`);
logger.error('Patient lookup failed', { recordId: patient.id, facilityId });
throw new Error('Record not found');
예시 2: 멀티시설 격리를 위한 RLS 정책
CREATE POLICY "facility_isolation"
ON patients FOR SELECT TO authenticated
USING (facility_id IN (
SELECT facility_id FROM staff_assignments WHERE user_id = auth.uid()
));
예시 3: 안전한 로깅
console.log('Processing patient:', patient);
console.log('Processing record:', patient.id);