JavaScript 전역 함수 —
eval · parseInt · isNaN 완전 정리
아래 코드는 자바스크립트의 대표적인 전역 함수(Global Function) 세 개를 한 번에 보여준다. 계산식이 담긴 문자열을 실제로 실행하는 eval(), 문자열을 정수로 바꾸는 parseInt(), 그리고 값이 "숫자가 아님(NaN)"인지 확인하는 isNaN()이다. 세 함수는 서로 다른 일을 하지만, 실무에서는 "문자열로 들어온 값을 안전하게 숫자로 다루기"라는 하나의 흐름으로 자주 함께 쓰인다.
eval(), parseInt(), isNaN()
eval("2*3+4*6")는 30
parseInt("32")는 32
parseInt("0x32")는 50
hello는 숫자가 아닙니다.
자바스크립트의 함수는 보통 특정 객체에 속한다. 예를 들어 document.write()는 document 객체의 함수이고, Math.round()는 Math 객체의 함수다. 하지만 eval(), parseInt(), isNaN()은 다르다. 이 셋은 어떤 객체에도 속하지 않고 코드 어디서든 그냥 이름만 써서 호출할 수 있다. 그래서 "전역 함수"라고 부른다.
window.parseInt(...)처럼 써도 동작하는 이유가 여기 있다. 사실 브라우저에서는 이 전역 함수들이 window 객체의 프로퍼티로 등록되어 있어서, window.를 생략해도 자동으로 찾아준다.보통 자바스크립트 코드는 미리 작성되어 있고, 브라우저가 그 코드를 그대로 해석해서 실행한다. 그런데 만약 계산식 자체가 문자열 형태로 나중에 만들어진다면? 예를 들어 사용자가 입력한 "2*3+4*6"이라는 텍스트를 실제 수식으로 계산하고 싶을 때, eval()은 그 문자열을 "코드처럼" 실행해서 결과를 돌려준다. 이번 코드의 eval("2*3+4*6")은 2×3=6, 4×6=24를 계산해 6+24=30을 반환한다.
eval()은 문자열을 "무엇이든" 코드로 실행한다. 문제는 그 문자열이 외부(사용자 입력, 서버 응답 등)에서 온 것이라면, 계산식이 아니라 악의적인 코드가 들어있어도 그대로 실행되어 버린다는 점이다. 예를 들어 사용자가 계산식 대신 쿠키를 훔치는 코드를 입력하면 eval()은 그것도 똑같이 실행한다. 그래서 "eval is evil"이라는 말이 있을 정도로 보안 교육에서 반복적으로 경고하는 함수다.
eval() 대신 안전한 수식 파서 라이브러리를 쓰거나, 애초에 자유 형식 수식 입력을 허용하지 않는 방식을 택한다. 학습용 예제가 아니라면 eval()은 최후의 수단으로만 고려한다.
HTML 폼 입력값, JSON 응답, URL 파라미터 등은 겉보기에 숫자 같아도 자바스크립트 내부에서는 문자열(string) 타입으로 들어온다. 문자열 "32"는 계산에 바로 쓸 수 없다. parseInt()는 문자열의 앞부분부터 문자를 하나씩 읽어가며 숫자로 해석 가능한 부분까지만 잘라내 정수로 바꿔준다. parseInt("32")는 문자 "3", "2"를 모두 숫자로 읽을 수 있으므로 정수 32가 된다.
이번 코드에서 가장 헷갈리기 쉬운 부분이다. parseInt("0x32")의 결과는 32가 아니라 50이다. 이유는 parseInt()가 문자열 맨 앞의 0x(또는 0X)를 "이 뒤에 오는 숫자는 16진수(hexadecimal)다"라는 신호로 자동 인식하기 때문이다. 16진수 32를 10진수로 바꾸면 3×16 + 2 = 50이 된다.
parseInt(str, 10)처럼 두 번째 인자로 진법을 명시하면 자동 판단에 의존하지 않는다- "0x" 접두어가 우연히 섞여 있어도 10진수로 강제할 수 있어 예상치 못한 값을 막는다
- 진법을 생략하면 브라우저가 문자열 앞부분을 보고 10진수·16진수를 스스로 추측한다 — 이게 바로 위 헷갈림의 원인
parseInt("hello")처럼 문자열의 맨 첫 글자부터 숫자로 해석할 수 없는 경우, parseInt()는 변환할 것이 하나도 없다고 판단하고 특수한 값을 반환한다. 이 값이 바로 NaN이다. "h"는 숫자가 아니므로 parseInt는 단 한 글자도 읽지 못하고 실패를 알리는 것이다.
NaN은 "Not a Number"의 약자로, 수학적으로 계산이 불가능하거나 의미 없는 연산 결과를 나타내는 특수 값이다. 재미있게도 자바스크립트에서 typeof NaN은 "number"다. 즉 NaN은 숫자 타입에 속하지만 "정상적인 숫자값이 아님"을 뜻하는 값이다. 0/0, parseInt("hello"), "abc" - 1 같은 연산은 모두 NaN을 만든다.
NaN === NaN은 false다. NaN은 세상에서 유일하게 "자기 자신과도 같지 않은" 값이다. 그래서 if (n === NaN)으로는 절대 NaN을 걸러낼 수 없고, 반드시 전용 함수가 필요하다.NaN은 ===로 비교할 수 없으므로, 자바스크립트는 값이 NaN인지 검사하는 전용 전역 함수 isNaN()을 제공한다. 인자로 넘긴 값이 NaN이면 true, 정상적인 숫자면 false를 반환한다. 이번 코드는 n = parseInt("hello")로 n이 NaN이 된 뒤, if(isNaN(n))으로 이를 확인하고 "hello는 숫자가 아닙니다."라는 메시지를 출력한다.
- 폼 입력값을
parseInt()로 변환한 뒤isNaN()으로 검증하는 흐름이 매우 흔하다 - 사용자가 숫자 대신 문자를 입력했을 때 이 패턴으로 즉시 걸러낼 수 있다
- 최신 코드에서는 더 엄격한
Number.isNaN()을 쓰기도 한다(형변환 없이 순수 NaN만 검사)
parseInt()는 문자열의 앞부분만 읽고 숫자가 아닌 부분이 나오면 거기서 멈춘다. 반면 Number()는 문자열 전체가 완전히 숫자여야만 변환에 성공하고, 조금이라도 이상한 문자가 섞이면 곧바로 NaN을 반환한다. 이 차이 때문에 "123px" 같은 값을 다룰 때 결과가 완전히 달라진다.
결과: 123
결과: NaN
CSS 픽셀 값("120px")처럼 숫자 뒤에 단위가 붙는 값을 정수만 뽑아 쓰고 싶다면 parseInt()가 적합하고, 입력값이 정확히 숫자 형식인지 통째로 검증하고 싶다면 Number()가 더 알맞다.
| 실수 | 증상 | 해결 |
|---|---|---|
사용자 입력을 그대로 eval()에 전달 |
악성 스크립트가 그대로 실행되는 보안 취약점 발생 | 외부 입력에는 eval() 대신 안전한 파서·검증 로직 사용 |
parseInt(str)에서 진법 생략 |
"0"으로 시작하는 값 등에서 의도치 않은 진법으로 해석 | parseInt(str, 10)처럼 진법을 항상 명시 |
if (n === NaN)으로 NaN 검사 |
NaN은 자기 자신과도 다르다고 판단되어 항상 false | isNaN(n) 또는 Number.isNaN(n) 사용 |
parseInt("08")을 8진수로 착각 |
구형 브라우저에서 접두어 없는 0 시작 문자열을 8진수로 오해 | 최신 표준은 10진수로 처리하지만, 혼동을 막으려면 진법을 직접 지정 |
Number()와 parseInt()를 같은 용도로 혼용 |
"120px" 같은 값에서 하나는 120, 하나는 NaN이 나와 버그 발생 | 단위 섞인 값은 parseInt, 순수 숫자 검증은 Number로 용도 구분 |
핵심 한 줄 요약
Tags
'php' 카테고리의 다른 글
| JavaScript 배열 — [] 리터럴과 인덱스 완전 정리 (0) | 2026.07.03 |
|---|---|
| JavaScript 객체 생성 — new Date · String · Array 완전 정리 (0) | 2026.07.03 |
| JavaScript 함수 — 선언·파라미터·return 완전 정리 (0) | 2026.07.03 |
| JavaScript break · continue — 반복 제어 완전 정리 (0) | 2026.07.03 |
| JavaScript switch — 커피 주문 완전 정리 (0) | 2026.07.03 |
왕진 블로그

댓글