LogoSEO Jing
  • All Posts
  • SEO Jing
  • okayJing
  • KD Team
  • CLAB Coreteam
  • Study

Contact Me

© 2026 SEOJing. All rights reserved.

이펙티브 타입스크립트 2판 Day 6: 유효한 상태만 표현하는 타입 설계

2026년 6월 28일·3분 읽기
예상 읽기 시간: 13분
범위: Effective TypeScript 2판 Item 28–34
오늘의 질문: “타입이 넓어지는 문제를 타입 단언으로 막아도 괜찮을까?”

먼저 보는 코드

ts
type User = { id: string; name: string };

type ViewState =
  | { status: "loading" }
  | { status: "error"; message: string }
  | { status: "ready"; user: User };

이 타입의 장점은 “ready인데 user가 없음” 같은 상태를 아예 표현하지 않는다는 점입니다. Day 6의 핵심은 타입을 많이 쓰는 게 아니라 불가능한 상태를 줄이는 설계입니다.

API 경계에서 유효한 상태 유니온으로 좁히는 흐름

틀리기 쉬운 직감

가장 흔한 대응은 이겁니다.

ts
const user = response.data as User;

하지만 단언은 런타임 데이터를 검증하지 않습니다. API가 name: null을 보내도 컴파일러는 이미 믿어버립니다. 그래서 경계에서는 확인하고, 내부에서는 좁혀진 타입만 흘리는 편이 낫습니다.

ts
function toUser(input: unknown): User | null {
  if (!input || typeof input !== "object") return null;
  const value = input as Record<string, unknown>;
  if (typeof value.id !== "string") return null;
  if (typeof value.name !== "string") return null;
  return { id: value.id, name: value.name };
}

추론 위치를 고르기

타입스크립트는 선언 위치의 단서를 보고 타입을 추론합니다. 너무 이른 곳에서 넓게 잡히면 뒤에서 계속 보정해야 합니다.

ts
const tabs = ["home", "settings"];
// string[]

const fixedTabs = ["home", "settings"] as const;
// readonly ['home', 'settings']

as const는 “이 값의 모양을 좁게 보존하겠다”는 신호입니다. 옵션 목록, 라우트 이름, 상태 태그처럼 리터럴 자체가 의미를 가질 때 유용합니다. 반대로 서버 응답처럼 실제 값이 불확실한 곳에 무작정 붙이면 거짓 안정감이 됩니다.

null과 undefined는 경계를 정한다

null | undefined | [] | {}가 섞이면 UI 조건문이 지저분해집니다. 더 나은 방식은 경계에서 한 번 정리하는 것입니다.

ts
function normalizeUsers(users: User[] | null | undefined): User[] {
  return users ?? [];
}

컴포넌트 내부에서는 User[]만 다루게 만들면 렌더링 조건이 단순해지고 테스트도 줄어듭니다. 단, “아직 로딩 중”과 “결과가 비어 있음”은 다른 상태이므로 [] 하나로 모두 합치면 안 됩니다. 그런 차이는 ViewState 같은 유니온으로 남겨야 합니다.

코드 리뷰 체크리스트

as가 검증 대신 쓰이고 있지 않은가? API 경계의 unknown이 내부까지 흘러 들어오지 않는가? loading, error, ready, empty가 서로 모순 없이 표현되는가? 리터럴 union이 필요한 값에 string이 너무 넓게 잡히지 않았는가? null/undefined 정규화가 의미 차이를 지워버리지 않는가?

짧은 복습

타입 단언은 런타임 검증이 아니다. 불가능한 상태는 optional 필드 여러 개보다 discriminated union으로 줄인다. as const는 리터럴 의미를 보존할 때 쓰고, 외부 데이터를 믿게 만드는 용도로 쓰지 않는다. API 경계에서 좁히고 UI 내부는 좁혀진 타입만 받게 만든다.

이렇게 보면 타입 설계는 “컴파일러를 만족시키는 장식”이 아니라 리뷰할 상태 공간을 줄이는 작업입니다.

Post Q&A

오케이징에게 물어보기

이펙티브 타입스크립트 2판 Day 6: 유효한 상태만 표현하는 타입 설계 전체를 기준으로 질문과 피드백을 받아요.답을 본 뒤에는 이 내용을 댓글로 달아서 서징에게도 물어볼 수 있어요. 작성자가 직접 볼 수 있어요!

0/500

포스트 목록

/study/effective-typescript
파일 14개, 폴더 0개
이펙티브 타입스크립트 2판 Day 1: 타입스크립트를 믿기 전에 알아야 할 경계이펙티브 타입스크립트 2판 Day 2: 타입을 값의 집합으로 보기이펙티브 타입스크립트 2판 Day 3: 타입 반복을 줄이는 리뷰 감각이펙티브 타입스크립트 2판 Day 4: 추론을 살리는 값 생성 패턴이펙티브 타입스크립트 2판 Day 5: 좁혀진 타입은 언제 다시 넓어지는가이펙티브 타입스크립트 2판 Day 6: 유효한 상태만 표현하는 타입 설계이펙티브 타입스크립트 2판 Day 7: 문자열보다 도메인 의미를 좁히기이펙티브 타입스크립트 2판 Day 8: any를 밖에 세우고 unknown으로 검증하기이펙티브 타입스크립트 2판 Day 9: 제네릭은 관계를 보존할 때만 강하다이펙티브 타입스크립트 2판 Day 10: 타입도 테스트하고 빠지는 분기는 막는다이펙티브 타입스크립트 2판 Day 11: 객체 타입은 열려 있고, 계약은 닫아야 한다이펙티브 타입스크립트 2판 Day 12: 타입은 공개 API의 사용법이다이펙티브 타입스크립트 2판 Day 13: 타입은 런타임과 테스트를 대신하지 않는다이펙티브 타입스크립트 2판 Day 14: JS에서 TS로 옮길 때 먼저 좁혀야 할 경계

같은 섹션의 대표 이미지

14 posts · latest first
런타임 값 검증, DOM 환경, 테스트, 컴파일러 성능으로 이어지는 타입스크립트 경계 다이어그램
Study26. 07. 09.

이펙티브 타입스크립트 2판 Day 13: 타입은 런타임과.

Item 74–78 범위를 바탕으로 런타임 타입 재구성, DOM과 환경 모델, 단위 테스트 관계, 컴파일러 성능을 코드 리뷰 관점에서 정리합니다.

26. 07. 09.SEOJing
JavaScript 현대화에서 @ts-check, allowJs, 모듈별 전환, noImplicitAny로 이어지는 마이그레이션 단계 다이어그램
Study26. 07. 09.

이펙티브 타입스크립트 2판 Day 14: JS에서 TS로 옮길.

Item 79–83 범위를 바탕으로 JS 현대화, @ts-check와 JSDoc, allowJs, 모듈별 마이그레이션, noImplicitAny를 코드 리뷰 관점에서 정리합니다.

26. 07. 09.SEOJing
내부 구현 타입에서 문서화된 public API 타입으로 넘어가는 경계 다이어그램
Study26. 07. 08.

이펙티브 타입스크립트 2판 Day 12: 타입은 공개 API의.

Item 67–73 범위를 바탕으로 public API 타입, TSDoc, this callback, module augmentation, TypeScript 기능 선택, source map을 코드 리뷰 관점에서 정리합니다.

26. 07. 08.SEOJing
Object iteration, Record, tuple/rest, XOR, brand, @types 버전 관리를 연결한 타입 리뷰 다이어그램
Study26. 07. 07.

이펙티브 타입스크립트 2판 Day 11: 객체 타입은 열려.

Item 60–66 범위를 바탕으로 Object iteration, Record, tuple/rest, XOR, brand, @types 버전 경계를 코드 리뷰에서 다루는 방법을 정리합니다.

26. 07. 07.SEOJing
타입 계약, 타입 테스트, never exhaustiveness, 코드 생성 경계를 보여주는 다이어그램
Study26. 07. 06.

이펙티브 타입스크립트 2판 Day 10: 타입도 테스트하고.

Item 55–59 범위를 바탕으로 type test, 타입 표시, 꼬리 재귀 한계, 코드 생성, never exhaustiveness를 코드 리뷰에서 다루는 방법을 정리합니다.

26. 07. 06.SEOJing
외부 경계, 제네릭, 조건부 타입, 템플릿 리터럴 타입의 역할과 과한 타입 계산의 위험을 보여주는 다이어그램
Study26. 07. 05.

이펙티브 타입스크립트 2판 Day 9: 제네릭은 관계를 보존할.

Item 49–54 범위를 바탕으로 type coverage, 제네릭, 조건부 타입, 템플릿 리터럴 타입을 코드 리뷰에서 어떻게 판단할지 정리합니다.

26. 07. 05.SEOJing
외부 JSON을 unknown으로 받고 검증 뒤 도메인 타입으로 넘기는 경계와 any가 내부로 번지는 위험을 보여주는 다이어그램
Study26. 07. 04.

이펙티브 타입스크립트 2판 Day 8: any를 밖에 세우고.

Item 42–48 범위를 바탕으로 any, unknown, 타입 단언, monkey patching, soundness 함정을 외부 입력 경계와 코드 리뷰 관점에서 정리합니다.

26. 07. 04.SEOJing
넓은 문자열과 선택적 필드를 도메인 이름과 유효 상태 유니온으로 좁히는 다이어그램
Study26. 06. 29.

이펙티브 타입스크립트 2판 Day 7: 문자열보다 도메인.

Item 35–41 범위를 바탕으로 string 남용, optional 필드, 특수 값, 도메인 이름 설계를 코드 리뷰 관점에서 정리합니다.

26. 06. 29.SEOJing
API 응답을 유효한 상태 유니온으로 변환하는 흐름 다이어그램
Study26. 06. 28.

이펙티브 타입스크립트 2판 Day 6: 유효한 상태만 표현하는.

Item 28–34 범위를 바탕으로 추론 위치, 유효 상태 모델링, API 입출력, null 경계, union 설계를 프론트엔드 코드 리뷰 관점에서 확장 정리합니다.

26. 06. 28.SEOJing
타입스크립트 추론이 값에서 API 경계로 흐르는 과정을 보여주는 다이어그램
Study26. 06. 27.

이펙티브 타입스크립트 2판 Day 5: 좁혀진 타입은 언제.

Item 22–27 범위를 바탕으로 narrowing, alias, context inference, evolving type, async/type flow를 프론트엔드 코드 리뷰 관점에서 다시 정리합니다.

26. 06. 27.SEOJing
TypeScript에서 넓은 타입으로 먼저 담으면 key와 literal 정보가 사라지고 리뷰 체크가 약해지는 흐름 다이어그램
Study26. 06. 26.

이펙티브 타입스크립트 2판 Day 4: 추론을 살리는 값 생성.

Effective TypeScript 2판의 Item 16–21을 바탕으로 index signature, 타입 추론 기본, 변수/객체 생성 패턴을 프론트엔드 코드 리뷰 관점에서 정리합니다.

26. 06. 26.SEOJing
반복된 타입 선언을 원본 타입에서 파생한 타입으로 바꿔 리뷰 체크를 강하게 만드는 흐름 다이어그램
Study26. 06. 25.

이펙티브 타입스크립트 2판 Day 3: 타입 반복을 줄이는 리뷰.

Effective TypeScript 2판의 Item 11–15를 바탕으로 excess property check, 함수식 타입, type vs interface, readonly, 타입 반복 제거를 프론트엔드 코드 리뷰 관점에서 정리합니다.

26. 06. 25.SEOJing
TypeScript 타입을 값의 집합, type space, value space, assertion 경계로 정리한 다이어그램
Study26. 06. 24.

이펙티브 타입스크립트 2판 Day 2: 타입을 값의 집합으로.

Effective TypeScript 2판의 Item 6–10을 바탕으로 타입 시스템을 탐색하는 법, 타입을 값의 집합으로 보는 관점, type/value space, 타입 단언의 경계를 코드 리뷰 관점에서 정리합니다.

26. 06. 24.SEOJing
TypeScript를 JavaScript 위의 정적 타입 계층, 타입 제거, 구조적 타이핑, any의 구멍으로 정리한 다이어그램
Study26. 06. 23.

이펙티브 타입스크립트 2판 Day 1: 타입스크립트를 믿기.

Effective TypeScript 2판의 Item 1–5를 바탕으로 TypeScript와 JavaScript의 관계, tsconfig, 타입 제거, 구조적 타이핑, any의 위험을 프론트엔드 코드 리뷰 관점에서 정리합니다.

26. 06. 23.SEOJing