스타일시트 경계값·null 입력 버그 수정
목차
스타일시트 쪽 버그 수정 작업을 마무리했다. 6개 파일, 수정 영역은 stylesheet 전반, 주요 케이스는 null 입력과 경계값이었음.
처음엔 재현이 잘 안 됐다. 정상 케이스로 돌리면 문제가 없고, QA 환경에서도 안 터지고. 그러다 보니 "그냥 가끔 이상한 거 아닌가" 하고 넘기고 싶은 충동이 생기는데, 그게 가장 위험한 타이밍이다. 간헐적으로 보이는 버그일수록 대개 명확한 조건이 있고, 조건을 못 찾은 것뿐이다.
결국 재현 조건을 세 가지로 좁혔다.
재현 조건:
1. 특정 값이 null 또는 빈 값인 경우
2. 경계값 입력 시 — 0, 음수, 최대값 등 "정상 범위 끝"
3. 타임아웃 상황에서의 상태 불일치
세 번째가 좀 까다로웠다. 타임아웃은 로컬에서 재현하기가 번거롭고, 상태 불일치는 타이밍 이슈처럼 보여서 처음엔 레이스 컨디션을 의심했다. 근데 코드 추적해보니 레이스가 아니라 null 체크가 누락된 상태에서 잘못된 기본값이 세팅되고, 거기에 타임아웃이 겹치니까 엉뚱한 상태로 굳어버리는 흐름이었음. 어느 한쪽만 고쳐도 증상이 줄어드는 것처럼 보이지만 두 원인이 독립적으로 존재하기 때문에, 둘 다 안 잡으면 다른 경로로 다시 터진다.
수정 방향
null-safe 처리는 개념은 단순한데 실제로 코드베이스 전체에 일관되게 적용하는 게 생각보다 번거롭다. 특히 스타일시트처럼 여러 컴포넌트가 공유하는 영역은 한 곳에서 값을 만들고 다른 곳에서 소비하는 흐름이 길어서, 중간에 null이 유입되면 터지는 지점이 발생 지점과 멀리 떨어져 있는 경우가 많다.
이번에 적용한 패턴은 대략 이렇다.
// 수정 전 — null이 내려와도 기본값 처리 없이 그냥 사용
function applyStyle(value) {
return computeStyle(value); // value === null이면 내부에서 예외 or 이상한 fallback
}
// 수정 후 — 입력 진입 시점에서 방어
function applyStyle(value) {
if (value == null || value === '') return DEFAULT_STYLE;
const clamped = Math.max(0, Math.min(value, MAX_VALUE)); // 경계값 클램핑
return computeStyle(clamped);
}
경계값 클램핑은 "그냥 막는다"는 느낌이 있어서 처음엔 조심스러웠는데, 스타일시트 맥락에서는 0 미만이나 최대값 초과 자체가 의미 없는 입력이라 명시적으로 잘라내는 게 맞다. 허용 범위 밖이면 예외를 던지는 방식도 있지만, 그렇게 하면 호출 측에서 전부 try-catch를 감싸야 해서 코드가 더 지저분해짐. 방어 코드로 흡수하되 로그를 남기는 쪽이 현실적이었다.
| 항목 | 내용 |
|---|---|
| 수정 파일 | 6개 |
| 주요 영역 | 스타일시트 |
| 발생 조건 | 경계값 / null 입력 / 타임아웃 상태 불일치 |
| 수정 방식 | 방어 코드 + null-safe 처리 + 로그 보강 |
| 추가 검토 | 유사 패턴 다른 파일 동시 점검 |
로그 보강도 이번에 같이 넣었다. null이 들어왔을 때 조용히 기본값으로 처리하면 나중에 "왜 이 값이 이렇게 렌더링됐지?"를 추적할 방법이 없어진다. 최소한 [WARN] null value received at applyStyle, falling back to DEFAULT 수준의 로그는 있어야 디버깅할 때 데이터 흐름을 따라갈 수 있음.
수정 후 동일 조건으로 재테스트했고, 유사한 패턴이 있는 다른 코드도 같이 점검했다. 이 부분은 좀 귀찮더라도 해두는 게 맞다. 같은 실수가 여러 곳에 있으면 고친 의미가 없고, 팀 차원에서 보면 리뷰어가 한 파일에서 잡은 패턴을 다른 파일에서 그냥 지나친 것도 기술 부채가 쌓이는 경로다.
디버깅 과정에서 다시 확인한 것들
원인을 잘못 짚어서 관계없는 코드를 한참 들여다보는 시간이 있었다. 레이스 컨디션이라고 의심하고 비동기 흐름을 한 30분 파고들었는데, 결국 로그로 돌아와서 입출력 값을 직접 찍어보고 나서야 null이 문제라는 걸 확인했음.
디버깅할 때 자꾸 잊어버리는 순서가 있다.
- 로그·스택 트레이스부터 — 코드 보기 전에 실제 입출력 값을 확인
- 재현 조건 명확화 — "가끔 터진다"는 가설을 버리고 조건을 확정
- 이진 탐색으로 범위 좁히기 — 어느 레이어에서 값이 깨지는지
- 가정을 코드로 검증 — "아마 이렇겠지"가 아니라 실제로 찍어보기
이 순서를 지키면 잘못된 방향으로 30분 날리는 일이 줄어든다. 알고 있어도 막상 급하면 코드부터 열어보게 되는데, 그게 함정이다. FAQ 스타일 파일도 이번 수정 과정에서 불필요해진 부분이 확인돼서 같이 제거했다. 쓰이지 않는 파일이 코드베이스에 남아있으면 나중에 "이게 왜 있지?" 하고 분석하는 비용이 생기니까, 확인된 시점에 바로 지우는 게 낫다.
댓글 0
첫 댓글 달아줘.