주말 동안 서비스 하고 있는 홈페이지에서 문제를 해결한 경험을 간단하게 기록으로 남기고자 글을 씁니다. 다만 Date 객체의 특수한 스펙이 문제 원인이었다 이런 내용은 아니고 단순히 문제가 발생한 상황에서 어떻게 대응했는지, 그리고 어떤 식으로 예방할 수 있었는지 회고하는 글입니다.
트러블 슈팅 타임라인
문제 발생
평화로운 일요일, 서비스 하고 있는 홈페이지의 제품 마감 시간이 하루가 땡겨져서 동작하고 있다는 청천벽력의 소식을 전화로 급히 전해 들었습니다.(서비스 특성 상 마감시간이 매우 중요합니다)
뭐가 문제인지는 모르겠지만, 일단 개발 DB등에 접근하려면 폐쇄망에 들어가야 합니다. 마음을 다잡으며 vpn을 켰습니다.
원인 추측
리스트 페이지에서는 마감일시가 정상적으로 표시되고 있었다.
상세 페이지에서는 마감시간만 이상하게 하루가 날라간 채로 동작하고 있다.
network 탭을 통해 api에서 날라오는 데이터가 정상인지 먼저 확인하자
아니면 javascript 동작 문제를 찾아보자
대충 이런 식의 사고 흐름을 생각하면서 노트북 부팅과 연결 시간을 보냈습니다.
디버깅 단계
먼저 네트워크 탭 살펴보니 데이터는 정상
마감시간을 처리하는 DOM 처리 하는 코드 쪽을 보니 데이터 넘어가는 거 정상
하지만 DOM의 처리 결과는 마감시간이 하루 먼저 땡겨져서 동작하는거 확인
데이터로 받은 시간을 Date 객체로 변환한후 현재 시간과 마감시간의 diff 를 계산하는 함수 코드에서 결과가 비정상으로 넘어오는 것 확인
diff를 계산하는 함수 코드 한줄씩 데이터 파싱 되는 부분 추적
괴상한 매직 넘버 발견.
// 실제 문제 됐던 코드의 일부입니다. org = new Date(org.getFullYear(), org.getMonth() + 1, org.getDate(), org.getHours(), org.getMinutes(), org.getSeconds()); target = new Date(target.getFullYear(), target.getMonth() + 1, target.getDate(), target.getHours(), target.getMinutes(), target.getSeconds());
3월의 말일이라는 오늘의 날짜와 마감시간이 4월의 첫날이라는 조건이 만나 마감시간이 기적처럼 하루가 날아가는 현상 발견
date 두개 diff를 계산할때 org이 3월 31일 이었고 target이 4월 1일이었습니다.
둘다 1개월씩 추가되니 전자는 5월 1일이 되버렸고(4월은 30일까지임), 후자도 5월 1일이 되버리는 문제가 있어서 하루 먼저 마감이 발생하는 버그였습니다.
0부터(1월이 0) 시작하는
getMonth
의 반환 값을 보고 1을 더한게 아닐까 추측해봅니다.
해결 과정
개발 환경 -> 테스트 환경 -> 최종 운영 환경 반영
이터레이션
데이터를 동일하게 세팅
문제 재현 확인
매직 넘버 제거
정상 동작 확인
상황 종료, 이 과정이 약 1시간 소요 됐습니다.
문제를 예방하거나 조기에 대응하기 위한 고민
테스트 코드 도입: 제일 먼저 생각하는 건 역시 테스트 코드였습니다. 함수 단위에서 문제가 발생하는 것은 테스트를 작성할 때 많이 예방 되는 편입니다.
시간 처리 라이브러리 도입: dayjs나, date-fns 같은 시간 처리를 위해 특화된 라이브러리를 도입하는 것 또한 좋은 옵션이 될 수 있을 것 같습니다.
마치며
간단한 트러블 슈팅 사례를 기록으로 남겨 봤습니다. 이런 연습을 통해 나중에 큰 문제를 해결하는데도 문제를 체계적으로 대응하는데 도움이 될 거라고 생각하여 글로 정리해봤습니다.