금요일 오후 3시, 라이브 제품에서 버그 리포트가 들어왔다
- 03 Dec, 2025
금요일 오후 3시, 라이브 제품에서 버그 리포트가 들어왔다
금요일 오후 3시 17분
슬랙에 빨간 점이 떴다. CS팀 채널.
“펌웨어팀 @김펌웨어 님, 고객사에서 제품 이상 동작 리포트 들어왔습니다. 확인 부탁드립니다.”
첨부된 영상을 봤다. 우리 제품이 멈춰있다. 화면에 아무것도 안 뜬다. LED만 깜빡인다.
양산 나간 지 3개월 된 제품이다. 지금까지 문제없었다. 갑자기 왜.
“재현되나요?” 물었다.
“고객사에서는 자주 발생한다고 합니다. 저희 테스트에서는 재현 안 됩니다.”
제일 싫은 유형이다.

일단 로그부터
고객사에 요청했다. “디버그 로그 남아있나요?”
30분 후 답장. “로그 기능 꺼져있었습니다.”
당연하지. 양산 버전은 로그 비활성화했다. 플래시 용량 아끼려고.
“언제부터 발생했나요?”
“정확히는 모르겠습니다. 이번 주에 여러 번 발생했다고 합니다.”
증상만 봐서는 모른다. 리셋인지, 하드폴트인지, 워치독인지.
우리 테스트 환경에서는 3시간째 돌려도 멀쩡하다. 고객 환경이 뭐가 다른 거지.
팀장한테 보고했다. “양산 제품 이슈 들어왔습니다. 재현은 안 됩니다.”
“심각한가?”
“고객사에서 자주 발생한다고 합니다.”
“주말에 대응 가능한가?”
알았다는 뜻이다.
환경 차이
고객사 환경을 조사했다. CS팀이 정리해준 내용.
- 24시간 연속 동작
- 온도: 실내, 에어컨 있음
- 전원: 5V 어댑터
- 네트워크: WiFi, 공유기는 TP-Link
- 펌웨어 버전: v1.2.3 (최신)
우리 테스트 환경이랑 똑같다. 뭐가 다르지.
HW팀 민수한테 물었다. “하드웨어 이슈 가능성?”
“양산 전에 다 검증했는데요. EMC 테스트도 통과했고.”
“혹시 로트 문제?”
“같은 로트 제품 다른 데서는 문제없어요.”
소프트웨어 문제다. 그것도 특정 조건에서만.

금요일 오후 5시
팀원들 다 퇴근했다. 팀장만 남아있다.
“일단 집에 가. 주말에 보자.”
나도 가고 싶다. 근데 못 간다.
고객사는 월요일까지 답변 원한다. 일요일 밤까지 원인 찾아야 한다.
회사 냉장고에서 레드불 두 개 꺼냈다. 오늘 밤샐 것 같다.
일단 코드 리뷰부터 시작했다. v1.2.3 릴리즈 이후 변경점.
아무것도 없다. v1.2.3이 최신이고, 그 이후 수정사항 없다.
그럼 v1.2.3 자체에 버그가 있다는 건데. 3개월 동안 왜 안 나왔지.
테스트 시나리오를 다시 봤다. 우리가 놓친 케이스가 있다.
24시간
고객사는 24시간 연속 동작이라고 했다. 우리 테스트는 최대 8시간.
보통 8시간이면 충분하다. 메모리 릭도 잡히고, 타이밍 이슈도 나온다.
근데 24시간 이상 돌려야 나오는 버그도 있다. 타이머 오버플로우 같은 거.
코드에서 타이머 쓰는 부분을 찾았다. 여러 개다.
WiFi 재연결 타이머, 센서 폴링 타이머, 워치독 타이머, RTC…
한 개씩 체크했다. 변수 타입, 오버플로우 조건, 래핑 처리.
있다.
WiFi 재연결 로직에서 uint32_t 타이머를 밀리초로 쓴다. 49일마다 오버플로우.
근데 비교 로직이 단순 대소비교다. 오버플로우 케이스를 안 본다.
if (current_time > reconnect_time + timeout) {
wifi_reconnect();
}
49일 넘어가면 current_time이 0으로 돌아간다. reconnect_time은 큰 값.
이 조건이 영원히 참이 된다. WiFi 재연결을 무한 반복한다.
찾았다.

금요일 밤 11시
재현 시나리오를 짰다. 타이머를 강제로 49일 근처 값으로 세팅.
보드에 올렸다. 돌렸다.
10분 후 멈췄다. 똑같은 증상.
LED만 깜빡이고, 응답 없다. 로그 출력도 멈췄다.
원인 확정이다.
수정은 간단하다. 타이머 비교 로직을 래핑 세이프하게.
if ((int32_t)(current_time - reconnect_time) > timeout) {
wifi_reconnect();
}
부호 있는 정수로 캐스팅하면 오버플로우 케이스도 올바르게 동작한다.
수정했다. 다시 테스트.
이번엔 안 멈춘다. 1시간 돌렸다. 문제없다.
패치 버전을 만들었다. v1.2.4.
빌드하고, 테스트 보드에 올리고, 검증했다.
새벽 2시다.
문서 작업
버그 리포트를 썼다.
원인: WiFi 재연결 타이머 오버플로우 처리 누락
발생 조건: 연속 동작 49일 경과 시
영향: 제품 응답 없음, LED만 동작
수정: 타이머 비교 로직 오버플로우 세이프하게 수정
패치 버전: v1.2.4
CS팀에 전달할 자료도 만들었다.
“고객사에 전달 부탁드립니다. 월요일 오전까지 v1.2.4 펌웨어로 업데이트하면 해결됩니다.”
양산 제품 패치 계획도 세웠다. 이미 나간 제품들은 OTA로 업데이트.
다행히 우리 제품은 OTA 지원한다. 안 했으면 리콜이다.
새벽 3시. 집에 갔다.
토요일 오전
11시에 일어났다. 슬랙 확인.
팀장: “고생했다. 월요일은 오후 출근해라.”
고맙다.
CS팀: “고객사에 전달했습니다. 월요일 업데이트 예정입니다.”
됐다.
침대에 누웠다. 천장을 봤다.
49일. 1180시간. 누가 그렇게 오래 테스트하나.
우리 테스트 시나리오는 8시간이 최대다. 비용 때문에. 시간 때문에.
양산 전에 못 잡은 버그다. 고객이 먼저 발견했다.
Low 레벨 개발은 이런 거다. 한 줄 실수가 49일 뒤에 터진다.
웹이면 고쳐서 배포하면 된다. 5분이면 된다.
펌웨어는 OTA 있어도 조마조마하다. 업데이트 중에 전원 나가면 브릭이다.
그래도 찾아서 다행이다.
교훈 같은 건 없다
타이머 오버플로우는 기본 중의 기본이다. 알고 있었다.
그런데 놓쳤다. 코드 리뷰 때 못 봤다. 테스트로도 못 잡았다.
완벽한 코드는 없다. 완벽한 테스트도 없다.
고객이 발견하기 전에 찾으면 좋은 거고, 못 찾으면 이렇게 된다.
금요일 오후 3시에 리포트 들어오고, 주말 날리고, 새벽에 고치고.
이게 펌웨어 개발이다.
월요일에 팀 회의 때 공유할 것이다. “타이머 비교 로직 체크리스트에 추가하자.”
다들 “아 그거” 할 거다. 알면서 놓친 거니까.
그래도 체크리스트에 넣는다. 다음에 또 놓칠 테니까.
Low 레벨은 이렇다. 같은 실수를 반복하지 않으려고 체크리스트 만들고, 그래도 놓친다.
그럼 또 추가한다. 체크리스트가 100개 넘어간다.
읽는 사람은 없다. 너무 길어서.
일요일
푹 잤다. 아무것도 안 했다.
월요일 오후 출근 예정이다. 고객사 업데이트 결과 확인해야 한다.
문제없이 되면 좋겠다. OTA 실패하면 또 야근이다.
침대에 누워서 생각했다. 웹 개발자들은 지금 뭐 하고 있을까.
카페에서 맥북 켜고 코딩하고 있을까. 배포 버튼 누르면 끝일까.
부럽다.
나는 보드 없으면 일 못 한다. 회사 와야 한다. 오실로스코프 봐야 한다.
디버거 연결하고, 플래시 지우고, 펌웨어 올리고, 리셋하고, 로그 보고.
49일 버그는 집에서 못 잡는다. 장비가 없어서.
그래도 찾았다. 그걸로 됐다.
금요일 오후의 빨간 알림은 늘 시작이다. 주말이 끝나고 월요일이 온다.
