제3장: 사고·아차사고 보고 레코드와 워크플로

기관이 생물안전 사고와 아차사고를 WIA-BIO-017 IncidentReport 타입 위에서 구조화된 레코드로 접수·조사·종결·외부 보고하는 방법을 다룬다.

제2장은 천천히 바뀌는 레코드를 다루었다. 등록된 연구시설, 그 시설의 인증 블록, 시설에서 일할 수 있도록 승인된 사람, 그리고 그 승인을 유지시키는 교육 이수 기록이다. 이 장은 실험실의 한 달 중 가장 곤란한 날에 만들어지는 레코드로 넘어간다. 이 레코드는 대개 급하게, 그리고 보고가 자신에게 어떤 결과를 가져올지 걱정하는 사람의 손으로 작성된다. 이 레코드를 어떻게 설계하느냐에 따라 기관이 그 사건에서 무언가를 배우는지, 그리고 다음 점검자가 첫 전화부터 최종 서명까지의 경과를 따라갈 수 있는지가 갈린다.

WIA-BIO-017 명세는 이 장의 재료를 세 곳에서 제공한다. §7.1의 심각도 표와 대응 시간, §7.3의 조사 및 시정 조치 개요, §7.4의 문서화 항목 목록이다. TypeScript SDK는 여기에 네 가지 상태를 갖는 status 필드를 포함한 IncidentReport 인터페이스를 더한다. 이 장은 이 모든 것을 오로지 행정적 구조로만 다룬다. 유출이나 노출에 물리적으로 어떻게 대응하는지, 어떤 의료 절차가 뒤따르는지, 어떤 물질의 위해성을 어떻게 판단하는지는 설명하지 않는다. 그러한 질문은 기관의 생물안전관리책임자와 직업보건 부서, 그리고 국가 당국과 WHO가 발행하는 공식 지침의 영역이다.

3.1 아차사고 보고가 중요한 이유

3.1.1 사람들이 기꺼이 쓰는 레코드 체계

모든 사고 데이터베이스에는 두 종류의 사건이 있다. 데이터베이스에 도달한 사건과 도달하지 못한 사건이다. 두 번째 집단은 보이지 않으며, 대부분의 기관에서 그 규모가 더 크다. 근무 교대 중에 받쳐 열어 둔 출입문, 승인이 만료된 지 일주일이 지났는데도 그대로 계속된 작업, 물품이 이미 옮겨진 뒤에야 서명된 이송 서류 같은 것들이다. 이들 중 어느 것도 피해를 낳지 않았지만, 모두 관리체계가 조금씩 어긋나고 있다는 신호이다. 이런 일을 보고하는 것이 자백처럼 느껴진다면 아무도 보고하지 않는다.

안전과학 분야에서는 그 대안을 공정 문화(just culture)라고 부른다. 조직이 정직한 실수나 시스템이 유발한 오류는 학습의 기회로 다루고, 무모하거나 고의적인 위반은 통상의 책임 절차로 처리하는 방식으로 둘을 구분하는 것이다. 데이터 표준이 공정 문화를 만들어 낼 수는 없지만, 잘못 설계된 레코드는 그것을 무너뜨릴 수 있다. 사고 양식의 첫 필드가 “책임자는 누구인가?”를 묻거나, 모든 요약본에 보고자의 이름이 찍히거나, 사고가 열리는 순간 보고자의 출입 권한이 자동으로 정지된다면, 그 양식은 사람들에게 침묵을 가르친다.

따라서 비처벌적 레코드 설계는 몇 가지 구체적인 규칙을 따른다. 이 규칙들은 모두 이 장의 뒷부분에서 필드 수준의 결정으로 다시 나타난다.

3.1.2 선행지표로서의 보고율

부상 건수나 노출 건수는 후행 지표이다. 그 수치가 움직일 때는 이미 피해가 발생한 뒤이다. 반면 기간별 아차사고 보고 건수를 활동 연구자 수나 등록 시설 수로 나눈 값은 선행 지표이다. 인원이 안정된 조직에서 아차사고 보고율이 오른다면 대개 좋은 소식이다. 사람들이 보고 창구를 신뢰한다는 뜻이기 때문이다. 1년 내내 아차사고를 한 건도 보고하지 않은 부서가 실제로 아무 일도 없었던 부서인 경우는 드물다.

이는 데이터 모델에 직접적인 결과를 낳는다. 아차사고를 집계하고 추세를 보려면, 아차사고는 별도 스프레드시트의 자유 기술 메모가 아니라 사고와 동일한 식별자 체계·타임스탬프·종결 워크플로를 갖는 일급 레코드여야 한다. 이 책은 목표 보고율을 제시하지 않는다. 기준값은 기관이 선택할 문제이며, 기관생물안전위원회가 1년 정도의 자체 기준선 데이터를 확보한 뒤에 정하는 것이 바람직하다.

3.1.3 SDK 타입에서 “아차사고”의 자리

SDK의 IncidentReport.type 열거형은 spill, exposure, equipment-failure, breach, procedural-violation, other를 나열한다. near-miss 값은 없으며, 이는 올바른 선택이다. 아차사고는 사건의 종류가 아니라 결과이기 때문이다. 절차 위반은 아차사고(아무 일도 일어나지 않음)일 수도 있고 사고(무언가 일어남)일 수도 있다. 결과를 유형 필드에 넣으면 보고자는 둘 다 참인 설명 가운데 하나를 골라야 한다.

그래서 이 책의 프로파일은 선택 필드 eventClass 하나를 추가하고 값으로 incident와 near-miss를 둔다. 이는 PHASE-1 Annex E가 말하는 의미의 추가형(additive) 확장이다. 이 필드를 모르는 기존 소비자는 그냥 무시하며, 기존 필드의 이름은 바뀌지 않는다. 이 장 전체에서 SDK가 정의하지 않은 필드는 프로파일 확장으로 표시하여, 독자가 표준 자체와 이 책의 제안을 구분할 수 있게 한다.

3.2 IncidentReport의 행정 필드

다음 표는 api/typescript/src/types.ts에 정의된 IncidentReport의 필드와, 관리 레코드로 쓸 때 이 책이 권장하는 처리 방식을 함께 보여 준다. SDK에는 정의되어 있지만 이 책이 관리 레코드에서 제외하는 필드도 함께 적어, 어떤 필드도 말없이 빠지지 않게 했다.

필드SDK 타입의미이 책의 프로파일 규칙
incidentIdstring고유 식별자안정적이며 재사용 금지, INC- 접두어(제2장 2.6)
dateDate | string사건 발생 시각UTC 기준 ISO 8601, 아래 타임스탬프 설명 참조
locationstring발생 장소등록 시설 ID와 호실을 참조, 평면도 수준의 세부 정보 금지
severity1 | 2 | 3 | 4심각도통보 SLA를 결정(3.3.4)
type6개 값 열거형사건 종류그대로 유지, 결과는 eventClass에 기록
personnelstring[]관련자가명 인사 ID만 사용
agentBiologicalAgent관련 물질기관 내부 등록부 참조로 대체(3.2.3)
concentrationnumber?물질의 정량 정보관리 레코드에서 제외
descriptionstring경위 서술사실 위주, 비공개 정보 점검을 거친 자유 기술
immediateActionsstring[]즉시 조치행정 조치만 기록(통보, 폐쇄, 기록 확보 등)
medicalEvaluationMedicalEvaluation?임상 정보범위 밖, 직업보건 사례 ID 링크로 대체
rootCausestring?근본원인요약 문자열, 상세는 RCA 레코드(3.4)
correctiveActionsstring[]시정 조치요약, 항목마다 CAPA 레코드로 뒷받침
preventiveActionsstring[]?예방 조치요약, 항목마다 CAPA 레코드로 뒷받침
followUpRequiredboolean후속 조치 필요 여부종결 전 false여야 하며, 아니면 CAPA가 열려 있어야 함
status4개 값 열거형워크플로 상태상태 기계로 통제(3.3)
reportedBystring보고자인사 ID, 익명 창구의 공용 ID도 허용
reviewedBystring?검토자closed 전 필수

3.2.1 식별자, 시각, 장소

SDK는 date를 Date | string으로 정의한다. 코드에서는 편리하지만 교환 시에는 모호하다. 관리 레코드는 모든 타임스탬프를 UTC 오프셋이 명시된 ISO 8601 형식(2026-03-11T05:40:00Z)으로 직렬화하고, 현지 시각 변환은 화면 표시 단계에서만 해야 한다. 또한 date 하나만으로는 SLA를 추적할 수 없다. 사건이 발생한 시각, 발견된 시각, 보고된 시각은 몇 시간에서 며칠까지 차이가 날 수 있으며, 나중의 점검에서 발견되는 아차사고라면 특히 그렇다. 이 책의 프로파일은 discoveredAt과 reportedAt을 선택적 확장으로 추가하고, date는 SDK가 기대하는 대로 발생 시각으로 유지한다.

location에 대해 SDK는 임의의 문자열을 허용하며, 명세의 예시도 호실을 자유 기술로 적는다. 관리 레코드에서는 위치가 등록 시설로 연결되어야 한다. 즉 제2장의 facilityId에 기관 공간 대장의 호실 식별자를 더한다. 이렇게 하면 문장을 해석하지 않고도 시설별·밀폐 등급 라벨별로 사건을 집계할 수 있고, 흔한 유출 경로 하나도 막을 수 있다. 자유 기술 위치 필드가 결국 건물 배치를 설명하게 되고, 그 보고서가 나중에 협력 기관과 공유되는 경우이다.

3.2.2 가명 식별자로서의 사람

personnel, reportedBy, reviewedBy에는 기관이 발급한 인사 ID를 넣어야 하며, 이름·이메일 주소·사원증에 인쇄된 사번을 넣어서는 안 된다. ID와 사람의 대응 관계는 인사 또는 신원 관리 시스템에 두고, 알 필요가 있는 역할(대개 생물안전관리책임자와 지정된 조사 담당자)에게만 공개한다. 제5장에서 다루듯 레코드가 기관 밖으로 나갈 때에는 ID를 다시 교환 전용 가명으로 치환한다. 개인정보 법제 측면은 제6장에서 다룬다. 여기서는 처음부터 이름을 담지 않은 레코드가, 나중에 이름을 지워야 하는 레코드보다 공유하기가 훨씬 쉽다는 점만 짚어 둔다.

3.2.3 데이터 최소화 원칙 아래의 agent 필드

SDK는 agent: BiologicalAgent를 필수 필드로 두며, BiologicalAgent 타입은 관리 레코드의 범위를 벗어나는 물질 특성 정보를 담는다. 제2장 2.5에서 정한 데이터 최소화 규칙에 따라, 이 책의 프로파일은 내장 객체를 참조로 바꾼다. 기관 내부 등록부 ID인 materialRef(출입이나 절차 관련 사건 대부분처럼 물질이 관련되지 않았다면 null)와, 등록부에 이미 기록된 분류 라벨이다. 등록부 항목의 내용을 알아야 하는 사람은 자신의 접근 권한으로 그 참조를 따라간다.

SDK 타입은 여전히 agent를 요구하므로, 이 프로파일을 쓰는 배포 환경은 SDK 함수를 호출하는 경계에 어댑터를 두어야 한다. 관리 레코드를 최소한으로 유지하면서 타입 검사를 통과시키도록 SDK를 감싸는 방법은 제4장에서 보인다. 핵심 설계 원칙은 의존 방향이다. 사고 레코드는 등록부를 가리킬 뿐, 등록부의 내용을 자기 안에 복사하지 않는다.

3.2.4 의료 정보는 직업보건 부서에 둔다

SDK는 선택 객체 medicalEvaluation과 별도의 MedicalEvaluation 타입도 정의한다. 대부분의 법역에서 직원의 임상 정보는 안전 기록보다 엄격하게 다뤄야 하는 건강 정보이며, 그 주인은 생물안전 부서가 아니라 직업보건 부서이다. 따라서 이 책은 MedicalEvaluation을 범위 밖으로 둔다. 프로파일은 대신 occupationalHealthCaseRef를 추가한다. 직업보건 부서가 발급하는 불투명한 사례 ID로, 생물안전관리책임자는 이를 통해 사례가 존재하는지, 아직 열려 있는지만 알 수 있고 그 내용은 알 수 없다. 직업보건 시스템이 그런 참조를 발급하지 못한다면 필드를 비워 두고 연결은 수작업으로 관리한다. 임시방편으로 임상 내용을 사고 경위 서술에 붙여 넣어서는 안 된다.

3.2.5 두 가지 심각도 표현

SDK에는 심각도를 표현하는 방식이 두 가지 있다. IncidentReport.severity는 숫자(1 | 2 | 3 | 4)이고, 공개 타입 SeverityLevel은 문자열 열거형('minor' | 'moderate' | 'serious' | 'critical')이다. 명세 §7.1.1의 표도 1~4단계에 같은 네 이름을 쓴다. 레코드 시스템은 인터페이스가 요구하는 숫자를 저장하고, 대응 관계는 공용 상수 하나에 정의하여 화면과 보고서가 서로 다른 말을 하지 않게 해야 한다.

// 심각도 라벨의 단일 기준(이 책의 프로파일)
const SEVERITY_LABEL: Record<1 | 2 | 3 | 4, SeverityLevel> = {
  1: 'minor',
  2: 'moderate',
  3: 'serious',
  4: 'critical',
};

아차사고의 경우, 이 책은 심각도에 실제로 일어난 사건의 수준을 기록하고, 선택적으로 potentialSeverity 확장에 위원회가 판단한 “일어날 수 있었던” 수준을 기록할 것을 권한다. 두 숫자는 서로 다른 질문에 답한다. 앞의 것은 통보 의무를, 뒤의 것은 조사 우선순위를 정한다. 둘을 한 필드에 섞으면 통보가 불필요하게 늘어나고, 가장 교훈적인 아차사고가 평범한 건들 사이에 묻힌다.

3.3 사고 상태 기계

IncidentReport.status는 open, under-investigation, resolved, closed의 네 값을 갖는다. SDK는 값만 정의하고 값 사이를 오가는 규칙은 정의하지 않는다. 규칙이 없으면 상태 필드는 마지막 편집자가 입력한 값이 될 뿐이고, 점검자는 “closed”가 “조사와 검증을 마쳤다”는 뜻인지 “누군가 대시보드에서 보기 싫어졌다”는 뜻인지 알 수 없다. 이 절은 그 규칙을 이 책의 프로파일로 제안한다.

3.3.1 상태와 전이

            보고 접수
                |
                v
          +-----------+   조사 담당 지정        +---------------------+
          |   open    | ---------------------> | under-investigation |
          +-----------+                        +---------------------+
                |                                   |           ^
                | 분류 결과 조사 불요               | RCA·CAPA  | 새 사실 또는
                | (아차사고, 심각도 1만)            | 확정      | 검토 불합격
                v                                   v           |
          +-----------+   효과성 검증 완료       +-----------+  |
          |  closed   | <----------------------- | resolved  |--+
          +-----------+                          +-----------+
                |
                | 재개(생물안전관리책임자, 사유 필수)
                +------------------> under-investigation
이전 상태다음 상태수행 주체(역할 예시)사전 조건
(신규)open등록된 모든 인원 또는 익명 창구최소 필드 존재: date, location, type, description, severity
openunder-investigation생물안전관리책임자조사 담당 지정, 통보 SLA 충족·미충족 기록
openclosed생물안전관리책임자기관 정책이 분류 단계 종결을 허용하는 경우만(예: 심각도 1 아차사고), reviewedBy와 분류 메모 필수
under-investigationresolved지정된 조사 담당rootCause 기재, 담당자와 기한이 있는 CAPA 레코드 1건 이상
resolvedunder-investigation생물안전관리책임자 또는 IBC검토 결과 RCA나 CAPA가 불충분, 사유 기록
resolvedclosed생물안전관리책임자(정책상 필요 시 IBC 포함)모든 CAPA 완료 또는 공식 이관, 효과성 검토 기록, reviewedBy 기재, followUpRequired가 false
closedunder-investigation생물안전관리책임자재개 사유 필수, 원래의 종결 기록은 감사 추적에 남음

두 가지 전이는 의도적으로 뺐다. open에서 resolved로 곧바로 가는 경로는 없다. “resolved”는 원인을 찾고 조치를 정했다는 주장이며, 아무리 짧더라도 조사가 있어야 하기 때문이다. open으로 되돌아가는 경로도 없다. 한 번 담당자가 지정된 레코드는 다시 주인 없는 상태로 돌아가지 않는다. 표에 없는 전이는 서비스가 거부하고 지적 사항으로 기록한다.

3.3.2 직무 분리

표의 역할은 예시이며, 실제 역할은 기관이 정한다. 다만 한 가지 규칙은 어느 기관이든 지키는 것이 좋다. 레코드를 resolved로 옮긴 사람과 closed로 옮기는 사람은 달라야 한다. SDK는 이미 reportedBy와 reviewedBy를 나누고 있으며, 프로파일은 여기에 reviewedBy가 조사 담당과 달라야 한다는 조건을 더한다. 자격 있는 사람이 한 명뿐이라면 두 번째 서명은 IBC 위원장이나 외부 검토자가 할 수 있으며, 그 사실을 레코드에 남긴다.

3.3.3 이력을 고쳐 쓰지 않는 재개

재개는 정상적인 일이다. 효과가 있어 보였던 CAPA가 한 달 뒤 실패하기도 하고, 두 번째 사건이 첫 근본원인이 틀렸음을 드러내기도 한다. 규칙은 재개가 덧붙이는 것이지 덮어쓰는 것이 아니라는 점이다. 종결 결정, 그 검토자와 시각은 감사 추적에 그대로 남고(추가 전용 AuditEvent는 제5장에서 설명한다), 재개된 조사는 옛 RCA를 고치지 않고 새 버전의 RCA를 추가한다. 점검자는 기관이 판단을 바꾸었다는 사실과 그 이유를 볼 수 있어야 한다.

서비스는 작은 가드 함수로 전이 표를 강제할 수 있다. 다음 코드는 예시이며, 역할 이름과 transitionAllowed 도우미는 SDK가 아니라 이 책의 프로파일에 속한다.

type IncidentStatus = IncidentReport['status'];

const ALLOWED: Record<IncidentStatus, IncidentStatus[]> = {
  'open':                ['under-investigation', 'closed'],
  'under-investigation': ['resolved'],
  'resolved':            ['under-investigation', 'closed'],
  'closed':              ['under-investigation'],
};

function transitionAllowed(
  rec: IncidentReport,
  to: IncidentStatus,
  actorId: string,
  investigatorId?: string,
): { ok: boolean; reason?: string } {
  if (!ALLOWED[rec.status].includes(to)) {
    return { ok: false, reason: `illegal transition ${rec.status} -> ${to}` };
  }
  if (to === 'closed') {
    if (!rec.reviewedBy) return { ok: false, reason: 'reviewedBy required' };
    if (rec.reviewedBy === investigatorId) {
      return { ok: false, reason: 'reviewer must differ from investigator' };
    }
    if (rec.followUpRequired) return { ok: false, reason: 'follow-up still open' };
  }
  if (to === 'resolved' && !rec.rootCause) {
    return { ok: false, reason: 'rootCause required' };
  }
  return { ok: true };
}

3.3.4 심각도와 통보 SLA

명세 §7.1.1은 심각도 단계마다 대응 시간을 부여한다. 레코드 시스템에서는 이를 통보 서비스 수준으로 이해하는 것이 가장 적절하다. 즉 사건이 알려진 순간부터 지정된 대응자(보통 생물안전관리책임자나 당직 연락처)가 이를 확인할 때까지의 최대 간격이다. 레코드는 기한과 그 충족 여부를 저장할 뿐, 대응 행위 자체는 기술하지 않는다.

심각도라벨대응 시간(명세 §7.1.1)레코드 동작(이 책의 프로파일)
1경미(Minor)24시간통보를 대기열에 넣음, 일일 요약으로도 가능
2중등(Moderate)4시간생물안전관리책임자에게 직접 통보, 미확인 시 상향
3심각(Serious)1시간당직 연락처 호출, 시간 초과 시 대리인에게 자동 상향
4위급(Critical)즉시기관 비상 계획의 채널 사용, 레코드는 사후 작성

명세의 표에는 단계별 사건 예시도 들어 있다. 그러나 그 예시는 밀폐와 물질에 관한 세부 사항을 섞고 있어 이 책의 범위를 벗어나므로 여기서는 뺐다. 기관은 각자의 심각도 기준을 생물안전 규정에 적어 위원회의 승인을 받고, 레코드에서는 그 규정의 버전을 참조해야 한다. 여기서 두 가지 실무 지침이 나온다. 첫째, SLA 시계는 date가 아니라 discoveredAt에서 시작해야 한다. 사흘 뒤에 발견된 아차사고가 1시간 목표를 소급해 맞출 수는 없기 때문이다. 둘째, 4단계에서는 레코드가 결코 통보 채널이 아니다. 비상 계획이 가동되는 동안 웹 양식에 글을 입력하고 있어서는 안 된다. 레코드는 사후에 작성하고, 실제 통보 시각은 통화 기록에서 옮겨 적는다.

3.4 근본원인 분석과 CAPA 레코드

3.4.1 구조화된 필드 묶음으로서의 5-Whys

명세 §7.3.1은 5-Whys 기법을 권한다. 무엇이 일어났는지를 묻고, 이어서 “왜”를 거듭 물으며 직접 원인에서 기여 요인, 시스템 문제를 거쳐 근본원인에 이르는 방식이다. SDK는 그 결과를 선택 문자열 하나, rootCause에 저장한다. 문자열 하나는 요약으로는 충분하지만 추론의 사슬을 잃는다. 그런데 검토자가 분석이 충분히 깊었는지 판단하려면 바로 그 사슬이 필요하다.

이 책의 프로파일은 rootCause를 한 줄 결론으로 유지하고, 사고 ID로 연결된 별도의 RCA 레코드를 추가한다. 각 단계를 독립된 항목으로 저장하므로, 검토자는 사슬이 어디에서 멈추었는지 보고 이의를 제기할 수 있다.

{
  "rcaId": "RCA-2026-0042-v1",
  "incidentId": "INC-2026-0042",
  "method": "5-whys",
  "version": 1,
  "steps": [
    { "level": "what",         "text": "..." },
    { "level": "immediate",    "text": "..." },
    { "level": "contributing", "text": "..." },
    { "level": "systemic",     "text": "..." },
    { "level": "root",         "text": "..." }
  ],
  "analyst": "PER-2C91",
  "completedAt": "2026-03-13T02:10:00Z"
}

다섯 개의 level 값은 §7.3.1의 다섯 질문과 대응한다. method 필드는 스키마를 바꾸지 않고도 다른 기법(예: 특성요인도의 분류 항목)을 받아들일 여지를 남긴다. 조사가 재개되면 version: 2로 새 버전을 추가하며, 첫 버전은 절대 수정하지 않는다.

좋은 근본원인 진술은 기관이 바꿀 수 있는 조건을 가리킨다. 빠진 점검표 항목, 불명확한 인수인계, 승인된 과제와 맞지 않는 출입 규칙 같은 것들이다. “연구자가 SOP를 따르지 않았다”처럼 사람으로 끝나는 진술은 대개 “왜”를 한 번 덜 물었다는 뜻이다.

3.4.2 CAPA 단계

명세 §7.3.2는 시정 조치를 네 단계로 나눈다. SDK는 이를 correctiveActions와 preventiveActions라는 두 문자열 배열로 평평하게 만든다. 추적을 위해서는 조치마다 담당자, 기한, 상태가 필요하므로, 프로파일은 SDK 배열을 사람이 읽는 요약으로 유지하면서 조치별 CAPA 레코드를 추가한다.

단계(명세 §7.3.2)목적SDK 배열필수 CAPA 필드(프로파일)
즉시(Immediate)재발 차단correctiveActions담당자, 완료 시각
단기(Short-term)직접 원인 해소correctiveActions담당자, 기한, 상태
장기(Long-term)시스템 문제 해결correctiveActions담당자, 기한, 상태, 연결된 규정·SOP 버전
예방(Preventive)안전 문화 강화preventiveActions담당자, 기한, 상태, 적용 범위(부서 또는 기관)

기한은 기관이 정한다. 표준은 기한을 규정하지 않으며, 이 책도 제안하지 않는다. 레코드 시스템이 할 수 있는 일은 기한을 넘긴 항목을 드러내는 것이다. 기한이 지난 CAPA는 사고의 종결을 막고, 생물안전관리책임자의 대시보드에 나타난다. 장기 조치가 다른 부서(예: 시설관리 부서)의 소관이라면, 그 부서의 작업 티켓을 참조하여 CAPA를 이관할 수 있다. 그러면 조치가 끝난 척하지 않고도 사고를 종결할 수 있다.

3.4.3 효과성 검토

resolved와 closed의 차이는 효과성 검토, 즉 조치가 실제로 무언가를 바꾸었다는 증거이다. 전형적인 증거는 행정적인 것이다. 문서관리 시스템에 올라간 개정 점검표, 해당 집단의 갱신된 교육 이수 기록, 규칙이 이제 지켜지고 있음을 보여 주는 후속 출입 기록 검토 등이다. 프로파일은 검토를 짧은 레코드로 저장한다. 검토자 ID, 날짜, 증거 참조, 그리고 판정(effective, partially-effective, not-effective)이다. effective가 아닌 판정은 사고를 under-investigation으로 되돌리며, 그 역방향 전이가 존재하는 이유가 바로 이것이다.

3.5 §7.4 문서화 점검표와 그 공백

명세 §7.4는 사고 보고서가 “반드시 포함해야 할” 항목을 나열한다. 이 목록을 SDK 타입에 대응시켜 보면, 명세와 참조 구현이 어디서 어긋나고 관리 프로파일이 어디서 결정을 내려야 하는지가 드러난다.

§7.4 항목SDK 필드상태이 책의 프로파일 처리
일시와 장소date, location부분장소가 자유 기술이므로 시설 ID와 호실 추가, discoveredAt·reportedAt 추가
관련 인원personnel충족가명 ID
관련 생물학적 물질agent충족하나 과도하게 상세내부 등록부를 가리키는 materialRef로 대체
사건 유형type충족아차사고용 eventClass 추가
심각도 분류severity충족공용 라벨 대응표, 선택적 potentialSeverity
즉시 조치immediateActions충족행정적 표현만 사용
의료 평가 요약medicalEvaluation범위 밖occupationalHealthCaseRef만 기록
근본원인 분석rootCause부분단계와 버전을 갖는 RCA 레코드 연결
시정·예방 조치correctiveActions, preventiveActions부분담당자·기한·상태를 갖는 CAPA 레코드 연결
후속 계획followUpRequired부분(불리언뿐)열린 CAPA 항목으로 계획을 표현
교훈없음누락lessonsLearned 추가(짧고 공유 가능한 문장)

세 가지 공백이 두드러진다. 교훈(lessons learned)에는 필드가 아예 없다. 부서 간에 가장 공유할 가치가 있는 부분인데도 그렇다. 프로파일은 lessonsLearned를 추가한다. 일반 독자를 대상으로 쓴 짧은 문장이며, 기관 내부에 게시하기 전에 비공개 정보가 없는지 검토하고, 이후 익명 공유에도 쓸 수 있게 한다(제6장에서 WIA-SOCIAL의 역할로 다룬다). 장소의 세분도는 자유 기술에 맡겨져 있어 집계가 불안정하다. 후속 계획은 불리언 하나로 축소되어, 검토자에게 무엇이 남았는지 알려 주지 못한다.

반대 방향으로, SDK에는 점검표가 요구하지 않는 필드가 하나 있다. concentration이다. “사고 보고서”라는 이름의 타입에 이 필드가 있으면, 보고자는 많은 사람이 읽는 레코드에 물질의 정량 정보를 입력하게 된다. 이 책의 프로파일은 이 필드를 제외한다. 이 발견 사항들은 제8장의 표준 1.1판 개정 제안 목록에도 함께 정리한다.

3.6 외부 규제 보고로의 인계

어떤 사고는 기관 밖으로 보고해야 한다. 기관생물안전위원회에 보고해야 하고, 경우에 따라서는 국가 당국에도 보고해야 한다. 한국에서 유전자변형생물체를 다루는 연구는 유전자변형생물체법(LMO법)의 적용을 받으며, 기관은 기관생물안전위원회를 운영하고 생물안전관리책임자를 지정한다. 어떤 사건을 누구에게 언제까지 보고해야 하는지는 법령과 시행규칙, 소관 당국이 정하며 시간이 지나면서 바뀐다. 이 책은 그 내용을 옮겨 적지 않는다. 독자는 현행 요건을 질병관리청(KDCA), 과학기술정보통신부, 국가 바이오안전성정보센터, 그리고 소속 기관의 IBC를 통해 확인해야 한다. 다른 나라의 기관은 각국의 규정을 따른다. WHO 실험실 생물안전 매뉴얼과 미국의 NIH Guidelines는 기관 위원회의 역할을 일반적인 수준에서 설명한다.

데이터 표준이 제공할 수 있는 것은 깔끔한 인계이다. 프로파일은 각각의 외부 통보를 상태값이나 자유 기술 메모가 아니라, 사고에 연결된 별도의 NotificationRecord로 모델링한다.

필드의미
notificationId안정적인 ID, 예를 들어 NTF- 접두어
incidentId보고 대상 사고
recipient수신자 범주(ibc, national-authority, funder, other)와 자유 기술 명칭
basis통보를 필요하게 만든 근거. 생물안전관리책임자가 기관 규정 조항이나 법령 조문을 참조로 입력
dueAt적용 규정에 따라 생물안전관리책임자가 정한 기한
sentAt, channel발송 시각과 수단(포털, 공문, 이메일)
externalRef수신자가 발급한 접수 번호나 사건 번호(있는 경우)
payloadRef실제로 보낸 문서에 대한 참조, 문서관리 시스템에 보관

핵심 설계 선택은 basis와 dueAt을 소프트웨어가 계산하지 않고 사람이 입력한다는 점이다. 국가 보고 필요 여부를 판정하는 규칙 엔진을 만들려면, 이 책이 검증할 수 없고 소프트웨어가 갱신되지 않은 채로도 바뀔 수 있는 법적 기준을 코드에 넣어야 한다. 소프트웨어의 역할은 더 좁고 더 믿을 만하다. 생물안전관리책임자가 통보가 필요하다고 판단한 뒤에는 그것이 잊히지 않게 하고, 기한이 보이게 하며, 실제로 보낸 내용을 보존하는 것이다. dueAt이 지났는데 발송되지 않은 통보가 있는 사고는 대시보드의 최우선 지적 사항이 되고 종결이 차단된다.

3.7 작성 예시: 민감 정보를 제거한 아차사고 레코드

명세 §9.3.1의 사고 예시에는 이 책의 범위를 벗어나는 물질·노출 관련 세부 사항이 들어 있다. 아래 예시는 같은 구조를 유지하되, 물질이 관련되지 않은 절차상 아차사고를 기술한다. 모든 식별자는 가상의 것이다. 본문에서 프로파일 확장으로 표시한 필드는 한데 묶어, 엄격한 SDK 소비자가 쉽게 구분할 수 있게 했다.

상황은 다음과 같다. 저녁 근무 교대 시간에 등록 실험실에 도착한 연구자가, 자동 닫힘 기능이 있는 출입 통제 문이 카트에 걸려 열려 있는 것을 발견한다. 실내에서 진행 중인 작업은 없고, 출입 기록상 무단 출입도 없다. 연구자는 문을 닫고 사고 양식으로 보고한다.

{
  "incidentId": "INC-2026-0042",
  "date": "2026-03-11T09:15:00Z",
  "location": "FAC-EXAMPLE-0007 / ROOM-214",
  "severity": 1,
  "type": "procedural-violation",
  "personnel": ["PER-7F3A"],
  "description": "교대 시간에 등록 실험실의 출입 통제 문이 카트에 걸려 열린 상태로 발견됨. 진행 중인 작업 없음. 출입 기록상 무단 출입 없음. 보고자가 문을 닫음.",
  "immediateActions": [
    "문을 닫고 카트를 치움",
    "생물안전관리책임자에게 전화로 통보",
    "직전 2시간의 출입 기록을 내보내 첨부"
  ],
  "rootCause": "교대 인수인계 점검표에 문 닫힘 확인 항목이 없었고, 입구 근처에 카트 보관 구역이 정해져 있지 않았음.",
  "correctiveActions": [
    "인수인계 점검표에 문 닫힘 확인 항목 추가 (CAPA-2026-0042-01)",
    "입구에서 떨어진 곳에 카트 보관 구역 표시 (CAPA-2026-0042-02)"
  ],
  "preventiveActions": [
    "부서 안전 회의에서 교훈 공유 (CAPA-2026-0042-03)"
  ],
  "followUpRequired": false,
  "status": "closed",
  "reportedBy": "PER-7F3A",
  "reviewedBy": "PER-0B44",

  "x-profile": {
    "eventClass": "near-miss",
    "potentialSeverity": 2,
    "discoveredAt": "2026-03-11T09:15:00Z",
    "reportedAt": "2026-03-11T09:32:00Z",
    "materialRef": null,
    "occupationalHealthCaseRef": null,
    "rcaRef": "RCA-2026-0042-v1",
    "capaRefs": ["CAPA-2026-0042-01", "CAPA-2026-0042-02", "CAPA-2026-0042-03"],
    "effectivenessReview": {
      "reviewer": "PER-0B44",
      "reviewedAt": "2026-04-15T01:00:00Z",
      "evidence": ["DOC-SOP-HANDOVER-v4", "ACCESS-LOG-REVIEW-2026-04"],
      "verdict": "effective"
    },
    "lessonsLearned": "닫혀 있어야 하는 문은 문에 붙인 안내문만이 아니라, 모든 인수인계에 이름이 붙은 확인 단계가 있어야 한다.",
    "notifications": []
  }
}

이 예시에서 몇 가지 설계 선택이 드러난다. agent 필드는 없고 materialRef는 null이다. 다루던 물질이 없었기 때문이다. 3.2.3에서 말했듯, 엄격한 SDK 소비자가 이를 받아들이려면 어댑터가 필요하다. 보고자와 관련자가 같은 가명 ID인데, 스스로 보고한 아차사고에서는 흔한 일이며 두 필드가 서로 독립적이어야 하는 이유를 보여 준다. 검토자는 보고자와 다르다. 경위 서술은 출입 기록과 대조할 수 있는 사실만 담고 그 이상은 적지 않는다. 빈 notifications 배열은 질문을 비워 둔 것이 아니라 하나의 결정(기관 규정상 외부 통보가 필요하지 않았음)을 기록한 것이다. 그렇게 결정한 생물안전관리책임자는 요청이 있으면 해당 규정 조항을 제시할 수 있어야 한다.

이 예시에서는 SDK와 이 책의 제안 사이의 경계를 분명히 보이려고 확장 필드를 하나의 x-profile 키 아래에 모았다. 실제 운영에서는 이를 최상위에 두는 편을 택할 수도 있다. 두 방식 모두 추가형이어서 기존 소비자를 깨뜨리지 않으며, 어느 쪽을 택했는지는 배포의 프로파일 매니페스트(제7장)에 문서화하면 된다.

3.8 구현 점검표

사고 모듈을 가동하기 전에 다음 질문들에 대한 답을 문서로 남겨 두는 것이 좋다. 가능하면 기관의 생물안전 규정이나 시스템 구성 기록에 적는다.

  1. 보고자 외의 누구도 지명하지 않고 아차사고를 보고할 수 있는가? 익명 보고도 가능한가?
  2. 발생·발견·보고 시각을 각각 UTC로 따로 저장하는가?
  3. 모든 장소가 등록 시설과 호실로 연결되는가?
  4. agent의 내용을 등록부 참조로 대체했고, concentration을 비활성화했는가?
  5. 임상 정보를 배제하고, 많아야 직업보건 사례 참조만 두는가?
  6. 승인된 표에 없는 상태 전이를 서비스가 거부하고, 거부할 때마다 기록하는가?
  7. 사고를 종결하는 검토자가 항상 조사 담당과 다른가?
  8. 열린 CAPA 항목과 미발송 통보가 종결을 차단하는가?
  9. 기관의 심각도 기준이 문서로 작성되어 있고, 버전으로 참조되는가?
  10. 생물안전관리책임자가 현행 국가 보고 요건을 소관 당국을 통해 확인했는가?

핵심 요점

기술적 안전 내용은 공식 생물안전 당국에 문의할 것. 이 장은 사고 레코드와 워크플로만 다룬다. 유출·노출 및 그 밖의 사건에 어떻게 대응하는지, 어떤 의료적 후속 조치가 적절한지는 기관의 생물안전관리책임자와 직업보건 부서, 그리고 질병관리청(KDCA)과 국가 생물안전 당국, WHO 실험실 생물안전 매뉴얼, BMBL 등 공식 지침에서 확인해야 한다.

복습 문제

  1. SDK의 type 열거형에 near-miss 값이 필요하지 않은 이유는 무엇이며, 프로파일은 결과를 어떻게 기록하는가?
  2. 프로파일이 구분하는 세 가지 타임스탬프는 무엇이며, 그중 통보 SLA 시계를 시작하는 것은 어느 것인가?
  3. open에서 resolved로 곧바로 가는 전이가 없는 이유를 설명하라.
  4. §7.4 점검표 가운데 SDK 타입이 완전히 지원하지 못하는 항목 두 가지를 들고, 각각에 대한 프로파일의 해법을 설명하라.