
HMI 없어도 브라우저로 PLC IO 본다 (PLCLink Phase 0 구현기)
지난 글에서 PLCLink를 왜 만들게 됐는지 얘기했습니다.
배선 확인할 때마다 제어 인원이 옆에 붙어야 하는 구조, 검사기 없이는 통신 로직 확인도 안 되는 상황이었고요.
이번 글은 Phase 0 실제로 첫 번째 동작을 만들어간 과정입니다.
Phase 0의 목표는 하나였습니다.
"엔지니어링 툴 없이, 브라우저에서 PLC IO 상태를 확인할 수 있는가"
Phase 0에서 만든 것
| 기능 | 내용 |
|---|---|
| 통신 진단 | PLC와 연결이 됐는지 단계별로 확인 |
| IO 상태 확인 | 비트(신호 ON/OFF)와 워드(숫자값) 실시간 확인 |
| 뷰 분리 | 엔지니어 설정 화면 / 비전문가 확인 화면 분리 |
단순해 보이지만 실제로 만들면서 생각보다 고민이 많았습니다.
1. 통신 진단 — 왜 4단계로 나눴나
처음에는 "연결 됐나요? Yes/No" 한 줄이면 충분할 것 같았습니다.
그런데 현장에서 연결이 안 됐을 때 원인이 한 군데가 아닙니다.
- 네트워크 자체가 안 되는 건지
- TCP 포트(통신 번호)가 막힌 건지
- PLC는 응답하는데 주소가 틀린 건지
- 읽어온 값 자체가 이상한 건지
그래서 4단계로 나눠서 어디까지 됐는지를 화면에 표시하도록 만들었습니다.
1단계 Ping → 네트워크 연결 자체가 되는가
2단계 TCP → PLC가 지정 포트에서 응답하는가
3단계 SLMP 응답 → MC Protocol 통신 자체가 되는가
4단계 값 정합성 → 읽어온 값이 유효한 범위인가
한 단계에서 실패하면 이후 단계는 자동으로 스킵하고, 해당 단계의 실패 원인을 안내합니다.

2. PLC Maker 선택 : Keyence와 Mitsubishi가 다르다
처음에는 Mitsubishi Q/R 시리즈 하나만 생각하고 만들었습니다.
그런데 실제로 Keyence KV 시리즈에 연결해보니 주소 체계가 달랐습니다.
KV Studio(Keyence PLC 프로그래밍 소프트웨어)에서 Y3920으로 보이는 주소를 그대로 SLMP 프로토콜(MC Protocol의 통신 규격)에 사용하면 값이 항상 0으로 나옵니다.
주소를 계산하는 방식 자체가 다르기 때문입니다.
Mitsubishi 방식:
Y3920 → 16진수 그대로 → SLMP 주소: 14624 (0x3920)
Keyence KV 방식:
Y3920
마지막 자리 "0" = 비트 위치 (0~F, 16진수)
앞 자리 "392" = 그룹 번호 (10진수)
SLMP 주소: 392 × 16 + 0 = 6272
같은 Y3920이라도 Mitsubishi는 14624번지, Keyence는 6272번지를 읽어야 합니다.
이걸 모르면 "통신은 되는데 값이 항상 0"이라는 상황이 생깁니다.
PLCLink에서는 설정 화면에서 PLC Maker를 선택하면 주소 변환이 자동으로 적용됩니다.
자세한 내용은 보족 글에서 따로 다룹니다.

3. IO 상태 확인 : 매번 입력 말고, 한 번 등록해두기
매번 주소를 직접 입력하는 방식이 아니라, 확인하고 싶은 포인트(PLC 주소)를 한 번 등록해 두면 계속 자동으로 읽어오는 방식을 선택했습니다.

등록 정보:
- 디바이스 종류: X, Y, M, D 등 (PLC 내부 메모리 영역 구분)
- 시작 주소: 어느 번지부터 읽을지
- 점수: 몇 개의 신호를 한 번에 읽을지
- 라벨: "실린더A 전진 완료" 같은 알아볼 수 있는 이름
등록해두면 선택한 주기(200ms, 500ms, 1000ms, 2000ms)로 자동 반복 읽기(폴링)를 합니다.
표시 방식은 이렇습니다.
- 비트(1비트 신호): ON이면 초록 박스, OFF이면 회색 박스
- 워드(16비트 숫자값): 현재 숫자값 그대로 표시
브라우저 로컬 스토리지(localStorage, 브라우저에 데이터를 저장하는 공간)에 설정을 저장해두니까,
페이지를 새로고침해도 등록한 포인트 목록이 그대로 남아 있습니다.
4. 뷰 분리 — URL 하나로 모드가 바뀐다
엔지니어가 설정해둔 화면을 비전문가도 별도 안내 없이 볼 수 있게 하고 싶었습니다.
URL 파라미터(주소 뒤에 붙는 조건값)로 모드를 나눴습니다.
| URL | 모드 | 차이 |
|---|---|---|
| http://서버IP:5173 | 엔지니어 모드 | 포인트 추가/수정, 설정 변경 가능 |
| http://서버IP:5173/?view=1 | 확인 모드 | 설정 화면 조회만 가능, 수정 불가 |
확인 모드에서는 사이드바(메뉴 패널)가 숨겨지고 포인트 수정 버튼이 아예 렌더링(화면에 그려지는 것)되지 않습니다.
숨겨진 게 아니라 코드 자체에 존재하지 않아서, 개발자 도구를 열어도 억지로 만들어낼 수 없습니다.
엔지니어가 확인 모드 URL을 공유하면, 전장 담당자나 기구 담당자가 자기 핸드폰으로 바로 접속할 수 있습니다.

에로사항 — 만들면서 막힌 것들

에로사항 1 : 통신은 됐는데 값이 항상 0
SLMP 응답은 옵니다. 오류도 없습니다.
그런데 읽어온 값이 항상 0입니다.
PLC에서는 분명히 신호가 ON인데.
처음에는 폴링 로직 문제라고 생각해서 비동기 코드를 몇 번이나 다시 봤습니다.
그 다음에는 주소가 잘못됐나 의심했습니다.
그러다가 아예 /api/debug/scan-full이라는 디버그 엔드포인트(특정 목적으로 만든 API 주소)를 만들어서 디바이스 코드와 주소 범위를 전수 스캔했습니다.
0x9D(Y 디바이스 코드) + 주소 6272에서 값 3이 찍혔고, 거기서 "주소 체계가 다르구나"를 알게 됐습니다.
값이 0으로 나오는 건 "연결은 됐는데 틀린 주소를 보고 있다"는 뜻이었습니다.
에로사항 2 : 설정이 저장됐다가 사라지는 버그
항목을 추가하고 페이지를 벗어났다 돌아오면 초기화되는 문제가 있었습니다.
원인은 useLocalStorage(브라우저 로컬 저장소와 연결하는 커스텀 훅)에 있었습니다.
상태를 업데이트할 때 함수 형태로 전달하면, 그 함수 자체가 JSON으로 변환되어 저장되는 버그였습니다.
함수는 JSON으로 변환이 안 되니까 실제로는 undefined(정의되지 않음)가 저장됐고, 다음에 페이지를 열면 빈 상태로 시작합니다.
// 문제 코드
localStorage.setItem(key, JSON.stringify(newVal))
// 수정 코드
const next = typeof newVal === 'function' ? newVal(prev) : newVal
localStorage.setItem(key, JSON.stringify(next))
코드 한 줄 차이지만, 현장에서 설정해놓은 게 날아가면 신뢰가 떨어집니다.
Phase 0 완료 (이게 가능해졌다)

Phase 0가 완료된 시점에서 실제 현장에서 이런 것들이 가능해졌습니다.
전장 담당자가 배선을 연결한 뒤, 핸드폰 브라우저에서 해당 IO 신호가 들어오는지 직접 확인할 수 있습니다.
제어 담당자가 옆에서 대기할 필요가 없습니다.
처음에는 핸드폰으로 접속이 된다는 걸 확인했을 때 "이게 되네?" 싶었습니다.
당연히 되는 구조로 만들었는데 막상 실제로 보니까 달랐습니다.
공유기만 있으면 전장 작업자가 각자 핸드폰으로 볼 수 있다는 게 생각보다 실용적이었습니다.
다음 단계(Phase 1)에서는 데이터를 기록하고, 값을 직접 쓰고, 조건이 성립하면 알림을 받는 기능을 추가합니다.
TMI — 더 알고 싶다면
통신 진단 4단계 중 어느 단계에서 제일 많이 막히나요?
경험상 3단계(SLMP 응답)에서 제일 많이 막힙니다. 네트워크 연결은 됐는데 PLC 쪽 MC Protocol 설정이 안 되어 있는 경우가 많습니다. Mitsubishi는 GX Works에서, Keyence는 KV Studio에서 통신 유닛 설정을 해줘야 합니다.
폴링 주기는 어떻게 정하는 게 좋나요?
PLC 스캔타임(PLC가 프로그램을 한 번 실행하는 주기, 보통 수 ms
수십 ms)보다 길게 유지하는 게 기본 원칙입니다. PLCLink 기본값은 200ms
500ms입니다. 배선 확인처럼 빠른 응답이 필요 없는 용도면 500ms~1000ms로 느슨하게 잡아도 됩니다.
현장에 WiFi가 없으면 어떻게 하나요?
공유기를 하나 가져가서 PLC 허브(HUB, 여러 기기를 연결하는 네트워크 장치)에 연결하거나, 서버 PC에서 WiFi 핫스팟을 켜는 방법이 있습니다. 어떤 방식이든 핸드폰이 서버 PC와 같은 네트워크에 있으면 됩니다.
확인 모드의 수정 차단은 보안이 되나요?
완전한 보안은 아닙니다. 서버 API 자체에 인증이 없으면 API를 직접 호출해서 값을 변경하는 건 기술적으로 가능합니다. 확인 모드는 UI 레벨의 차단입니다. 비전문가가 실수로 건드리는 것을 막는 용도이고, 악의적인 접근을 막는 용도는 아닙니다. 추후 인증 기능 추가를 고려하고 있습니다.
IO 포인트 주소를 직접 입력해야 하나요?
현재는 직접 입력하는 방식입니다. GX Works나 KV Studio에서 주소를 확인하고 옮겨 적는 방식으로 쓰고 있습니다. 나중에는 PLC에서 모듈 정보를 자동으로 불러와서 주소 입력을 더 편하게 할 계획입니다.
코드는 GitHub에서 확인할 수 있습니다.
github.com/Gweongooing/PLCLink
'(개인Project)_개발 > PLC-PC 연결' 카테고리의 다른 글
| [Program][Phase1.5] PLC 껐다 켜도 데이터 남기는 방법 (SQLite 전환으로 이력 관리 시작) (0) | 2026.05.12 |
|---|---|
| [Program][보족] Mitsubishi MC Protocol로 Keyence PLC 연결하기 ( 주의할 것들) (0) | 2026.05.02 |
| [Program][보족] 등록한 포인트가 새로고침하면 사라지는 버그 (원인과 해결 한 줄) (0) | 2026.05.01 |
| [Program][보족] GitHub 몰라도 괜찮다 (PLCLink 다운받는 법 단계별 정리) (0) | 2026.04.30 |
| [Program][시작] 현장 엔지니어가 직접 만든 PLC 웹 모니터링 툴 (왜 만들었나?) (0) | 2026.04.20 |