MES를 1년쯤 돌린 라인에서 한 달치 비가동 기록을 뽑아 사유별 누적 시간으로 정렬해 보세요. "기타", "미분류", 또는 뭉뚱그린 설비 고장 코드 하나가 상위 3위 안에 있으면 코드 목록이 잘못된 겁니다. 작업자가 성의가 없는 게 아닙니다. 라인이 멈춰 있고 뒤에 사람이 서 있는 상황에서, 자기 상황에 맞는 항목이 없는 메뉴에서 가장 빨리 빠져나갈 길을 고른 것뿐입니다.
실패하는 비가동 프로젝트는 대부분 감지, 입력 시점, 목록 길이 이 셋 중 하나에서 무너집니다. 다들 하고 싶어 하는 분류 체계 논쟁은 잘해야 네 번째 문제입니다.
감지와 설명은 다른 일이다
제어 시스템은 충전기가 멈춘 것을 압니다. 하지만 디팔레타이저의 레인 잼 때문에 상류 컨베이어 두 대가 굶었다는 사실은 모르고, 앞으로도 모릅니다. 계층을 분리해서 다루세요.
| 계층 | 예 | 출처 |
|---|---|---|
| 설비 상태 | 가동, 정지, 블록, 대기(굶음), 고장 | PLC·SCADA 태그 |
| 비가동 이벤트 | 10:14:22 → 10:22:05 정지 | 시작·종료가 있는 시간 구간 레코드 |
| 사유 코드 | 품종 교체, 상류 자재 대기, 캡퍼 고장 | 자동 또는 작업자 분류 |
| 코멘트 | "디팔 레인 잼 이후 병 공급 끊김" | 예외 상황에만 쓰는 자유 입력 |
이벤트 경계가 틀리면 어떤 사유 코드로도 리포트를 고칠 수 없습니다. 가동 여부를 라인 속도 임계값이 아니라 모터 런 피드백에서 뽑아 정지 기록이 8초씩 늦게 잡히면, 그 교대조의 모든 지속 시간이 어긋납니다. 그리고 회의에서 OEE 숫자를 두고 싸우기 전까지 아무도 눈치채지 못합니다.
상태 모델이 이미 절반을 분류해 준다
포장 라인이라면 ISA-TR88.00.02(PackML)이 대부분의 사유 코드 목록이 버리는 구분을 이미 해 둡니다. Held는 내부 원인으로 멈췄고 작업자 조치가 필요한 상태, Suspended는 상류 자재 대기나 하류 블록 같은 외부 원인이며 흐름이 돌아오면 알아서 풀리는 상태입니다. 이 한 비트가 "우리 충전기가 부실하다"와 "디팔레타이저가 병목이다"를 가르는데, 상태 머신에서 공짜로 얻을 수 있습니다.
반도체 쪽이라면 SEMI E10의 6가지 기본 상태(Productive, Standby, Engineering, Scheduled Downtime, Unscheduled Downtime, Non-Scheduled)가 이미 트리의 상단을 나눠 놓았고, E79가 그 위에 OEE 지표를 정의합니다. 생산 부서와 관리 부서가 "이게 정지에 포함되냐"로 갈릴 때 근거로 들 정의가 필요하면 ISO 22400-2의 가용률과 MOM KPI 정의를 쓰면 됩니다.
이 상태들은 사유를 제안하는 데 쓰고 고정하는 데 쓰지 마세요. 기본값으로 채우되 작업자가 바꿀 수 있게 하고, 둘 중 무엇이 일어났는지 함께 저장합니다.
끝까지 고를 수 있을 만큼 짧게
처음 만든 코드 목록의 3분의 2는 끝내 쓰이지 않습니다. 저는 대분류 67개, 라인당 말단 코드 2540개를 기준으로 잡습니다. 말단을 세분화하는 건 그 구분이 실제 조치를 바꿀 때뿐입니다.
| 그룹 | 쓸 만한 말단 코드 | 망치는 방식 |
|---|---|---|
| 계획 정지 | 품종 교체, 세척, 예방 정비 | 계획·비계획 손실을 한 통에 담기 |
| 설비 고장 | 충전기 고장, 라벨러 고장, 컨베이어 드라이브 고장 | 라인 전체에 "설비 이상" 하나 |
| 자재 | 자재 없음, 자재 불량, 포장재 부족 | 사실 대신 부서 이름을 넣은 코드 |
| 흐름 | 상류 자재 대기, 하류 블록 | 흐름 문제를 설비 고장 안에 숨기기 |
| 품질 홀드 | 시험실 홀드, 검사 부적합, 재작업 | 품질 정지를 기계 정지에 섞기 |
| 유틸리티 | 압축공기, 스팀, 냉수, 정전 | 전사적 원인을 자유 입력으로만 남기기 |
1년에 두 번 쓰는 코드는 코드가 아닙니다. 코멘트이거나 설비 보전 시스템의 작업 지시 항목입니다. 작업자 화면에 남은 희귀 코드는 모든 선택에 스크롤을 한 번씩 더 붙입니다.
데이터 품질을 가르는 건 메뉴가 아니라 입력 시점이다
정지가 감지되는 순간 입력창을 띄우면 "기타"가 쌓입니다. 그때 작업자는 두 손으로 잼을 빼고 있습니다.
저는 대부분의 라인에서 프롬프트 임계값을 120초로 두고, 그보다 짧은 정지는 마이크로 스톱으로 묶어 설비 상태만으로 자동 분류합니다. 정지가 드물고 길게 나는 공정이면 60초도 괜찮지만, 그 아래로 내려가면 노이즈를 분류시키려고 사람을 붙잡는 셈입니다. 어떤 값을 쓰든 설비별로 설정 가능해야 합니다. 품종 교체가 잦은 라인과 연속 충전 라인이 생각하는 "긴 정지"는 다르니까요.
입력 화면의 나머지는 이렇게 잡습니다.
- 현재 상태와 진행 중인 정지 시간을 선택창 옆에 같이 띄운다. 무엇을 분류하는지 보이게.
- 알람 요약 위를 덮거나 복구 조작을 막는 모달은 쓰지 않는다.
- 자주 쓰는 사유를 위쪽에 두되 순서를 고정한다. 사용 빈도에 따른 자동 재정렬은 똑똑해 보이지만 손에 익은 위치를 매번 없앤다.
- 권한이 있는 사용자만 수정 가능하게 하고, 원래 값은 남긴다.
- 자동 판정인지, 작업자 입력인지, 관리자 수정인지 출처를 표시한다.
- 코멘트는 긴 이벤트나 특정 코드에만 필수로 두고, 모든 정지에 요구하지 않는다.
나중에 리포트가 요구할 필드
| 필드 | 이유 |
|---|---|
| 설비/라인 ID | ISA-95 설비 계층 기준 손실 집계 |
| 시작·종료 타임스탬프 | 지속 시간 검증, 교대조 배분 |
| 정지 시점의 감지 상태 | 제어 시스템이 실제로 본 것을 보존 |
| 사유 코드 ID + 표시 라벨 | 안정적인 키와 표시 문구를 분리 |
| 사유의 출처 | 자동, 작업자, 관리자, 외부 반입 |
| 제품·배치·오더 | 손실을 생산 맥락에 연결 |
| 사용자 및 수정 이력 | 책임 추궁 없이 검토 가능하게 |
| 코멘트 | 영구 코드로 만들 가치는 없는 세부 사항 |
여기서 흔히 두 가지를 틀립니다. 첫째, 코드는 안정적인 숫자나 문자열 ID를 쓰고 라벨만 바뀌게 해야 합니다. 안 그러면 "캡퍼 고장"을 "캡퍼 잼"으로 다듬는 순간 18개월치 추이가 깨집니다. 둘째, 이벤트는 통째로 저장하고 리포트 시점에 자릅니다. 06:00을 넘긴 정지를 저장할 때 두 레코드로 쪼개면 원래 이벤트를 복원할 수 없고, 이후 모든 쿼리가 인접한 두 레코드가 한 번의 정지인지 두 번인지 추측해야 합니다.
그리고 공백, "알 수 없음", "입력 불필요"는 서로 다른 값입니다. 셋을 빈 문자열로 뭉치면 답이 없는 것과 일부러 비운 것을 구분할 방법이 사라집니다.
목록은 첫 한 달에 설계된다
첫 달은 주간, 안정되면 월간으로 봅니다.
- 미분류 누적 시간 내림차순으로 정렬한다. 그게 작업 목록이다.
- 두 작업자가 다르게 쓰는 코드를 찾는다. 대개 한 조에는 같은 뜻이고 다른 조에는 다른 뜻인 코드 두 개다.
- 중복은 합친다. 나누는 건 그 구분이 의사결정을 바꿀 때만.
- 자동 판정 상태와 선택된 사유를 대조해 불일치를 본다.
마지막 대조는 분류 체계를 손대기 전에 먼저 해 볼 값어치가 있습니다. 상태 머신이 Suspended라고 하는데 작업자가 설비 고장을 고른 이벤트는 전부 감지 로직 버그이거나 교육 공백이고, 둘 다 범주 논쟁보다 고치는 비용이 쌉니다.