Skip to content
isdnetworks
Go back

늦게 대답하는 장치

휴대폰으로 근거리 무선 장치를 제어하는 앱을 만들었는데 가끔 동작이 이상했다. 버튼을 두 번 누르면 첫 번째 응답이 두 번째 뒤에 오는 경우가 있었다.

Table of contents

Open Table of contents

방금 읽은 응답이 방금 것이라는 가정

코드는 명령을 쓰고 바로 읽어서 그 응답을 방금 보낸 명령의 것으로 다루고 있었다. 유선처럼 순서가 보장되는 환경에서는 대체로 맞는 가정이다.

무선에서는 응답이 늦게 오거나 순서가 바뀌거나 이전 명령의 응답이 지금 도착할 수 있다. 그 가정 하나가 화면을 엉뚱한 값으로 바꾸고 있었다.

요청과 응답에 붙인 번호

프로토콜을 조금 바꿔서 명령과 응답에 같은 번호를 넣게 했다. 앱은 보낸 번호를 기억하고 그 번호의 응답만 받아들인다.

번호가 안 맞는 응답은 버리므로 늦게 온 옛 응답이 화면을 바꾸지 못한다. 순서를 보장할 수 없으면 순서에 기대지 않는 방식으로 바꾸는 것이 답이었다.

타임아웃을 실측으로 정한다

응답이 아예 안 오는 경우가 있어서 기다릴 시간을 정해야 했다. 정상 상태에서 응답 시간을 여러 번 재서 분포를 봤다.

대부분은 매우 짧고 가끔 한참 걸리는 꼬리가 있었다. 감으로 정하면 짧을 때는 정상 응답을 실패로 처리하고 길 때는 사용자를 오래 기다리게 하므로 분포를 보고 꼬리를 어디까지 받아들일지로 정했다.

재시도가 위험한 명령

응답이 없을 때 재시도하고 싶지만 명령은 도착했고 응답만 유실됐을 수 있다. 그러면 재시도가 두 번 실행이 된다.

명령을 성질별로 나누니 절대값 설정과 조회는 두 번 해도 결과가 같고 상대 변경과 토글은 위험했다. 위험한 것들을 절대값 명령으로 바꿔서 앱이 아니라 프로토콜 쪽에서 재시도를 안전하게 만들었다.

연결 상태와 기기 안 로그

무선 연결은 자주 끊기므로 연결을 상태로 다루고 화면에 표시했다. 끊기면 자동으로 다시 붙되 사용자가 앱을 안 보고 있으면 시도하지 않게 해서 배터리를 아꼈다.

현장에서 나는 문제는 재현이 어려워서 최근 사건을 담는 순환 버퍼 로그를 앱 안에 뒀다. 시각과 순번이 함께 남으니 문의가 왔을 때 무슨 일이 있었는지를 재구성할 수 있었다.

정리


Share this post on:

Previous Post
스토어 심사가 실제로 보는 것
Next Post
요약 한 줄과 상세 자료