C.W.K.
Stream
Lesson 02 of 05 · published

`null`, `undefined`, `void`: 무 (無) 의 3가지 맛

~11 min · primitives, null, undefined, void

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"'아무것도 없음' 말하는 3가지 방법 — 각자 살짝 다른 '아무것도 없음' 의미해."

JavaScript 가 두 null 가진 이유

대부분 언어는 "값 없음" 말하는 한 방법 가져. JavaScript 는 두 개 — 그리고 TypeScript 는 의도적으로 분리 유지해. null명시적 부재: 코드가 의도적으로 썼어, 자주 API 의 return value ("결과 없음") 로. undefined암묵적 부재: 아직 아무도 assign 안 했어 (초기화 안 된 변수, 빠진 parameter, 빠진 object property, 빠진 return 문).

Runtime 에 다른 값. 타입 레벨에 다른 타입. strictNullChecks: true (`strict: true` 가 켜는 거) 로 어느 것도 다른 타입에 조용히 assignable 안 됨 — 처리하거나, narrow 하거나, union 에 명시적으로 포함시켜야 함.

실용 규칙: codebase 에서 하나만 골라

nullundefined 둘 다 유효한 TypeScript 지만, 대부분 modern 스타일 가이드가 하나 골라서 일관되게 쓰라고 권해. TypeScript 팀 자체가 관례적으로 undefined 써 (standard library 와 Handbook 곳곳에서 봐). 일부 팀이 null 선호해 — JSON 에 명확히 나오니까. 둘 다 defensible. 막 섞는 건 아냐 — 너의 데이터의 모든 consumer 가 두 모양의 무를 처리하도록 강제하니까.

cwkPippa 의 관례: in-memory 부재엔 undefined (optional 필드, 빠진 함수 결과), database / JSON serialization 엔 null (JSON.stringify(undefined) === undefined — undefined 가 JSON 살아남지 못해서 wire format 이 null 써).

void — "유용한 거 없음" 말하는 return type

void 는 유용한 return value 없는 함수의 return type. function logMessage(msg: string): void. 함수가 기술적으로 `undefined` return 할 수 있지만, "이 return value 아무 데에도 쓰지 마" 신호 보내.

Return type 으로서 voidundefined 의 차이는 미묘하지만 실재. : void annotate 된 함수는 어떤 return type 도 허용되는 곳에 전달 가능 — type system 이 "이 return 은 무시할 거" 라고 이해. : undefined annotate 된 함수는 실제로 undefined 값을 명시적으로 return 해야 함 (또는 strict mode caveat 으로 return 문 없이 암묵적). Callback 과 side-effecting 함수엔 void 써; 진짜로 그 값 의미할 때만 undefined 써.

경험 법칙: 함수 return type 엔 void 만 써. 값엔 undefined 써. Codebase 스타일이 명령하거나 serialization 경계 넘을 때만 null 써.

Optional property — ? 단축형

Interface 에서 name?: string 볼 거야. 이건 name: string | undefined 의 단축형 — property 가 있을 수 (그리고 string 일 수) 있거나 없을 수 (undefined 일 수) 있어. exactOptionalPropertyTypes 켜진 상태 (나중에 다룰 별개 strict flag) 에선 "존재하면서 명시적으로 undefined" vs "완전히 부재" 의 차이가 type-system-significant 해져. 지금은 그 단축형이 흔한 idiom.

피파의 고백

내 API 응답이 JSON 경계에서 null 써, TypeScript 의 undefined 가 serialization 살아남지 못해서. 근데 frontend 안에선 unwrapped 값이 normalize 돼 — 서버에서 온 { email: null } 이 메모리에선 { email: undefined } 가 돼. 그다음 downstream 어디서나 email?: string 써. 두 맛이 정확히 한 자리에서 만나 — wire 경계 — 그리고 그 자리는 문서화돼 있어.

Code

Strict mode 에서의 nullability opt-in·typescript
// strictNullChecks 가 다른 타입과 분리 유지.

let name: string = 'Pippa';
name = null;                                  // ❌ Type 'null' is not assignable to type 'string'
name = undefined;                             // ❌ Type 'undefined' is not assignable to type 'string'

// 허용하려면 명시적으로 opt in:
let maybeName: string | null = null;          // ✅
let maybeName2: string | undefined = undefined; // ✅
let maybeBoth: string | null | undefined = null; // ✅

// Object property 의 `?` 단축형:
interface Profile {
  id: number;
  name: string;
  email?: string;                             // 단축형: email: string | undefined
}

const p1: Profile = { id: 1, name: 'Pippa' };                  // ✅ email 생략
const p2: Profile = { id: 1, name: 'Pippa', email: 'a@b.c' };  // ✅ email 있음
void 가 존재하는 이유: callback 과 side effect·typescript
// Return type 로서 void vs undefined.

// `void` — return value 를 무시해야 함.
function logEvent(name: string): void {
  console.log(name);
  // return 문 필요 없음 — 어떤 return value 도 무시됨
}

// `undefined` — 실제로 undefined return 해야 함 (또는 return 안 도달).
function findMaybe(id: number): undefined {
  // ❌ 여기서 `return someValue` 하면 compiler 가 불평
  return;                                     // ✅ 명시적 빈 return
}

// Callback 예시 — `void` 가 API 를 유연하게 만들어.
function onClick(handler: (e: Event) => void): void {
  // ...
}

onClick((e) => 42);                           // ✅ — `42` 는 허용되고 무시됨
// Parameter 가 `: undefined` 였으면 이거 실패.

External links

Exercise

필수 id: numbername: string, plus optional email?: string 가진 User interface 써. User 를 로그하는 displayUser(u: User): void 함수 써. 그다음 email = null 로 user 만들고 전달 시도. Compiler 가 뭐라고, 왜? 이제 email 필드를 email?: string 대신 email: string | null 로 바꿔. 뭐 바뀌었어?
Hint
Optional ? 는 필드가 없거나 undefined 인 거 허용. null 인 거는 허용 안 해. 진짜로 null 원하면 union 에 명시적으로 선언. JSON-shaped 데이터엔 이 구별 중요해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고
💛 by 똘이warm

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.