안녕하세요 웹 YB 김다현입니다.
개발을 하다 보면 NaN이라는 친구를 마주칠 때가 있는데요. 보통 숫자를 다룰 때 등장하지만 진짜 숫자처럼 다루면 곤혹을,,, 치룰 수도 있는 함정 같은 친구랍니다. 코드가 의도치 않게 NaN을 반환하거나, NaN을 제대로 처리하지 않으면 예상치 못한 오류가 발생할 수 있어요. 이번 기회에 NaN의 개념을 확실히 이해하고 미리 실수를 방지해볼까요?
🔎 그래서 NaN이 뭔데?
자바스크립트로 개발을 하다 보면 숫자가 있어야 할 자리에 뜬금없이 NaN이라는 값이 튀어나올 때가 있는데요. NaN은 "Not-a-Number"의 약자로, 말 그대로 숫자가 아니라는 의미랍니다. 자바스크립트는 주로 숫자를 다루는 계산이 이상하게 꼬였을 때 NaN을 반환해요.
예를 들어, 숫자가 아닌 값을 숫자로 나누거나 제곱근을 구하는 등 말이 안 되는 연산을 할 때 NaN이 등장합니다.
console.log(0 / 0); // NaN
console.log(Math.sqrt(-1)); // NaN
console.log("hello" - 3); // NaN
위 코드를 보면 0 / 0 이나 음수의 제곱근을 구하려고 할 때 NaN이 반환되는 걸 볼 수 있어요. 이런 계산은 논리적으로 성립하지 않기 때문에 자바스크립트가 "이건 숫자가 아니야" 라는 의미로 NaN을 돌려줘요.
🪄 NaN의 독특한 성질
NaN에는 다른 숫자와 구별되는 독특한 점이 하나 있는데요. 바로 NaN은 자기 자신과도 같지 않다는 거예요. 이게 무슨 뜻이지? 싶으실 것 같아 코드로 설명해볼게요.
console.log(NaN === NaN); // false
다른 값들은 대부분 자기 자신과 같지만 NaN은 유일하게 NaN === NaN에서 false를 반환한답니다. 자바스크립트에서 NaN은 어떤 값과도 같지 않다고 판단해요. 심지어 자기 자신과도,,, ^^ 그래서 NaN이 코드에 있을 때 이를 감지하는 게 살짝 까다로울 수 있어요.
왜 그럴까요? 그건 바로 자바스크립트는 NaN을 "이건 확실히 숫자가 아니야" 라고 인식하고, 어떤 숫자와도 비교하지 않으려고 하기 때문이에요.
😵💫 그럼 어떻게 확인해?
다행히 자바스크립트에는 NaN을 감지하기 위한 함수들이 있어요. 근데 NaN을 감지할 때 사용하는 함수도 종류가 여러 가지라서 헷갈리기 쉬워요. (가지가지...) 그럼 하나씩 설명해볼게요!
isNaN() 함수
이 함수는 값이 NaN인지 확인하는 기본적인 방법이에요. 하지만, isNaN()은 쓰면서도 조심해야 하는 함수예요. 왜냐하면, 숫자가 아닌 값에 대해서도 NaN으로 판별할 수 있기 때문에...!
console.log(isNaN("Hello")); // true
console.log(isNaN(123)); // false
console.log(isNaN(NaN)); // true
"Hello" 같은 문자열이 NaN이 아님에도 불구하고 true가 반환되는 걸 볼 수 있어요. isNaN()은 숫자가 아니면 무조건 NaN으로 간주하는 경향이 있어서 정확하게 NaN만 감지하는 데는 적합하다고 볼 수 없어요. (ㅠㅠ)
Number.isNaN() 함수
이 문제를 해결하기 위해 나온 함수가 바로 Number.isNaN()이에요. Number.isNaN()은 정확하게 NaN인 경우에만 true를 반환해요. 즉, 숫자가 아니라고 해서 무조건 NaN으로 간주하지 않아요. 둘을 비교해볼게요.
console.log(isNaN("Hello")); // true
console.log(Number.isNaN("Hello")); // false
console.log(isNaN(NaN)); // true
console.log(Number.isNaN(NaN)); // true
"Hello"에 대해 Number.isNaN()은 false를 반환하는 걸 볼 수 있어요. 정확히 NaN인 경우에만 true를 반환하니까, NaN을 감지할 때는 Number.isNaN()을 사용하는 것이 훨씬 더 안전하겠죠? 😇
🥸 잠깐! 느슨한 비교와 엄격한 비교?
자바스크립트에서는 두 값을 비교할 때 사용할 수 있는 두 가지 연산자가 있는데요. 느슨한 동등 비교(==)와 엄격한 동등 비교(===)가 있어요. 이 두 연산자는 비교할 때 미~묘하게 다른 방식을 사용하는데, 이걸 알아두면 NaN뿐만 아니라 다른 값들을 비교할 때도 실수를 줄일 수 있답니다!
느슨한 비교(==)
==는 느슨한 비교라고 불리고, 서로 다른 타입의 값들도 비교할 수 있도록 타입을 자동으로 변환하려고 해요.
예를 들어, 문자열 "5"와 숫자 5를 느슨하게 비교하면 자바스크립트가 문자열을 숫자로 바꾼 후에! 비교해요.
console.log("5" == 5); // true
console.log(false == 0); // true
이렇게 타입 변환을 해가면서 비교하기 때문에 예상치 못한 결과가 나올 수 있어요. 그렇기 때문에 ==을 사용할 때는 주의하기로 약속,,,
엄격한 비교(===)
이 친구는 엄격한 비교라고 불리고, 타입이 다르면 무조건 false를 반환해요. 타입이 같을 때만 값을 비교하기 때문에 이 방식이 더 안전하다고 볼 수 있답니다.
console.log("5" === 5); // false
console.log(false === 0); // false
갑자기 이 두 친구를 언급한 이유에 대해 더 짚고 넘어가자면, 자바스크립트에서 NaN뿐만 아니라 다른 값들도 비교할 때 혼란스러울 수 있는 상황이 많기 때문이에요. NaN 말고도 타입 비교의 함정 ^^ 에 조심하기 위해 알아두면 좋을 것 같아 같이 설명해봤어요...ㅎㅎ
NaN인지 확인하고 싶을 때는 Number.isNaN()을 사용해야 하는 거 잊지 말기!
🐛 실제 코드에서 어떻게 버그가 발생할까?
실전에서 NaN이 어떻게 예기치 않은 문제를 일으킬 수 있는지 보기 위해 간단한 예제를 가져왔어요.
계산 중간에 NaN이 발생하는 상황을 생각해볼게요. 예를 들어 유저로부터 여러 개의 숫자 입력을 받아 평균을 계산하는 코드가 있다고 가정해 봅시다!
let inputs = ["10", "20", "DahyunKim"];
let sum = 0;
inputs.forEach(input => {
sum += Number(input);
});
let average = sum / inputs.length;
console.log(average);
이 코드에서는 DahyunKim을 숫자로 변환할 때 NaN이 발생하고, 결국 sum에 NaN이 더해지면서 전체 계산이 NaN으로 변질됩니다. 평균을 계산하려 했지만 NaN이 나오고 예상치 못한 결과가 발생하는 이슈가 생겨요. ㅠㅠ
이럴 때는 각 입력 값이 NaN인지 확인한 후에만 더하도록 하면 오류를 방지할 수 있어요.
inputs.forEach(input => {
let num = Number(input);
if (!Number.isNaN(num)) {
sum += num;
}
});
이렇게 하면 정확한 숫자 값만 더하게 되어 NaN이 포함된 오류를 방지할 수 있답니다!
🍯 세 줄 요약이자 NaN을 안전하게 다루기 위한 꿀팁!
- NaN인지 확인할 때는 Number.isNaN()을 사용하기!
isNaN()은 정확히 NaN이 아닌 값들도 true로 판단할 수 있으니 주의 필요 - 비교 연산에서는 ==보다는 ===를 사용하기!
불필요한 타입 변환을 줄여주기 때문에 오류가 줄어들 거예요... - NaN이 발생할 가능성이 있다면 미리 NaN을 감지하고 처리하는 습관 들이기 ^_^
'2주차' 카테고리의 다른 글
[JavaScript] 자바스크립트의 데이터 타입에 대해.araboza (0) | 2024.10.29 |
---|---|
[JS] 스코프(Scope) (0) | 2024.10.29 |
[JS] 자바스크립트 가비지 컬렉션 (GC) (0) | 2024.10.29 |
[JS] localStorage 사용법을 알아보자. (0) | 2024.10.29 |
함수형 프로그래밍 찍먹 (0) | 2024.10.29 |