Files
2nd/10_Wiki/Topic_Programming/Coding/Null_Safety_Patterns.md
T
Antigravity Agent 9148c358d0 docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
2026-07-05 00:33:48 +09:00

5.3 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, created_at, updated_at, last_reinforced, review_reason, merge_history, tags, raw_sources, tech_stack, applied_in
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status created_at updated_at last_reinforced review_reason merge_history tags raw_sources tech_stack applied_in
null-safety-patterns Null 안전 패턴 (Null Safety Patterns) Coding draft null-safety-patterns
optional
maybe
nullable
undefined-handling
NPE
null B 0.85 conceptual 2026-05-09 2026-05-09 2026-05-09
coding
type-safety
null
undefined
vibe-coding
P-Reinforce session 2026-05-09 — bulk Coding seed batch 1
language applicable_to
TypeScript / Kotlin / Rust / Swift
모든 도메인

Null 안전 패턴

Null/undefined 는 "값이 없음"이라는 정보를 담지 못하는 가장 빈약한 표현. 타입에서 nullable 을 명시적으로 분리하고, 언래핑 지점을 명확히 만들어라.

📖 핵심 개념

Tony Hoare가 "the billion dollar mistake" 라고 부른 null 참조 문제. 모던 언어들은 다음 중 하나로 대응:

  1. 타입 시스템에서 nullable 분리: TypeScript T | null, Kotlin T?, Swift T?
  2. Optional 타입: Rust Option<T>, Haskell Maybe a
  3. Strict mode: TS의 strictNullChecks, Kotlin 디폴트, Swift 디폴트

핵심은 "이 값은 없을 수 있다"를 타입이 명시적으로 표현하고 컴파일러가 강제하는 것.

💻 코드 패턴

1. nullable 명시 (TypeScript with strictNullChecks)

// ❌ 모호함 — name 이 항상 있는지 가끔 없는지 모름
function greet(user: { name: string }) { return `Hi, ${user.name}`; }

// ✅ 명시
function greet(user: { name: string | null }) {
  if (user.name === null) return 'Hi, friend';
  return `Hi, ${user.name}`;
}

2. Optional Chaining + Nullish Coalescing

// 깊은 경로 안전 접근
const city = order?.shipping?.address?.city ?? 'Unknown';

// ❌ 주의: || 는 falsy("" / 0) 도 fallback 으로 처리
const port = config.port || 3000; // port가 0이면 3000 됨!
const port = config.port ?? 3000; // null/undefined 만 fallback ✓

3. 타입 가드 + 좁히기

function isPresent<T>(x: T | null | undefined): x is T {
  return x !== null && x !== undefined;
}

const items = users.map(u => u.email).filter(isPresent); // string[]

4. Maybe / Option 모나드 패턴 (TS)

type Some<T> = { kind: 'some'; value: T };
type None = { kind: 'none' };
type Maybe<T> = Some<T> | None;

const some = <T>(value: T): Maybe<T> => ({ kind: 'some', value });
const none = (): Maybe<never> => ({ kind: 'none' });

function map<T, U>(m: Maybe<T>, f: (t: T) => U): Maybe<U> {
  return m.kind === 'none' ? m : some(f(m.value));
}
function getOr<T>(m: Maybe<T>, fallback: T): T {
  return m.kind === 'some' ? m.value : fallback;
}

복잡한 변환 체인이 많을 때만 도입. 단순한 T | null 로 충분한 경우엔 over-engineering.

5. Non-null assertion (!) 의 좁은 사용

const el = document.getElementById('root')!; // OK if you control the HTML

// ❌ 위험
function findUser(id: string) {
  return users.find(u => u.id === id)!; // 못 찾으면 런타임 사고
}

// ✅
function findUser(id: string): User {
  const u = users.find(u => u.id === id);
  if (!u) throw new NotFoundError(id);
  return u;
}

🤔 의사결정 기준

시그니처 의미 사용 시점
T 항상 값 있음 강한 보장이 필요할 때 (도메인 invariant)
T | null 값이 의도적으로 없을 수 있음 "선택 사항" 의미 명확할 때
T | undefined 아직 초기화 안 됨 / 키 없음 object property optional 표현
T | null | undefined 둘 다 가능 외부 데이터 (API 응답) — 즉시 정규화 권장
Maybe<T> / Option<T> 변환 체이닝이 잦음 복잡한 nullable pipeline

안티패턴

  • any 로 회피: 타입 시스템 우회. 컴파일은 통과하지만 런타임 폭사.
  • Non-null assertion 남발 (x!.y!.z!): 컴파일러를 침묵시키지만 보장 없음. 매번 가드 또는 스키마 검증.
  • || 로 falsy 까지 fallback: 0, "", false 가 의미 있는 값일 때 사고. ?? 사용.
  • null 과 undefined 둘 다 보내기: 한 코드베이스에서 한 컨벤션 (보통 undefined 권장 — JSON 직렬화 시 사라져 명시적).
  • null check 잊고 nested access: obj.a.b.cobj.a null 일 때 폭사. optional chaining ?. 사용.
  • 외부 API 응답을 그대로 nullable 채로 도메인 깊숙이 전파: 경계에서 zod / io-ts 같은 스키마로 정규화.

🤖 LLM 활용 힌트

  • LLM에게 함수 작성: "strictNullChecks 가정. 가능한 nullable 은 시그니처에 명시" 라고 요청.
  • 외부 API 파싱: "zod 같은 라이브러리로 nullable 을 즉시 도메인 타입으로 정규화" 명시.
  • TypeScript 옵션: 프로젝트 tsconfig.json"strict": true 또는 최소 "strictNullChecks": true 가 있어야 이 모든 패턴이 의미 있음.

🧪 검증 상태

  • verification_status: conceptual
  • Kotlin / Swift / Rust 의 default null safety 모델, TypeScript strictNullChecks 가 표준.
  • 적용 사례 발견 시 applied_in 추가.

🔗 관련 문서