PII 규정 준수 패턴은(는) 무엇을 하나요?
의료 애플리케이션에서 환자 데이터, 임상 데이터 및 재무 데이터를 보호하기 위한 패턴입니다. HIPAA(미국), DISHA(인도), GDPR(유럽) 및 일반적인 의료 데이터 보호 규정에 적용 가능합니다.
사용 시기
- 환자 기록을 다루는 모든 기능 구축 시
- 임상 시스템에 대한 접근 제어 또는 인증 구현 시
- 의료 데이터베이스 스키마 설계 시
- 환자 또는 임상 데이터를 반환하는 API 구축 시
- 감사 추적 또는 로깅 구현 시
- 데이터 노출 취약점에 대한 코드 검토 시
- 멀티 테넌트 의료 시스템을 위한 행 수준 보안(RLS) 설정 시
작동 방식
의료 데이터 보호는 분류(민감한 데이터 식별), 접근 제어(열람 권한 관리), 감사(열람 기록 추적)의 세 가지 계층으로 작동합니다.
데이터 분류
PHI(보호 대상 건강 정보) — 환자를 식별할 수 있고 건강과 관련된 모든 데이터: 환자 이름, 생년월일, 주소, 전화번호, 이메일, 국가 식별 번호(SSN, Aadhaar, NHS 번호), 의무 기록 번호, 진단명, 약물, 검사 결과, 영상, 보험 증권 및 청구 세부 정보, 진료 예약 및 입원 기록, 또는 이들의 모든 조합.
PII(환자 외 민감 데이터) 의료 시스템에서: 임상의/직원 개인 세부 정보, 의사 수가 구조 및 지급 금액, 직원 급여 및 은행 계좌 정보, 벤더 지급 정보.
접근 제어: 행 수준 보안
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;
}
일반적인 정보 누출 벡터
오류 메시지: 클라이언트에 전달되는 오류 메시지에 환자 식별 데이터를 절대 포함하지 마십시오. 세부 정보는 서버 측에만 기록하십시오.
콘솔 출력: 전체 환자 객체를 절대 로깅하지 마십시오. 의무 기록 번호, 국가 식별 번호 또는 이름 대신 불투명한 내부 레코드 ID(UUID)를 사용하십시오.
URL 파라미터: 쿼리 문자열이나 경로 세그먼트에 환자 식별 데이터를 절대 넣지 마십시오. 로그나 브라우저 기록에 나타날 수 있습니다. 불투명한 UUID만 사용하십시오.
브라우저 저장소: localStorage 또는 sessionStorage에 PHI를 절대 저장하지 마십시오. PHI는 메모리에만 유지하고 필요시 가져오십시오.
서비스 역할 키: 클라이언트 측 코드에서 service_role 키를 절대 사용하지 마십시오. 항상 anon/publishable 키를 사용하고 RLS가 접근을 제어하도록 하십시오.
로그 및 모니터링: 전체 환자 기록을 절대 로깅하지 마십시오. 불투명한 레코드 ID만 사용하십시오(의무 기록 번호가 아님). 오류 추적 서비스로 보내기 전에 스택 트레이스를 정리하십시오.
데이터베이스 스키마 태깅
스키마 수준에서 PHI/PII 열을 표시하십시오:
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 안전하지 않은 오류 처리
// 나쁨 — PHI 노출
throw new Error(`환자 ${patient.name}을(를) ${patient.facility}에서 찾을 수 없음`);
// 좋음 — 일반 오류, 세부 정보는 불투명 ID로 서버 측에 기록
logger.error('환자 조회 실패', { recordId: patient.id, facilityId });
throw new Error('기록을 찾을 수 없습니다');
예제 2: 다중 시설 격리를 위한 RLS 정책
-- 시설 A의 의사는 시설 B의 환자를 볼 수 없음
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()
));
-- 테스트: 의사-facility-a로 로그인하여 facility-b 환자 질의
-- 예상: 0행 반환
예제 3: 안전한 로깅
// 나쁨 — 식별 가능한 환자 데이터 로깅
console.log('환자 처리 중:', patient);
// 좋음 — 불투명한 내부 레코드 ID만 로깅
console.log('레코드 처리 중:', patient.id);
// 참고: patient.id도 의무 기록 번호가 아닌 불투명한 UUID여야 함