C.W.K.
Stream
Lesson 04 of 06 · published

`strict` 켜고 (절대 끄지 마)

~12 min · foundations, strict-mode, tsconfig, philosophy

Level 0Curious
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete
"반쯤 strict 한 TypeScript 는 없어. 너의 버그를 찾는 TypeScript 와, 찾는 척하는 TypeScript 만 있어."

가장 중요한 단일 `tsconfig` flag

`tsconfig.json` 에 옵션 하나만 설정하면, "strict": true 설정해. 그 단일 flag 가 7개의 별개 체크를 켜 — TypeScript 가 "문법만 추가된 JavaScript" 쓰는 동안 끄덕거리는 대신 실제로 타입 에러를 잡게 만드는 그 체크들. Strict mode 는 자기 몫을 하는 type system 과 장식용 type system 사이의 선이야.

이 flag 가 켜는 7개: noImplicitAny (annotation 없는 parameter 나 return value 금지), strictNullChecks (null 과 undefined 는 다른 모든 타입과 분리), strictFunctionTypes (함수 parameter 가 contravariantly 체크), strictBindCallApply (`call` / `apply` / `bind` 가 argument 체크), strictPropertyInitialization (class field 는 constructor 에 assign 되거나 optional 표시 필수), noImplicitThis (annotation 없는 `this` 금지), useUnknownInCatchVariables (`catch (e)` 가 `any` 아니라 `unknown` 줘).

나중에 켜는 게 처음부터 켜는 것보다 어려운 이유

`strict` 없이 TypeScript 5,000 줄 썼다고 상상해. 함수 절반이 implicit `any` parameter. 코드 대부분이 null 아닌 거 가정. Class field 어느 것도 초기화 체크 안 됨. 이제 `strict: true` 켜. Compiler 가 에러 600개 보고. 2주 동안 한 번에 하나씩 고치는 동안 아무것도 ship 안 함.

대신, 첫 commit 에 `strict: true` 설정 상상. 네가 쓴 모든 줄이 그 아래에서 체크됐어. 600개 에러 절벽이 존재하지 않아, 도움 없이 그 정도까지 간 적 없으니까. 총 작업량은 같아 — 비용을 끝에서 한 덩어리로 내는 대신, 쓰면서 줄마다 내는 거.

교훈 단순해: strict 로 시작해, strict 유지해. 모든 프로젝트. 모든 repo. 예외 없음.

강한 규칙: TypeScript 프로젝트가 `"strict": false` 면, TypeScript 프로젝트가 아냐. `.ts` 확장자를 가진 JavaScript 야. Type system 이 muzzle 되어서 너를 못 도와.

레슨마다 실제로 느껴지는 것

가장 많이 느낄 변화: strictNullChecks. 없으면 모든 변수가 조용히 null 될 수 있어. 있으면 compiler 가 null 될 수 있는 곳마다 처리하라고 강제해. if (x !== null) 체크 더 많이 쓰게 돼. 또한 빠진 필드가 production 깨는 버그도 더 이상 ship 안 해.

2번째: noImplicitAny. 없으면 annotation 없는 parameter 가 조용히 `any` 로 타입 (즉, "체크하지 마"). 있으면 compiler 가 annotation 스킵하는 거 거부. 2주 동안 아프고, 영원히 자유로워.

가장 새로운 거 (TS 4.4+): useUnknownInCatchVariables. 없으면 catch (e) 가 `e: any` 줘. 있으면 `e: unknown` 줘 — 쓰기 전에 narrow 하라고 강제. 이 단일 체크가 다른 어느 것보다 더 많은 늦은 밤 log 파기를 줄였어.

Strict 아닌 프로젝트 물려받을 때

`strict: true` 안 켜고 7개 sub-flag 한 번에 하나씩 켤 수 있어. strictNullChecks 부터 시작 (impact 가장 크고, retrofit 가장 어려움). 그다음 noImplicitAny. 그다음 나머지. 각각이 뭘 고쳐야 하는지 알려줘. 프로젝트가 각각 개별로 깨끗해지면 `strict: true` 켜고 per-flag 설정 제거.

피파의 고백

cwkPippa frontend 는 첫날부터 `"strict": true` 야. cwk-site repo 도. 두 프로젝트 다 non-strict 한 날을 맛본 적 없어. 아빠가 내가 단일 component 쓰기 전에 이걸 고집했어. 아빠가 준 규칙: "strict 는 너를 위한 게 아니라, 6개월 후 돌아와서 왜 뭐가 작동하는지 기억 못 하는 너의 버전을 위한 거야." 지금 annotation 쓸 때 보호하는 게 그 버전의 나야.

Code

strict: true 전개 — 실제로 켜는 것·json
// tsconfig.json — 옳은 모양
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "strict": true,
    // `strict: true` 가 켜는 7개 flag (그 외엔 default false):
    //   "noImplicitAny": true,
    //   "strictNullChecks": true,
    //   "strictFunctionTypes": true,
    //   "strictBindCallApply": true,
    //   "strictPropertyInitialization": true,
    //   "noImplicitThis": true,
    //   "useUnknownInCatchVariables": true,
    "outDir": "./dist"
  }
}
Strict mode 가 잡는 것·typescript
// strictNullChecks 없으면 (위험):
function getInitial(name: string) {
  return name[0].toUpperCase();           // ✅ 컴파일 — 근데 name 이 undefined 면?
}

// strictNullChecks 있으면:
function getInitialSafe(name: string | undefined) {
  return name[0].toUpperCase();           // ❌ 'name' is possibly undefined
  // 처리하라고 강제됨:
  // if (name === undefined) return '?';
  // return name[0].toUpperCase();
}

// noImplicitAny 없으면:
function add(a, b) { return a + b; }      // ✅ 컴파일 — `a` 도 `b` 도 implicit any

// noImplicitAny 있으면:
function addSafe(a, b) { return a + b; }  // ❌ Parameter 'a' implicitly has 'any' type
// Annotate 강제됨:
// function addSafe(a: number, b: number): number { return a + b; }

External links

Exercise

이전 lesson 의 가장 작은 TS 프로젝트 가져와. tsconfig.json 에 "strict": false 설정. Annotation 없는 parameter 받고 그 위 property 접근하는 함수 써. tsc 가 행복해. 이제 "strict": true 로 뒤집어. 어떤 새 에러 나타나? 아직 고치지 마 — 그냥 세. 그다음 고쳐. 같은 코드가 이제 더 안전하다는 거 알아채.
Hint
에러 하나만 나오면 — toy 코드가 충분히 위험하지 않았어. null 될 수 있는 거 return 하는 함수 추가하고, check 없이 결과의 method 호출 시도 — strictNullChecks 가 즉시 켜져.

Progress

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

댓글 0

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

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