-
jSerialComm사용해서 read시 윈도우 환경에서의 끊겨서 읽히는 현상 트러블 슈팅Java-Kotlin 2025. 12. 24. 23:57반응형
최근 안드로이드와 RFID 리더기를 연동하는 프로젝트를 진행하면서 겪었던 시리얼 통신의 데이터 파편화 문제와 그 해결 과정을 공유합니다.
1. 문제 상황
저는 jSerialComm 라이브러리를 사용하여 RFID 태그를 시리얼 통신으로 Read하도록 개발하였습니다.
맥(Mac) 환경에서 테스트할 때는 RFID 태그 데이터가 한 번에 잘 들어왔는데, 윈도우 환경이나 특정 태블릿에 리더기를 연결하니 이상한 현상이 발생했습니다.
- 기대값: 10~20바이트의 전체 태그 데이터 (예: ABC12345...)
- 실제값: 단 2바이트만 읽히고 read() 함수가 종료됨 (예: AB)
심지어 read() 함수에 타임아웃을 넉넉히 주었는데도, 데이터가 조금이라도 들어오는 순간 함수가 리턴되어 버리는 문제였습니다. 또한, 태그를 찍지 않았는데도 이전에 찍었던 데이터가 뒤늦게 들어오는 현상도 있었습니다.
2. 원인 분석
원인은 크게 두 가지였습니다.
- 시리얼 통신의 특성: 시리얼 통신은 패킷(Packet) 단위가 아니라 물이 흐르는 스트림(Stream) 방식입니다. 송신 측에서 "Hello"를 보냈다고 해서 수신 측이 반드시 한 번의 read로 "Hello"를 다 받는다는 보장이 없습니다. "He", "llo" 이렇게 쪼개져서 들어올 수 있습니다.
- OS 드라이버의 차이: read(buffer, timeout) 함수의 동작 방식은 "타임아웃까지 기다려라"가 아니라 "데이터가 들어올 때까지 최대 타임아웃만큼 기다려라"입니다. 윈도우나 일부 안드로이드 USB 드라이버는 데이터를 버퍼링하다가 아주 짧은 덩어리로 먼저 보내주기도 합니다. 앱 입장에서는 "어? 데이터 왔네?" 하고 2바이트만 읽고 루프를 빠져나가 버리는 것입니다.
3. 해결 방법 (Solution)
이 문제를 해결하기 위해 두 가지 로직을 적용했습니다.
- Drain 로직 추가: read 요청 직전에 남아있는 하드웨어/소프트웨어 버퍼 찌꺼기를 강제로 비웁니다.
- 모으기 로직 추가: 한 번의 read를 믿지 않고, 원하는 데이터가 다 찰 때까지 반복해서 읽습니다.
위 로직 2가지를 추가함으로서 문제 상황을 해결 할 수 있었습니다.
4. 결론
시리얼 통신을 다룰 때는 "한 번의 read 호출로 모든 데이터가 온다"는 가정을 버려야 한다는 것을 알게 되었습니다. 특히 안드로이드의 다양한 제조사 단말기와 USB 컨트롤러 환경을 고려한다면, 반드시 루프를 돌며 데이터를 누적 하여 데이터를 처리하도록 하는 로직은 필수적입니다.
또한, RFID처럼 태깅 시점이 불분명한 경우 read 직전에 버퍼를 비워주는(Drain) 작업를 해야 "이전에 찍은 데이터"가 "지금 찍은 데이터"로 보이는 것을 막을 수 있습니다.
'Java-Kotlin' 카테고리의 다른 글
Kotlin에서 RfidReader와 USB Serial로 통신 기능 구현 (1) 2025.12.10