버그가 저절로 사라지면 반갑기보다 찜찜합니다.
외주 SI 프로젝트의 배치 모니터링 화면에서 상세 드로어가 열리지 않는다는 보고가 들어왔고, 원인을 좁히는 사이에 코드 한 줄 배포하지 않았는데 다시 멀쩡해졌습니다.
이번 포스팅에서는 원인을 끝내 확정하지 못한 버그를 어떻게 기록해 두었는지, 무엇을 반증했고 무엇이 남았는지 순서대로 풀어 보도록 하겠습니다.
콘솔은 조용했고 드로어만 반응이 없었습니다
증상은 단순했습니다. 목록의 행을 눌러도 오른쪽 상세 드로어에 open 클래스가 붙지 않았습니다.
콘솔에는 빨간 오류가 하나도 없었습니다.
이상한 건 드로어를 여는 함수를 콘솔에서 손으로 부르면 열린다는 점이었습니다. 다만 열린 뒤에는 닫히지 않았습니다.
드로어 요소에 배선이 끝났다는 표시로 붙여 두는 속성도 찍어 봤습니다. 값은 undefined 였습니다.
이 표시는 초기화 콜백의 맨 끝에서 붙기 때문에, 그 콜백이 끝까지 가지 못했다는 뜻으로 읽었습니다.
세 가지 가설을 차례로 지웠습니다
그러면 틀린 것으로 판명된 가설부터 보겠습니다. 재발했을 때 같은 길을 다시 걷지 않으려고 이 부분을 가장 공들여 적어 두었습니다.
첫째는 응답이 중간에 잘렸다는 가설이었습니다. 화면에 심어 둔 데이터 배열을 찍어 보니 11777건이 온전히 들어와 있어서 지웠습니다.
둘째는 그리드 라이브러리의 생성 함수가 버전업으로 없어졌다는 가설이었습니다. 옛 이름과 새 이름을 typeof 로 찍어 보니 둘 다 function 이라 지웠습니다.
셋째는 건수 제한을 풀어 둔 설정 때문에 데이터가 너무 많아졌다는 가설이었습니다. 증상과 연결되는 고리가 없어서 지웠습니다.
정상인 환경은 배치 로그가 50건이었고 문제가 난 환경은 10000건이 넘었기 때문에 데이터 양이 계속 눈에 밟혔습니다. 그런데 같은 11777건으로 그리드 생성 함수를 콘솔에서 돌려 보니 오류 없이 그려졌습니다.
의심은 갔지만 입증은 못 했으니, 기록에도 입증되지 않았다고만 적었습니다.
콜백이 아예 시작되지 않았을 가능성이 남았습니다
드로어 배선과 행 클릭 배선은 같은 초기화 콜백 안에 있었고, 그 앞에는 그리드 생성 하나만 있었습니다.
APP.onReady(function () {
APP.grid.create('historyGrid', columns, rows);
grid.onRowClicked = openDetail;
wireDrawer();
});
그리드 생성은 손으로 돌렸을 때 멀쩡했습니다. 그러면 콜백 중간에서 죽었다기보다, 콜백이 처음부터 돌지 않았다는 쪽이 더 설명이 잘 됩니다.
가장 그럴듯한 후보는 웹서버 정적 폴더에 드로어로 바꾸기 전의 옛 JS 파일이 남아 있었다는 것입니다.
화면 템플릿은 새 버전이라 드로어 요소는 있고, 공통 드로어 스크립트도 새 버전이라 손으로 부르면 열리고, 화면 전용 JS만 옛 버전이라 배선이 없는 조합입니다. 관측과 빈틈없이 맞아떨어지기 때문에 유력하다고 봤습니다.
문제는 이걸 확인하기 전에 증상이 사라졌다는 점입니다. 정적 파일 전송이 늦게 끝났거나 부분 전송이었던 것도 같은 계열의 후보로 적어 두었습니다.
⚠️ 원인은 끝내 확정하지 못했습니다. 아래 내용은 "이렇게 고쳤다" 가 아니라 "다음에 이것부터 보겠다" 입니다.
"오류 없음" 은 "정상" 이 아니었습니다
원인과 별개로 이번에 드러난 약점이 두 가지 있었습니다.
하나는 그리드 생성 함수의 조용한 실패 경로입니다. 대상 요소가 없거나 라이브러리가 안 올라왔을 때 예외 대신 일반 로그 한 줄을 남기고 빠져나오게 되어 있었습니다.
그러니 빨간 오류가 없다는 사실만으로는 아무것도 증명되지 않았습니다.
다른 하나는 배선 순서입니다. 드로어는 그리드에 의존하지 않는데, 그리드 생성 뒤에 놓여 있어서 그리드가 죽으면 닫기 배선까지 함께 사라지는 구조였습니다.
그래서 원인과 무관하게 유효한 수정 두 가지를 넣었습니다. 드로어 배선을 그리드 생성 앞으로 옮겼고, 그리드 유틸은 새 생성 함수와 옛 생성 함수를 차례로 시도하고 둘 다 없으면 로그를 남기게 했습니다.
이 수정은 증상이 사라진 시점에 아직 배포 전이었습니다. 그래서 이 수정 덕분에 나았다고 말할 수는 없습니다.
재발하면 제가 이 순서로 보겠습니다
1. 서버에 올라가 있는 화면 JS 파일을 브라우저 주소창으로 열고, wireDrawer 문자열이 들어 있는지부터 봅니다. 이번에 못 한 확인이라 맨 앞에 둡니다.
2. 개발자도구를 먼저 열어 둔 채 새로고침합니다. 나중에 열면 로드 시점의 콘솔이 사라지기 때문입니다.
3. 콘솔에서 빨간 오류만 찾지 않고 일반 로그까지 읽습니다.
4. 반증된 가설(응답 잘림, 생성 함수 제거, 건수 제한 해제)은 다시 세우지 않습니다.
5. 서로 의존하지 않는 초기화 배선은 순서로 묶지 않습니다. 앞이 죽으면 뒤가 통째로 사라지기 때문입니다.
6. 원인을 못 찾은 버그는 관측, 반증, 남은 후보, 다음 확인법 네 칸으로 나눠 적습니다.
저절로 나은 버그는 닫고 싶어지지만, 저라면 원인 미확정이라고 적어 둔 채 열어 두겠습니다. 다음에 재발했을 때 헤매는 시간을 줄여 주는 건 그 기록이기 때문입니다.
혹시 지금 "어느새 괜찮아진" 버그가 하나 있다면, 잊기 전에 남은 후보와 확인법 한 줄씩만 적어 두시는 건 어떨까요?
그러면 오늘도 모두 스테이블 하세요.
만든 것들
'Coding, Testing, Challenge' 카테고리의 다른 글
| AI 대화 기록에 비밀번호·키 144개가 남아 있었다, 바이브코딩 전에 할 보안 점검 (0) | 2026.10.08 |
|---|---|
| Claude Code 메모리 파일이 24KB를 넘으면 생기는 일과 해결법 (0) | 2026.10.07 |
| 롤백 가드를 만들었는데 DDL 에서는 무의미했습니다 (0) | 2026.10.06 |
| 미니앱 번들 3,072KB 상한 맞추기, 한 줄로 앱당 1MB를 덜어냈습니다 (0) | 2026.10.05 |
| Claude Code 메모리 정리법, "기억해"와 "허브에 저장"과 "백로그로"를 나눈 이유 (0) | 2026.10.04 |