야간 근무자가 이송 펌프 기동 버튼이 회색이라며 당직 엔지니어에게 전화한다. 20분 뒤에 원인이 나온다. 하류 탱크가 고수위 퍼미시브에 걸려 있었다. 그 정보는 처음부터 PLC 안에 있었다. 운전원이 보고 있던 화면까지 올라오지 않았을 뿐이다.
실패한 건 그 전화다. 인터록은 제 역할을 했다. 화면이 못 한 것이다.
활성 비트 하나에 다섯 가지 질문이 숨는다
대부분의 페이스플레이트는 ButtonEnabled 같은 식 하나로 끝난다. 서로 독립적인 다섯 가지 판단이 불리언 하나로 뭉개진다.
- 권한 — 지금 로그인한 사용자가 이 조작을 할 수 있는가.
- 모드 — 설비가 원격, 자동, 수동, 정비, 로컬 중 어디에 있는가.
- 퍼미시브 — 현재 공정 조건이 이 조작을 허용하는가.
- 인터록 — 보호 조건이 지금 막고 있는가.
- 품질 — HMI가 관련 태그를 실제로 읽고 쓸 수 있는가.
템플릿상 최종 비트가 필요하면 그대로 두면 된다. 다만 다섯 개 입력을 같이 들고 올라와야 한다. 운전원의 질문은 "눌리는가"가 아니라 "다섯 중 무엇이 막고 있는가"이기 때문이다.
가장 싼 방법은 명령마다 정수 하나를 더 쓰는 것이다. PLC에서 판정한, 어떤 조건이 먼저 걸렸는지를 담은 사유 코드. 이 글의 나머지는 전부 그 결정에서 파생된다.
보임, 활성, 확인, 거부는 서로 다른 장치다
흔한 착각은 "숨김"을 "보안"으로 보는 것이다. 버튼을 숨기면 화면은 단순해진다. 막히는 건 없다. 스크립트 클라이언트, OPC UA 세션, 엔지니어링 워크스테이션은 버튼이 그려지든 말든 같은 태그를 쓴다. IEC 62443-3-3 SR 2.1은 권한 강제를 시스템의 책임으로 두지, 도면의 책임으로 두지 않는다.
| 판단 | 무엇이 결정하는가 | 잘못 쓰면 |
|---|---|---|
| 보임 | 설비 옵션 유무, 객체 종류, 화면 역할 | 그 기능이 있는지조차 모른다 |
| 활성 | 공정 상태, 퍼미시브, 태그 품질 | 눌러도 계속 거부되는 버튼이 된다 |
| 확인 창 | 영향이 큰 조작, 트립 후 재기동, 이상 상태 | 일상 조작이 느려지거나 위험 조작이 너무 쉬워진다 |
| PLC 거부 | 모드, 인터록, 명령 출처 — 최종 판단 | HMI 설정 실수로 보호 로직이 우회된다 |
드레인 밸브가 괜찮은 예다. 모든 운전원에게 보이되, 수동 모드이고 하류 여유가 있을 때만 활성화하고, 라인에 제품이 남아 있으면 확인을 받고, 명령 출처가 로컬이면 PLC가 아예 거부한다. 네 개 층, 네 개 사유. 그중 안전 계층은 마지막 하나뿐이다.
비활성 문구는 현장 용어로 쓴다
운전원이 버튼 색을 이해하려고 워치 테이블을 열게 하면 안 된다. 지금 막고 있는 첫 번째 사유를 버튼 아래 상태 줄이나 페이스플레이트 상단에 띄운다.
비활성: 펌프가 로컬 모드입니다비활성: 토출 밸브가 열리지 않았습니다비활성: MCC-3에서 트립 리셋 필요비활성: 현재 권한으로 레시피 변경 불가비활성: PLC 통신 품질 불량
실제로 납품되는 문구와 비교해 보면 된다. 사용 불가, 잘못된 상태, 권한 없음. 이 세 줄이 새벽 두 시 전화의 원인이다. 로직은 어느 조건이 걸렸는지 이미 알고 있다. 그걸로 활성 비트를 계산했으니까. 화면에 닿기 전에 그 정보를 버리는 건 설계자의 선택이다.
여러 조건이 동시에 걸렸으면 운전원이 조치할 수 있는 것부터 보여준다. "토출 밸브 미개방"이 "보조 태그 통신 저하"보다 먼저다. 둘 다 사실이어도 한쪽에는 다음 동작이 있고 다른 쪽에는 전화기밖에 없다.
역할 이름은 바뀌고 조작 단위는 남는다
어떤 현장은 Operator, Lead, Maintenance, Engineer를 쓴다. 다음 현장은 반장, 설비 담당, 공정 엔지니어, 협력사 계정을 쓴다. 역할 이름은 그 현장의 말버릇이고 다음 조직 개편을 못 넘긴다. 권한은 조작 단위로 문서화하고 역할을 거기에 매핑한다.
| 조작 | 일반적인 권한 | 추가 조건 |
|---|---|---|
| 설비 기동/정지 | 운전원, 반장 | 원격 모드, 퍼미시브 정상 |
| 알람 리셋 | 운전원, 반장 | HMI 리셋 허용 알람 |
| 수동 오버라이드 | 정비, 엔지니어 | 정비 모드, 사유 기록 |
| 레시피 파라미터 변경 | 반장, 엔지니어 | 레시피 잠금 해제, 범위 제한 |
| 시험용 인터록 바이패스 | 엔지니어 | 허용되더라도 시간 제한과 기록 필수 |
마지막 줄에는 분명한 의견이 있다. 만료 없는 인터록 바이패스는 영구 바이패스다. 시운전 때 걸어 둔 게 3년 뒤에도 그대로 있다. 화면이 그 사실을 다시 말해 준 적이 없기 때문이다. 타이머와 전체 화면의 바이패스 표시를 같이 만들든지, 아니면 만들지 말든지 둘 중 하나다.
시운전 때 실제로 걸어 봐야 하는 경우
태그 시뮬레이션으로 통과한 로직을 실제 설비가 떨어뜨린다. 상태를 강제로 만들어서 확인한다.
- 권한, 모드, 퍼미시브가 모두 정상 — 버튼이 활성화되고 설비가 실제로 움직인다.
- 권한은 맞고 모드가 틀림 — 비활성이고, 모드 사유가 뜬다.
- 권한 없음 — 화면 기준대로 숨김 또는 비활성이고, 클라이언트 툴로 강제 쓰기를 해도 거부된다.
- 네트워크 케이블을 뽑는다 — 캐시된 값으로 버튼이 활성 상태로 남아 있으면 안 된다.
- 인터록이 걸린 상태에서 HMI 식을 일부러 틀리게 둔다 — 그래도 PLC가 막는다.
- 페이스플레이트를 열어 둔 채 역할을 바꾼다 — 로그아웃 없이 활성 상태가 갱신된다.
건너뛰기 쉬운 건 4번이고, 나중에 무는 것도 4번이다. 품질이 나쁜 캐시 퍼미시브는 정상 true와 화면상 구분이 안 된다. 저하 운전용으로 명시 설계한 명령이 아니라면, 필요한 태그의 품질 불량은 비활성 조건으로 본다. 저하 운전용으로 설계했다면 그 사실을 화면에 써 둔다.
6번은 예전 두꺼운 클라이언트보다 웹 HMI에서 더 중요하다. 같은 페이스플레이트를 브라우저 두 개로 열고 한쪽에서 역할을 바꿔 본다. A 세션 로그아웃 후에도 B 세션이 엔지니어 권한을 들고 있으면 그건 표시 버그가 아니다.
이런 설계가 썩는 지점
HMI와 PLC의 퍼미시브 로직이 다르다. 화면은 된다고 하는데 PLC가 거부한다. 구조적으로는 맞다 — PLC가 최종 판단을 해야 한다. 하지만 주 단위로 반복되면 운전원은 화면을 안 믿고 되는 버튼을 찾을 때까지 누른다. PLC 거부 코드를 올려서 양쪽 이야기를 맞춘다.
권한 상승에 기록이 없다. 관리자가 로그인해서 뭔가를 열어 놓고 자리를 뜬다. 다음 운전원이 그대로 물려받는다. IEC 62443-3-3이 세션 잠금(SR 2.5)과 원격 세션 종료(SR 2.6)를 따로 요구하는 이유가 이것이다. 운전 스테이션의 비활동 타임아웃과, 명령이 나갈 때 누가 어떤 역할을 들고 있었는지에 대한 기록.
사유 코드 번호를 다시 매긴다. 그 코드는 로그와 지원 통화와 누군가의 엑셀에 남는다. 개정을 넘겨도 값은 고정하고, 번역은 표시 시점에 한다.
페이스플레이트에 올려 둘 필드
명령 단위로, 이름을 붙여서, 구조체로 넘긴다.
CanStartCannotStartReasonCodeCommandSourceAllowedOperatorRoleLevelPermissiveSummaryOkInterlockActiveWriteQualityGood
명령 경로가 OPC UA라면 서비스 결과도 버리지 않는다. 쓰기에서 돌아온 Bad_UserAccessDenied는 서버가 거부했다는 뜻이고, 이건 퍼미시브가 성립하지 않은 것과 완전히 다른 문제다. 둘 다 로그에 남긴다.
기준은 질문 하나면 된다. 운전원이 회색 버튼을 가리키며 왜냐고 묻는다. 답하는 데 엔지니어가 필요하면 설계가 아직 안 끝난 것이다.