JavaScript 환경에서 개발하다 보면 null과 undefined는 가장 자주 마주치며, 동시에 가장 많은 오류를 유발합니다. TypeScript는 이 문제를 해결하기 위해 strictNullChecks라는 강력한 옵션을 제공하며, 이를 활성화하느냐에 따라 타입 시스템의 동작 방식이 완전히 달라집니다.
null과 undefined의 차이
✔ undefined
JavaScript에서 값이 “할당되지 않은 상태”를 의미합니다.
let a;
console.log(a); // undefined
변수를 선언만 하고 초기화하지 않으면 자동으로 undefined가 됩니다.
✔ null
의도적으로 “값이 비어있음”을 나타낼 때 사용합니다.
let b = null;
즉, undefined는 시스템이 부여하고, null은 개발자가 명시적으로 할당하는 경우가 많습니다.
strictNullChecks 옵션이란?
TypeScript에서 가장 중요한 옵션 중 하나입니다. 이 옵션을 켜면 null과 undefined가 모든 타입에서 자동으로 허용되지 않습니다.
// strictNullChecks: false (기본)
let name: string = null; // 허용
let age: number = undefined; // 허용
// strictNullChecks: true
let name: string = null; // 오류
let age: number = undefined; // 오류
즉, strictNullChecks는 “null 안전성”을 보장하기 위해 존재합니다. 이 옵션을 켠 순간 TypeScript는 더 이상 null과 undefined를 자동으로 허용하지 않습니다.
strictNullChecks가 켜졌을 때의 동작
1. null/undefined를 허용하려면 명시적으로 타입에 포함해야 함
let username: string | null = null;
let email: string | undefined = undefined;
이는 “nullable한 값”임을 타입 정의에서 명확하게 알리는 패턴입니다.
2. 값 사용 전 반드시 null 체크 필요
function printLength(str: string | null) {
if (str !== null) {
console.log(str.length);
}
}
이제 TypeScript가 null 가능성을 인지하기 때문에 런타임 오류를 크게 줄일 수 있습니다.
Non-null Assertion Operator ( ! )
“이 값은 절대 null이 아니다”라는 뜻으로 null 가능성 체크를 무시하는 연산자입니다.
let el = document.getElementById("app")!;
el.innerHTML = "Hello";
하지만 남용은 매우 위험합니다. strictNullChecks를 켠 의미가 사라질 수 있기 때문에 정말 확실할 때만 사용해야 합니다.
Optional Chaining (?.)
null/undefined가 발생할 가능성이 있는 값을 안전하게 접근할 수 있는 문법입니다.
user?.profile?.email
이 문법은 null-safe 코드를 작성할 때 필수입니다.
Nullish Coalescing (??)
null 또는 undefined일 때만 기본값을 사용하도록 도와줍니다.
let nickname = input ?? "Guest";
빈 문자열("")이나 0은 그대로 유지되기 때문에 기존의 || 연산자보다 더 안전합니다.
strictNullChecks를 반드시 켜야 하는 이유
- 런타임 오류의 80%가 null/undefined 관련 오류
- null 가능성을 타입에서 명확하게 표현할 수 있음
- 도구(IDE, LSP)가 null-safe 코드를 자동으로 유도
- 함수 호출 과정에서 값이 누락되는 버그 방지
- 대규모 프로젝트에서 유지보수성 급증
strictNullChecks는 타입 안정성을 극대화하는 가장 중요한 옵션이며 최근 모든 현대 TypeScript 프로젝트에서는 거의 “필수”로 간주됩니다.
실무에서 자주 쓰는 nullable 설계 패턴
✔ 명시적인 nullable 타입
type Nullable<T> = T | null;
✔ API 응답 패턴
type UserResponse = {
id: number;
name: string | null;
};
✔ optional property (undefined 가능성 포함)
type User = {
name?: string; // string | undefined
};
옵셔널 속성은 자동으로 undefined 가능성을 포함합니다.
null과 undefined는 JavaScript에서 매우 흔하면서도 위험한 값이지만, TypeScript의 strictNullChecks 옵션을 통해 안전한 코딩을 강제할 수 있습니다.
- null = 의도적으로 비워짐
- undefined = 초기화되지 않음
- strictNullChecks = null/undefined를 타입 시스템에서 엄격하게 다룸
- nullable 값은 반드시 타입으로 명시
- optional chaining, nullish coalescing로 안전하게 접근 가능
