외부 기기의 상태 확인과 표시의 베스트 프랙티스 - 『접속 중』으로만 끝내지 않는 설계
· 小村 豪 · Windows, 외부 기기, 장치 연계, 상태 관리, UI/UX, 감시
산업용 카메라, 바코드 리더, PLC, 계측기, 프린터, 시리얼 기기, USB 기기.
외부 기기와 연결되는 Windows 앱에서는 실제 불량 그 자체보다 먼저 화면의 상태 표시가 현실과 어긋나는 것으로 사고가 나는 경우가 꽤 많습니다.
예를 들어 이런 상태입니다.
- OS에서는 보이는데 다른 프로세스가 잡고 있어 쓸 수 없다
open은 됐는데 원점 복귀, 워밍업, 인증이 끝나지 않았다- 기기는 매달려 있지만 응답은 이미 멈춰 있다
- 취득 스레드가 죽어 있는데 마지막 값만 화면에 남아 있다
- 상정 외의 개체나 firmware인데 단순히 「접속 중」이라고 표시해 버린다
여기서 정말로 알고 싶은 것은 연결되어 있는가 어떤가만이 아닙니다.
지금 무엇을 안전하게 해도 되는가입니다.
1. 먼저 결론
외부 기기의 상태 확인과 표시에서 가장 효과가 있는 것은 상태를 1개의 boolean으로 뭉개지 않는 것입니다.
적어도 다음은 나누는 편이 안전합니다.
- 존재: OS에서 보이는가
- 세션 확립: 자기 앱이 open / login / initialize 완료인가
- 응답성: heartbeat나 status query에 돌아오는가
- 기능 준비: 실제 조작을 지금 받을 수 있는가
- 데이터 신선도: 화면의 값은 새로운가
- 구성 일치: 상정한 개체, 형번, firmware인가
- 감시 건전성: 애초에 감시 처리가 살아 있는가
꽤 거칠게 말하면 이렇습니다.
존재 확인은 OS 쪽, 사용 가부는 앱 쪽, 신선도 판정은 화면 쪽에서 가진다.
이 3가지를 섞지 않는 것만으로도 상태 표시는 꽤 안정됩니다.
2. 왜 「접속 중」이 위험한가
「접속 중」이라는 문구는 하나의 문구로 여러 의미를 멋대로 짊어지게 됩니다.
실제로는 적어도 다음 질문들이 섞여 있습니다.
- OS에서 대상 기기의 interface가 보이는가
- 자기 앱이 그 기기를 open / login / initialize할 수 있었는가
- 가벼운 문의에 기한 내에 답하는가
- 지금 요구한 조작을 안전하게 실행할 수 있는가
- 화면에 나오는 값은 새로운가
- 상정한 개체·형번·firmware인가
이 6가지 중 어느 것을 충족하고 있는가에 따라 「쓸 수 있다」의 의미는 바뀝니다.
예를 들어 다음 4가지는 전부 다릅니다.
- 미접속
애초에 OS가 대상 interface를 찾지 못했음 - 접속 완료 / 확인 중
물리적으로는 보이지만 초기화나 인증이 끝나지 않음 - 접속 완료 / 사용 불가
응답은 있지만 warming up, busy, interlock, media 없음 등으로 동작할 수 없음 - 값이 오래됨
이전에는 취득할 수 있었지만 화면의 값은 freshness budget을 초과했음
이것들을 전부 「접속 중」으로 뭉개면 operator는 무엇을 해야 할지 판단할 수 없습니다.
3. 우선 나누어야 할 상태
추천은 내부 상태는 다축으로 가지고, UI에서는 필요에 따라 요약하는 것입니다.
3.1 내부에서 나누고 싶은 상태축
| 축 | 무엇을 의미하는가 | 전형적인 확인 방법 | UI에서 보여 주고 싶은 예 |
|---|---|---|---|
| 존재 | OS에서 대상 interface가 보이는가 | 기동 시 열거, arrival / removal 통지 | 미접속 / 접속 완료 |
| 세션 | 자기 앱이 open / login / initialize 완료인가 | handle / SDK 초기화 결과 | 확인 중 / 초기화 중 |
| 응답성 | status query나 heartbeat에 돌아오는가 | timeout 붙은 경량 문의 | 응답 있음 / 응답 지연 / 응답 없음 |
| 기능 준비 | 실제 조작이 지금 가능한가 | device-specific status | 사용 가능 / busy / warming up |
| 데이터 신선도 | 표시값이 새로운가 | timestamp / sequence | 최신 / 값이 오래됨 |
| 구성 일치 | 상정 기기와 일치하는가 | model / serial / firmware / profile | 대상 기기 / 상정 외 기기 |
| 감시 건전성 | 앱의 감시 경로가 살아 있는가 | worker heartbeat / loop lag | 감시 중 / 감시 정지 |
여기서 중요한 것은 기기가 나쁜 상태와 앱이 관측할 수 없는 상태를 나누는 것입니다.
3.2 UI는 전부를 평면적으로 보여 주지 않아도 된다
내부에서 다축으로 가지면 화면이 시끄러워질 것처럼 보입니다.
하지만 UI는 전부를 같은 무게로 낼 필요는 없습니다.
추천은 3층입니다.
- 상단에 요약 상태
- 그 아래에 이유
- 필요하다면 상세 패널
예를 들어,
- 요약:
접속 완료 / 사용 불가 - 이유:
워밍업 중남은 약 18초 - 상세:
modelserialfirmwarelast heartbeatlast frame time
처럼 나누면 정보량을 늘려도 꽤 읽기 쉬워집니다.
4. 상태 확인의 베스트 프랙티스
4.1 기동 시 열거와 도착 / 삭제 통지
Windows에서 외부 기기를 다룰 때의 토대는 기동 시에 기존 기기를 열거하고, 이후에는 arrival / removal 통지를 받는 것입니다.
특히 잡아 두고 싶은 것은 다음입니다.
- 통지만으로는 기존 기기는 주울 수 없다
- runtime communication에서는 setup class보다 interface class 쪽이 자연스럽다
- remove 통지와 I/O error의 보이는 방식이 전후할 수 있다
실무 규칙으로서는 심플합니다.
- 기동 시에 열거한다
- 통지를 구독한다
- 통지를 받으면 재열거해 내부 상태를 reconcile한다
4.2 「존재」「열 수 있다」「응답한다」「쓸 수 있다」를 나눈다
외부 기기의 사고는 여기를 한꺼번에 다뤘을 때 늘어납니다.
- 존재한다
OS에서 interface가 보인다 - 열 수 있다
다른 프로세스 경합이나 권한 문제 없이 handle / session을 가질 수 있다 - 응답한다
가벼운 문의에 timeout 내에 답한다 - 쓸 수 있다
실제의 조작을 받을 수 있다
이 4가지는 같지 않습니다.
4.3 event와 poll을 섞는다
event 기반만, poll 기반만, 중 어느 한쪽으로 치우치기보다 검출은 event, 건전성 확인은 poll이 실무에서는 다루기 쉽습니다.
- arrival / removal은 event
- heartbeat / status query는 poll
- freshness 판정은 timestamp / sequence
이 나눔 방식으로 하면 접속 검출과 실사용 가부를 끊어내기 쉬워집니다.
4.4 감시 처리와 UI를 분리한다
UI thread에서 직접 open / read / status query를 돌리면 표시의 사정과 감시 처리의 사정이 쉽게 섞입니다.
추천은,
- 감시 워커가 state store를 갱신
- UI는 state store를 구독해 묘화
- UI 조작은 command로서 감시 층에 건넨다
라는 형태입니다.
이것으로 감시 정지와 기기 정지를 나누어 다루기 쉬워집니다.
4.5 개체 식별을 안정시킨다
friendly name이나 COM3 같은 겉보기 식별자만으로 상태를 쫓으면 개체를 잘못 잡기 쉬워집니다.
가능하다면,
- serial number
- logical device id
- stable device path
- 기기 쪽의 개체 ID
같은 흔들리지 않는 키를 내부에 가지는 편이 안전합니다.
5. 표시의 베스트 프랙티스
5.1 한 장으로 보는 판단표
| 실제 상태 | UI의 요약 | 보충 표시 |
|---|---|---|
| interface 없음 | 미접속 | 케이블, 전원, USB 접속을 확인 |
| interface 있음, 초기화 중 | 접속 완료 / 확인 중 | 초기화 중, 인증 중, 워밍업 중 |
| 응답 있음, 조작 조건 미달 | 접속 완료 / 사용 불가 | busy, media 없음, interlock open |
| 응답 있음, 값이 오래됨 | 접속 완료 / 값이 오래됨 | 최종 갱신 12초 전 |
| 응답 없음 | 응답 없음 | 재접속 중, 통신 timeout |
| 상정 외 개체 | 상정 외 기기 | model / serial / firmware 불일치 |
| 감시 처리 정지 | 감시 이상 | 감시 워커 정지, 재기동이 필요 |
5.2 문구는 「상태 + 이유 + 다음 행동」
에러나 이상만으로는 화면으로는 약합니다.
메시지는 다음 3요소로 치우치는 편이 operator가 헷갈리기 어려워집니다.
- 상태: 무엇이 일어나고 있는가
- 이유: 왜 그렇게 판단했는가
- 다음 행동: 무엇을 하면 되는가
예를 들어,
접속 완료 / 사용 불가 - 워밍업 중 - 약 18초 기다려 주세요응답 없음 - heartbeat timeout - 케이블과 전원을 확인해 주세요상정 외 기기 - Firmware 2.1.0이 필요합니다 - 대상 기기를 확인해 주세요
같은 형태입니다.
5.3 stale data를 숨기지 않는다
last known value는 도움이 됩니다.
다만 live value의 얼굴로 보여 주지 않는 편이 안전합니다.
추천은,
- 값 옆에 timestamp
- 값의 age 표시
- stale이 되면 색이나 라벨을 바꾼다
- 일정 시간을 넘으면 조작 가능 판정에서 뺀다
입니다.
5.4 중요도에 따라 보여 줄 장소를 바꾼다
status bar는 편리하지만 간과되기 쉽습니다.
critical한 이상은 status bar의 구석에만 두지 않는 편이 안전합니다.
- 경미한 상태 변화: status bar
- 작업 계속 가능한 주의: inline notice
- 조작 정지가 필요한 이상: 주 표시 영역, 대화상자, 배너
라는 구분 사용이 솔직합니다.
5.5 여러 대 표시에서는 요약과 상세를 나눈다
여러 대의 기기를 다루는 화면에서는 전건 상세를 항상 내면 보기 어려워집니다.
- 상부에 전체 요약
- 하부에 기기별 행
- 선택 시에 상세 페인
의 3단으로 하면 전체 파악과 개별 구분을 양립시키기 쉽습니다.
6. 재접속과 운영의 베스트 프랙티스
6.1 재접속은 backoff 붙여서
응답이 멈췄을 때의 재접속을 최단 루프로 계속 두드리지 않는 편이 안전합니다.
- device / driver / SDK에 부하를 준다
- 로그가 홍수가 된다
- 일시적인 불안정을 악화시킨다
- UI가 심하게 흔들린다
기 때문입니다.
추천은,
- 초회는 바로 retry
- 안 되면 단계적으로 간격을 늘린다
- 상한을 설정한다
- 수동
재접속도 준비한다
입니다.
6.2 flapping을 매끄럽게 한다
USB 접촉 불량이나 네트워크 순단 같은 장면에서는 상태가 짧은 시간 동안 오갑니다.
여기서 생 이벤트를 그대로 UI에 내면 꽤 보기 어렵습니다.
그래서,
- 내부 로그는 생 이벤트 그대로 남긴다
- UI는 짧은 확인 기간을 두고 나서 확정 표시한다
- 다만 critical 이상은 바로 보여 준다
라는 구분 사용이 다루기 쉽습니다.
6.3 최소한 남겨야 할 로그
상태 표시의 개선은 로그 설계와 거의 세트입니다.
| 항목 | 예 |
|---|---|
| timestamp | 2026-03-20T10:23:41.512+09:00 |
| stable device key | camera:A1B2C3 |
| 표시명 | 전 공정 카메라 |
| 구 상태 -> 신 상태 | Ready -> Stale |
| 이유 | heartbeat timeout firmware mismatch |
| 에러 코드 | HRESULT Win32 SDK code |
| last success | 2026-03-20T10:23:36.011+09:00 |
| age / RTT | 5.5s 320ms |
| retry count | 3 |
| app / firmware version | App 1.8.2 / FW 2.4.1 |
특히 중요한 것은 상태 전이 로그입니다.
6.4 감시 정지와 기기 정지를 혼동하지 않는다
- poll loop가 예외로 죽었다
- SDK callback이 멈췄다
- acquisition worker가 deadlock했다
- state store 갱신만 멈췄다
이럴 때 기기는 살아 있어도 앱은 관측할 수 없습니다.
이 상태를 미접속이나 응답 없음만으로 내면 기기 쪽의 문제로 보여 버립니다.
그래서 감시 경로의 건전성은 별도의 축으로 가지는 편이 좋습니다.
7. 기기 타입별 놓치기 쉬운 점
7.1 USB / PnP 기기
- 통지만으로는 existing device는 주울 수 없다
- runtime에서는 setup class보다 interface class가 자연스럽다
- composite device는 여러 interface를 낼 수 있다
- remove 통지와 I/O error의 보이는 방식이 전후할 수 있다
7.2 시리얼 기기
COMx가 보이고 있는 것만으로는 안심할 수 없습니다.
- 포트 자체는 있지만 대상 기기가 매달려 있지 않다
- 다른 프로세스가 open하고 있다
- 응답은 이미 멈춰 있다
- read / write가 timeout으로 굳는다
시리얼에서는 존재와 응답과 사용 가능을 특히 나누는 편이 안전합니다.
7.3 네트워크 기기
ping이 통과하는 것과 앱이 쓸 수 있는 것을 동일시하지 않는 편이 좋습니다.
- 이름 해결할 수 있는가
- TCP 접속할 수 있는가
- 앱 층 handshake할 수 있는가
- status가 ready인가
- 값이 fresh한가
의 단계가 있습니다.
7.4 SDK 의존의 카메라 / 계측 기기
SDK callback이 오고 있는 것만으로 live로 단정하지 않는 편이 안전합니다.
- callback thread 자체가 멈춘다
- frame은 오지만 timestamp가 나아가고 있지 않다
- image stream은 오지만 control channel이 죽어 있다
- reconnect 후의 설정 재적용이 끝나지 않았다
이기 때문에 SDK의 밖에서 본 건전성도 가지면 안전합니다.
8. 해서는 안 되는 것
- 상태를
접속 중 / 미접속 / 에러의 3개로 뭉갠다 - 통지만으로 existing device도 주울 수 있다고 생각한다
open성공을 그대로사용 가능으로 본다- last known value를 fresh한 얼굴로 보여 준다
- timestamp를 표시하지 않는다
- UI thread에서 open / read / status query를 돌린다
- retry를 최단 루프로 돌린다
- critical한 이상을 status bar에만 낸다
미접속과감시 정지를 혼동한다- friendly name이나
COM3만으로 개체 식별한다
9. 정리
외부 기기 연계 앱에서 정말로 중요한 것은 무엇을 확인하면 어디까지 말해도 되는가를 정하는 것입니다.
특히 다음이 효과가 있습니다.
존재하고 있다
자기 앱이 열 수 있다
응답하고 있다
지금 그 조작을 할 수 있다
화면의 값이 새롭다
이 5가지를 나눈다.
그 위에서 꽤 거칠게 말하면 다음입니다.
- 기동 시는 열거, 이후는 통지
- 사용 가부는 heartbeat와 device-specific status로 정한다
- 표시값에는 timestamp와 age를 가지게 한다
- critical한 이상은 간과되기 어려운 장소로 낸다
- 감시계의 이상을 기기 이상으로 보여 주지 않는다
「접속 중」이라고 낼 수 있는 것보다 그 표시가 현실과 얼마나 어긋나기 어려운가 쪽이 실무에서는 훨씬 중요합니다.
10. 참고 자료
- Microsoft Learn, CM_Register_Notification
- Microsoft Learn, Registering for Notification of Device Interface Arrival and Device Removal
- Microsoft Learn, Registering for Device Notification
- Microsoft Learn, Comparison of setup classes and interface classes
- Microsoft Learn, Device Information Sets
- Microsoft Learn, SetupDiEnumDeviceInterfaces
- Microsoft Learn, Communications functions
- Microsoft Learn, ClearCommError
- Microsoft Learn, COMMTIMEOUTS structure
- Microsoft Learn, WaitCommEvent
- Microsoft Learn, Monitoring Communications Events
- Microsoft Learn, Status Bars (Design basics)
- Microsoft Learn, UX checklist for desktop applications
관련 기사
같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.
Windows의 문자 코드와 개행 코드를 정리한다 - Shift_JIS / UTF-8 / UTF-16, 문자 깨짐, CRLF / LF, 왜 혼란스러운가
Windows에서 자주 섞이는 Shift_JIS와 UTF-8, UTF-16, BOM, CRLF/LF의 차이를 bytes 시점에서 분해하고, 문자 깨짐과 개행 문제를 나누어 다루는 실무 규칙과 사고 조사의 5문 체크리스트까지 정리했습니다.
ClickOnce란 무엇인가 - 구조, 업데이트, 어울리는 장면・어울리지 않는 장면을 실무 시점에서 정리
ClickOnce가 무엇이고 매니페스트, 캐시, 업데이트, 서명이 어떻게 맞물려 동작하는지를 Mermaid 그림과 함께 정리하고, 사내용 .NET 데스크톱 앱 배포에서 어울리는 안건과 어울리지 않는 안건을 실무 시점에서 판단할 수 있도록 도와드립니다.
Windows 샌드박스로 Windows 앱 개발의 검증을 빠르게 하는 방법 - 관리자 권한 문제, 클린 환경, 권한 부족・리소스 부족의 재현을 실무용으로 정리
Windows Sandbox로 Windows 앱의 클린 환경 검증을 빠르게 하는 실무 노하우를 정리합니다. .wsb 파일을 용도별로 나누고, 입력은 읽기 전용・출력만 쓰기 가능으로 분리하며, 표준 사용자나 메모리 부족, GPU 없는 상태의 재현까...
Windows에서 DLL 이름 해결의 메커니즘 - 검색 순서, Known DLLs, API set, SxS를 실무용으로 정리
Windows의 DLL 이름 해결을 검색 순서 암기에서 멈추지 않고, DLL redirection·API set·SxS manifest·Known DLLs 같은 전단 규칙, SetDefaultDllDirectories와 LoadLibraryEx의...
Windows의 관리자 특권이 필요해지는 것은 언제인가 - UAC, 보호 영역, 설계상의 구분 방법
Windows에서 관리자 권한이 필요한지는 사용자 직함이 아닌 앱이 건드리는 경계로 정해진다는 관점에서, UAC 동작과 보호 영역, per-user 대 per-machine, 매니페스트와 분리 모델까지 정리하여 불필요한 승격을 줄이는 설계 판단 ...
관련 토픽
이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.
Windows 기술 토픽
Windows 개발, 장애 조사, 기존 자산 활용에 관한 KomuraSoft LLC 기사를 모은 토픽 허브입니다.
이 주제와 연결되는 서비스
이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.
Windows 앱 개발
상주 처리, 장비 연동, 운영 로그, 유지 보수 가능한 구조가 필요한 Windows 데스크톱 애플리케이션을 지원합니다.
저자 프로필
기사 저자의 프로필 페이지입니다.
Go Komura
합동회사 코무라소프트 대표
Windows 소프트웨어 개발, 기술 상담, 장애 조사를 중심으로 재현이 어려운 장애 조사와 기존 자산이 남아 있는 프로젝트에 강점이 있습니다.
공개 링크