한 줄로 끝낼 수 없는 흐름 — 활동·부적합·원인·조치를 분리한 이유
엑셀 한 줄에 발견·원인·조치·결과를 다 넣으면, 어디서 막혔는지 추적이 안 됩니다. 한 줄을 4단계 엔티티로 쪼개고, NC 상태를 자식 EXE 로부터 자동 계산하게 한 이유.
2026년 7월 5일 · 정윤환 · 5분
회사들이 안전점검을 합니다. 점검표가 돌아옵니다. 부적합 사항이 나옵니다. 엑셀에 기록됩니다. 한 행에 이렇게 적혀 있습니다.
3층 화학물질 보관실 환기 부족 — 환기팬 추가 설치 예정 (담당: 김OO, 기한: 3월 말)
깔끔합니다. 그런데 한 달 뒤에 이런 일이 벌어집니다.
- 환기팬 설치는 됐는데, 진짜 원인은 흄후드 동선이었습니다.
- 김 과장이 환기팬을 달았다고 보고했는데, 한 달 뒤 다시 보니 흄 농도가 그대로입니다.
- 같은 부적합이 두 달 뒤 다른 층에서 똑같이 발생합니다.
엑셀의 한 줄에는 너무 많은 게 압축돼 있었습니다. 발견·원인·조치·결과가 한 칸에 다 들어가니, 어디가 막혔는지 추적이 안 됩니다.
01 · Four entities
그래서 우리는 한 줄을 4단계로 쪼갰습니다
부적합 1건이 진짜로 닫히려면, 보이지 않는 사슬이 깁니다.
- Activity— 점검·감사 1회. “6월 정기 안전점검”, “협력사 합동점검” 같은 컨테이너.
- NonConformity (NC) — 그 안에서 발견된 부적합 1건.
- RootCause (RCA) — 그 부적합의 근본원인 분석. 5Why · 어골도로 풀면 보통 여러 개가 나옵니다.
- Execution (EXE) — 그 원인을 끝맺을 조치 1건. 담당자 · 기한 · 결과가 붙습니다.
각 단계를 컬럼이 아닌 엔티티로 둔 이유는 단순합니다. 컬럼이면 담당자 한 명, 기한 하나, 결과 하나만 표현됩니다. 엔티티면 “같은 부적합에 원인이 셋, 각 원인마다 조치가 둘씩” 같은 현실의 카디널리티가 그대로 들어옵니다.
02 · Why Activity
Activity 를 왜 또 따로 뒀나
NC 하나에도 사업장·부서·날짜·출처 같은 컨텍스트가 다 붙는데, 같은 점검에서 발견된 NC 들은 거의 다 같은 컨텍스트를 공유합니다. 그래서 그 공유분을 Activity 라는 상위 컨테이너로 끌어올렸습니다. 점검 한 번에 NC 12건이 나와도, 사업장·부서·출처는 활동에 한 번만 입력하고 자식 NC 에 cascade denormalize 됩니다. 입력 부담이 줄어듭니다.
화면도 이 카디널리티대로 갈라집니다. 같은 데이터를 활동 기준 / 부적합 기준 / 출처 기준 / 조치내용 기준4개의 뷰로 보여주는데, 어디에 서 있는지에 따라 보고 싶은 단위가 달라지기 때문입니다. 안전팀장은 “이번 달 활동 몇 건이었지?”, 담당자는 “내 조치 몇 개 남았지?”, 임원은 “출처별 부적합 분포가 어떻지?” — 같은 자료를 다른 축으로 자릅니다.
03 · XOR source
부적합 출처를 catalog 와 free text 둘 다 허용한 이유
처음엔 모든 출처를 조직별 카탈로그(org_non_conformity_source)에서 고르게 만들려고 했습니다. 그런데 운영해 보니 카탈로그에 없는 출처가 늘 생깁니다. “외부 감사관 지적”, “동료 제보”, “공장 시찰 중 사장이 직접 발견”. 그래서 non_conformity_source_id 와 non_conformity_source_text 를 XOR 로 두었습니다. 카탈로그를 강제하면 운영이 막히고, 자유 입력만 두면 통계가 깨집니다. 둘 다 두되 둘 중 하나만 채워지게 — 운영의 현실과 통계의 일관성을 동시에 잡는 선택이었습니다.
04 · Derived state
‘끝맺기’는 NC 가 직접 적지 않습니다
NC 의 상태(OPEN / IN_PROGRESS / AWAITING_VERIFICATION / VERIFIED / REWORK / CLOSED / CANCELLED)는 사람이 손으로 바꾸지 않습니다. 자식 EXE 들로부터 자동으로 derive 됩니다. EXE 가 하나도 없으면 OPEN, 미완료 EXE 가 하나라도 있으면 IN_PROGRESS, 모두 완료 + 효과성 미평가면 AWAITING_VERIFICATION… 이렇게요. 그리고 변할 때마다 ActionStatusHistory 에 한 줄씩 append 됩니다. 누가 언제 어떤 상태로 옮겼는지 사후에 다 추적됩니다.
CLOSED / CANCELLED 만 사람이 명시합니다. 자동 계산보다 우선합니다 — 비즈니스 종결은 시스템이 판단할 수 없는 영역이라.
Next
다음 편 — 이 4단계 트리를 화면에 어떻게 그렸는지 — 왜 표가 아니라 캔버스를 골랐는지.