JS 에서의 NPE (Null Pointer Exception) 가 문제가 되었던 이유
- 타입스크립트 없는 바닐라 JS로 코딩을 하다보니 런타임이 아니면 NPE 를 눈치챌 수 없었다.
- JS 에서 주로 DOM 엘리먼트에 대한 작업을 하는데 대부분 브라우저 내장 API 를 통해 작업이 진행된다.
- 브라우저 내장 API 를 이용하다보니 메서드를 통해 불러오게 된다.
- DOM 을 불러올 때 보통
document.querySelector() 를 이용해 불러왔다.
- 그런데 DOM 은 조건부로 생성되는 경우가 많은데 DOM 이 없는 경우
document.querySelector() 메서드의 결과가 null 을 가리키게 된다.
- 처음엔
null 을 가리킨지 모르고 . 을 통해 메서드를 불러오니 null pointer exception 이 발생한다.
- 그리고 NPE 가 발생하면 이후 코드는 전부 무시된다.
- 코드가 진행되다가 말아서 원치 않았던 결과가 초래되어 매우 이상한 화면이 보여질 때가 있다.
- 이후 콘솔에는 에러 스택 트레이스만 있어서 정확히 어떤게 문제가 됐는지 알기 힘들 때도 있다.
const a = document.querySelector("#notExist");
console.log("sequence1");
console.log("sequence2");
a.style.display = "none";
console.log("sequence3"); // 무시됨
console.log("sequence4"); // 무시됨
console.log("sequence5"); // 무시됨
문제 다시 적기
- 타입 체킹이 없어 런타임에만 NPE 를 확인할 수 있다.
- UI 는 상태가 자주 변해서 조건부로만 NPE 가 발생하기 때문에 더 까다롭다.
- 에러 이후 코드가 무시된다.
- 가끔은 스택 트레이스를 통해 에러 지점도 찾기 힘들다.
문제 해결 방식
. 기호를 쓸 때 && 를 이용해 최대한 안전하게 코딩하자.
. 을 쓸 때마다 객체가 실제로 존재하는지 확인해야 한다.
. 을 써야만 한다면, 항상 프로퍼티를 가져올 대상 객체가 실제로 존재하는지 a && a.prop 과 같은 코드로 확인하자.
document.querySelector() 보다 에러 포인트 지점을 좀 더 쉽게 알 수 있도록 해보자.
selector 를 이용할 때 아래와 같은 함수를 끼워넣어서 내가 어떤 엘리먼트를 찾다가 실패했는지에 대해 조금 더 이해하기 쉽게 만들어봤다.
const validateSelector = (selector) => {
const $elem = $query(selector);
if (!$elem) {
console.warn(`${selector} 엘리먼트가 존재하지 않습니다.`);
return false;
}
return true;
};