TypeScript - null과 undefined 비교

안녕하세요, 야심찬 프로그래머 여러분! 오늘은 초보자들이 자주 혼동하는 흥미로운 주제에 대해 깊이 다룰 것입니다: TypeScript에서 nullundefined의 차이입니다. 혼란스러워할 필요는 없습니다 - 저도 처음 이 개념을 접했을 때는 머리를 긁적이기도 했지만! 이 강의가 끝나면 이 두 특별한 값을 구분하는에 있어 프로가 될 것입니다. 시작해보겠습니다!

TypeScript - null vs. undefined

null이란?

TypeScript(그리고 JavaScript)에서 null은 어떤 객체 값이 의도적으로 존재하지 않음을 나타내는 특별한 값입니다. 이는 "여기에 무언가가 있어야 하지만, 지금은 아무것도 없다"고 말하는 것과 같습니다.

이를 더 잘 이해하기 위해 몇 가지 예를 보겠습니다:

let myPet: string | null = null;
console.log(myPet); // 출력: null

// 코드 후반부...
myPet = "Fluffy";
console.log(myPet); // 출력: Fluffy

이 예제에서 우리는 myPet이라는 변수를 문자열이나 null로 선언합니다. 처음에는 null로 설정하여 아직 동물을 가지지 않았음을 나타냅니다. 나중에 동물을 얻으면 "Fluffy"라는 이름을 myPet에 할당합니다.

다른 예제를 보겠습니다:

function findUser(id: number): { name: string } | null {
// 데이터베이스를 검색하는 것을 상상해봅시다
if (id === 1) {
return { name: "Alice" };
} else {
return null;
}
}

let user = findUser(1);
console.log(user); // 출력: { name: "Alice" }

user = findUser(2);
console.log(user); // 출력: null

이 경우, findUser 함수는 사용자 객체를 반환하거나 사용자가 찾이지 않으면 null을 반환합니다. 이는 프로그래밍에서 흔히 사용되는 패턴입니다 - null을 사용하여 검색이나 연산이 결과를 내지 못 했음을 나타냅니다.

undefined는 무엇인가?

이제 undefined에 대해 이야기해보겠습니다. 이 특별한 값은 선언된 변수가 아직 값을 할당받지 않았음을 나타냅니다. 비어 있는 상자처럼 - 존재는 하지만 아직 내용이 없습니다.

다음 예제를 통해 undefined를 설명해보겠습니다:

let myName: string;
console.log(myName); // 출력: undefined

// 코드 후반부...
myName = "John";
console.log(myName); // 출력: John

function greet(name?: string) {
console.log(name);
}

greet(); // 출력: undefined
greet("Alice"); // 출력: Alice

처음에 myName을 선언하지만 값을 할당하지 않습니다. TypeScript는 자동으로 undefined 값을 부여합니다. 나중에 값을 할당하면 더 이상 undefined가 아닙니다.

greet 함수에서는 선택적 매개변수를 사용합니다. 매개변수를 제공하지 않고 함수를 호출하면 name 매개변수는 undefined가 됩니다.

다른 상황에서 undefined를 만날 수 있는 예제입니다:

let person = {
name: "Bob",
age: 30
};

console.log(person.name); // 출력: Bob
console.log(person.job); // 출력: undefined

이 경우 person.jobundefined입니다. person 객체에 job 속성을 정의하지 않았기 때문입니다.

Null과 Undefined: 중요한 차이

이제 nullundefined를 각각 탐구했으므로, 그 차이를 비교하여 더 잘 이해해보겠습니다.

요소 null undefined
의미 어떤 객체 값이 의도적으로 존재하지 않음 변수가 선언되었지만 값이 할당되지 않음
타입 객체 정의되지 않음
JSON 유효 무효
기본 함수 매개변수 기본적으로 사용되지 않음 선택적 매개변수에 대해 사용됨
동등성 비교 null == undefined (참), null === undefined (거짓) undefined == null (참), undefined === null (거짓)

다음 코드 예제를 통해 이 차이를 설명해보겠습니다:

// 타입 검사
console.log(typeof null);       // 출력: "object"
console.log(typeof undefined);  // 출력: "undefined"

// JSON 시리얼라이제이션
console.log(JSON.stringify({ a: null }));     // 출력: {"a":null}
console.log(JSON.stringify({ a: undefined })); // 출력: {}

// 기본 함수 매개변수
function sayHello(name: string = "World") {
console.log(`Hello, ${name}!`);
}

sayHello();        // 출력: Hello, World!
sayHello(undefined); // 출력: Hello, World!
sayHello(null);    // 출력: Hello, null!

// 동등성
console.log(null == undefined);  // 출력: true
console.log(null === undefined); // 출력: false

실제로 nullundefined 사이의 선택은 개인이나 팀의 선호도에 따라 다릅니다. 그러나 차이를 이해하면 더 정확하고 버그가 적은 코드를 작성하는 데 도움이 됩니다.

마지막 예제를 통해 모든 것을 연결해보겠습니다:

function processUser(user: { name: string, age?: number } | null | undefined) {
if (user === null) {
console.log("User explicitly set to null");
} else if (user === undefined) {
console.log("User not provided");
} else {
console.log(`Processing user: ${user.name}, Age: ${user.age ?? "Unknown"}`);
}
}

processUser(null);                    // 출력: User explicitly set to null
processUser(undefined);               // 출력: User not provided
processUser({ name: "Alice" });       // 출력: Processing user: Alice, Age: Unknown
processUser({ name: "Bob", age: 30 }); // 출력: Processing user: Bob, Age: 30

이 함수는 null, undefined, 그리고 유효한 사용자 객체를 다르게 처리하는 실제 상황을 보여줍니다.

이제 TypeScript에서 nullundefined에 대해 배웠습니다. 연습이 완성입니다. 따라서 이 개념들을 자신의 코드에서 실험해보세요. 행복한 코딩을 기원하며, 변수들이 항상 의도적으로 null이나 undefined가 되길 바랍니다!

Credits: Image by storyset