본문 바로가기
DEV/FE

[why] JavaScript는 왜 undefined를 사용할까?

by krokerdile 2024. 10. 26.

개요

JavaScript 개발을 하다 보면 자주 마주치는 값이 있습니다. 바로 undefined입니다. 변수를 선언만 하고 값을 할당하지 않았을 때, 함수가 반환값 없이 실행을 마쳤을 때, 객체의 존재하지 않는 속성에 접근할 때 등 다양한 상황에서 만나게 되죠. 하지만 왜 JavaScript는 이런 상황에서 undefined라는 특별한 값을 사용하기로 했을까요?

역사적 배경

JavaScript가 처음 만들어진 1995년, Brendan Eich는 10일 만에 이 언어의 첫 버전을 완성해야 했습니다. 이미 잘 알려져 있겠지만 1995년 5월, 그는 '자바와 비슷해야 하며, 넷스케이프 브라우저 내의 거의 모든 것을 제어할 수 있어야 한다'는 명령하에 열흘 만에 Javascript를 만들었다고 합니다.

흥미로운 점은 JavaScript가 nullundefined 두 개의 "값이 없음"을 나타내는 상태를 가지게 된 것인데, 이는 현재 많은 개발자들에 의해 설계 실수로 간주되고 있습니다. 당시 새로운 스크립트 언어의 개발이 브라우저 개발에서 그렇게 우선순위가 높은 작업도 아니었기 때문에 시간도 많이 주어지지 않았은 만큼 당연히 실수도 많았고 날림으로 개발된 부분도 많았다고 합니다. Eich 역시 이후 인터뷰에서 이를 언어 설계의 실수 중 하나로 인정했다고 합니다.(트위터 참고)

타입 시스템의 특수성

JavaScript는 Java처럼 원시 타입(primitives)과 객체(objects)를 구분했지만, 한 가지 중요한 차이가 있었습니다. Java에서는 변수가 선언될 때 타입이 고정되는 반면, JavaScript의 변수는 어떤 타입의 값이든 자유롭게 담을 수 있었죠. 이런 동적 타입 시스템에서는 "원시 타입도 아니고 객체도 아닌" 특별한 상태를 나타내는 값이 필요했습니다.

null과의 차별화

undefined의 도입에는 null과의 차별화가 중요한 고려사항이었습니다:

  1. null의 특수성: null은 이미 "객체가 아님"을 나타내는 특별한 값으로 존재했습니다. typeof null"object"를 반환하는 것은 JavaScript의 첫 버전부터 존재했던 오류입니다.
  2. C 언어의 영향: null은 C 언어의 영향으로 숫자 연산에서 0으로 자동 변환되는 특성을 가지고 있었습니다.
console.log(null * 5);        // 0
console.log(undefined * 5);   // NaN
console.log(typeof null);     // "object"
console.log(typeof undefined); // "undefined"

// undefined는 전역 객체의 속성
console.log(window.undefined); // undefined
console.log(globalThis.undefined); // undefined

브라우저에서 실제로 실행해본 모습

예외 처리의 부재와 브라우저 환경에서의 안정성

JavaScript의 초기 버전에는 현대적인 예외 처리 메커니즘(try-catch)이 없었습니다. 더구나 웹 브라우저라는 특수한 환경에서는 사소한 에러로 인해 전체 페이지가 작동을 멈추는 것을 방지해야 했습니다. undefined는 이러한 "조용한 실패(fails silently)" 전략의 중요한 부분이었습니다.

기술적 특징

undefined는 JavaScript에서 독특한 위치를 차지합니다:

  1. 전역 객체의 속성: undefined는 전역 객체(브라우저의 window 또는 Node.js의 global)의 속성입니다. 하지만 ES5부터는 이 속성이 수정불가능(non-writable)하게 변경되었습니다.
  2. 원시값: undefined는 JavaScript의 7가지 원시 타입 중 하나입니다.
  3. 자동 할당: 다음과 같은 상황에서 자동으로 할당됩니다:
// 1. 변수 선언만 하고 초기화하지 않은 경우
let variable;
console.log(variable); // undefined

// 2. 반환값이 없는 함수의 실행 결과
function noReturn() {
  console.log("Hello");
}
console.log(noReturn()); // undefined

// 3. 존재하지 않는 객체 속성에 접근할 때
const obj = {x: 1};
console.log(obj.y); // undefined

// 4. 함수 파라미터가 전달되지 않았을 때
function greet(name) {
  console.log(name);
}
greet(); // undefined

null과 undefined의 주요 차이점

  1. 의미론적 차이:
    • null: 의도적으로 값이 없음을 나타내는 상태
    • undefined: 값이 할당되지 않은 상태
// JSON 직렬화 시 동작:
const obj = { a: undefined, b: null }; 
console.log(JSON.stringify(obj)); // {"b":null}

//타입 비교:
console.log(typeof null); // "object" (언어의 오류) 
console.log(typeof undefined); // "undefined"

 

현대적 처리 방식

최신 JavaScript와 TypeScript에서는 undefinednull을 더 우아하게 처리할 수 있습니다:

  1. Optional Chaining:
    const user = { profile: { name: "John" } }; 
    // 현대적인 방식 
    const name = user?.profile?.name;
  2. Nullish Coalescing:
    const value = undefined ?? "default"; 
    console.log(value); // "default"
  3. TypeScript의 Strict Null Checks:
    function process(value: string | undefined) { 
        if (value === undefined) { 
            return "No value provided"; 
        } 
           return value.toUpperCase(); 
    }

미래 전망

TypeScript의 영향으로 undefined 처리는 더욱 엄격해지고 있습니다. 특히 "엄격한 null 검사" 옵션은 많은 잠재적 오류를 컴파일 시점에 잡아낼 수 있게 해줍니다:

// 엄격한 null 검사를 적용한 경우
function processUser(user: User | undefined) {
    // 컴파일러가 undefined 체크를 강제
    if (user === undefined) {
        return "사용자 정보가 없습니다";
    }
    return user.name; // 안전하게 접근 가능
}

마무리

JavaScript의 undefined는 언어 설계 초기의 결정이 현재까지 이어져 온 재밌는 경우인 것 같습니다. 물론 두 개의 "값 없음" 상태를 가진 것은 논란의 여지가 있지만, 오히려 브라우저 환경에서의 안정성 확보에 큰 역할을 했으며, 이는 JavaScript가 웹의 주요 프로그래밍 언어로 성장하는 데 중요한 요소가 되었습니다.

생각해보면 좋을 점

  • 여러분은 nullundefined를 어떤 기준으로 구분해서 사용하시나요?
  • TypeScript의 엄격한 null 검사가 실제 개발에서 얼마나 도움이 되나요?
  • 다른 언어들의 "값이 없음" 표현 방식과 비교했을 때, JavaScript의 접근 방식은 어떨까요?

참고자료

  1. MDN Web Docs - undefined
  2. 2ality - undefined vs. null revisited
  3. TypeScript Handbook - Strict Null Checks
  4. JavaScript Info - Nullish coalescing operator '??'
  5. web.dev - Optional chaining
  6. ECMAScript® 2023 Language Specification
  7. JavaScript: The Definitive Guide, 7th Edition
  8. You Don't Know JS Yet: Types & Grammar
  9. JS의 소리를 찾아서
  10. JS는 왜 그모양일까?