Post

JavaScript 안전 운전 매뉴얼 — 언어 함정으로 실무 버그 줄이기

스코프, 호이스팅, 전역 오염, 암묵적 형변환 등 JS 언어 함정으로 생기는 버그를 줄이는 체크리스트

JavaScript 안전 운전 매뉴얼 — 언어 함정으로 실무 버그 줄이기

1) 한 문단 요약 — 이 글이 막아주는 버그 유형 5개

이 글은 스코프 착각, 호이스팅 오해, 전역 오염, 암묵적 형변환, NaN/undefined/null 처리 실수로 발생하는 실무 버그를 줄이기 위한 매뉴얼이다. 각 항목을 함정 → 증상 → 원인 → 해결 패턴으로 반복 학습하도록 구성했으며, PR 전에 바로 점검 가능한 규칙과 체크리스트를 제공한다.


2) 위험지도 — 빈도 높은 함정 TOP 8

함정실무 증상원인권장 패턴금지 패턴
var 사용값이 예기치 않게 바뀜함수 스코프 + 호이스팅let / constvar
암묵적 호이스팅undefined 접근 에러선언/할당 분리선언-사용 거리 최소화선언 위치 무시
전역 변수다른 모듈에서 충돌글로벌 네임스페이스 공유모듈 스코프window 직접 할당
임시변수 남용로직 추적 어려움상태 분산표현식/함수 추출중간 상태 누적
== 비교조건 분기 오류강제 형변환=====
undefined/null 혼용예외 처리 누락의미 구분 없음계약 기반 명시혼용 체크
숫자 형변환NaN 전파입력 검증 부재Number + 검증암묵 변환
isNaN 오용NaN 아닌 값 통과전역 isNaN의 변환Number.isNaNisNaN

3) 핵심 주제별 상세 설명

A. var vs let/const (호이스팅 + 스코프)

Bad

1
2
console.log(count); // undefined
var count = 10;

런타임 원인 var는 선언이 함수 스코프 상단으로 끌어올려지고(undefined로 초기화), 할당은 그대로 남는다.

Better

1
2
console.log(count); // ReferenceError
const count = 10;

이유 TDZ(Temporal Dead Zone)로 인해 잘못된 접근을 즉시 실패시킨다. 버그를 조기에 노출한다.


B. 스코프와 전역 오염의 실제 사례

Bad

1
2
3
function init() {
  config = { mode: 'prod' }; // 암묵적 전역
}

런타임 원인 선언 키워드 누락 → 전역 객체에 바인딩 → 다른 코드와 충돌.

Better

1
2
3
function init() {
  const config = { mode: 'prod' };
}

원칙 전역은 공유 메모리다. 공유 메모리는 충돌을 낳는다.


C. 임시변수 제거가 버그를 줄이는 이유

Bad

1
2
3
4
5
let result;
if (isValid) {
  result = price * tax;
}
return result;

런타임 위험 분기 누락 시 undefined 반환.

Better

1
2
if (!isValid) return 0;
return price * tax;

이유 상태를 저장하지 않고 즉시 계산하면, 누락 가능한 경로가 사라진다.


D. 타입 검사와 비교 (== / ===, undefined / null)

Bad

1
if (value == null) { ... }

런타임 원인 null == undefinedtrue. 의도가 숨겨진다.

Better

1
2
3
if (value === null) { ... }
// 또는
if (value === undefined) { ... }

원칙 undefined는 “없음”, null은 “의도적 비어 있음”. 계약을 구분하라.


E. 형변환, NaN, isNaN

Bad

1
if (isNaN(value)) { ... }

런타임 원인 isNaN은 내부적으로 Number 변환을 수행한다.

1
isNaN('foo') // true

Better

1
if (Number.isNaN(value)) { ... }

추가 패턴

1
2
const num = Number(input);
if (Number.isNaN(num)) throw new Error('Invalid number');

4) 안전 규칙 12개

  1. var를 사용하지 마라
  2. 선언과 사용 거리를 최소화하라
  3. 전역에 쓰지 마라
  4. 임시변수를 의심하라
  5. 비교는 항상 ===
  6. undefinednull을 구분하라
  7. 암묵적 형변환에 기대지 마라
  8. 숫자는 변환 후 검증하라
  9. isNaN 대신 Number.isNaN
  10. 실패 경로를 먼저 처리하라
  11. 런타임 실패를 숨기지 마라
  12. 읽히지 않는 코드는 위험 코드다

5) 미니 퀴즈 6문제

Q1

1
2
console.log(a);
let a = 1;

예측: ? 해설: TDZ → ReferenceError

Q2

1
2
console.log(b);
var b = 1;

해설: undefined (호이스팅)

Q3

1
0 == false

해설: true (형변환)

Q4

1
Number.isNaN('foo')

해설: false (변환 없음)

Q5

1
isNaN('foo')

해설: true (암묵 변환)

Q6

1
2
let x;
x === null

해설: false (undefined)


마무리 — PR 전 실무 체크리스트 15개

  1. var가 있는가
  2. 선언 키워드 누락이 있는가
  3. 전역 접근이 있는가
  4. 임시변수가 상태를 들고 있는가
  5. 조건 분기에 ==가 있는가
  6. 타입 의도가 드러나는가
  7. undefined/null을 혼용했는가
  8. 숫자 입력 검증이 있는가
  9. NaN 전파 가능성이 있는가
  10. 실패 경로가 명시적인가
  11. 런타임 에러를 숨겼는가
  12. 스코프 경계가 명확한가
  13. 코드 순서가 실행 순서와 일치하는가
  14. 읽지 않고도 예측 가능한가
  15. “왜 이렇게 했는지” 설명 가능한가

This post is licensed under CC BY 4.0 by the author.