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

Contact Me

© 2026 SEOJing. All rights reserved.

이펙티브 타입스크립트 2판 Day 8: any를 밖에 세우고 unknown으로 검증하기

2026년 7월 3일·4분 읽기
범위: Effective TypeScript 2판 Item 42–48
오늘의 질문: “API 응답 타입을 모를 때 any로 빨리 넘기는 게 정말 더 빠를까?”

먼저 보는 코드

ts
async function loadUser(id: string) {
  const response = await fetch(`/api/users/${id}`);
  const data: any = await response.json();

  return {
    id: data.id,
    name: data.profile.name,
    isAdmin: data.role === "admin",
  };
}

이 코드는 타입 에러가 거의 나지 않습니다. 그래서 안전해 보이기도 합니다. 하지만 실제로는 타입스크립트가 “검사할 근거를 잃은” 상태에 가깝습니다. data.profile이 없거나 id가 숫자여도 내부 코드까지 any가 번지면 리뷰 포인트가 사라집니다.

Item 42–48 구간의 핵심은 타입 시스템을 이기는 요령이 아니라, 검사가 필요한 경계와 검사가 끝난 내부를 분리하는 습관입니다.

any와 unknown 경계 설계

틀리기 쉬운 직감: any는 생산성을 높인다

any는 가끔 필요한 탈출구입니다. 문제는 탈출구가 통로가 될 때입니다. 외부 입력, 서드파티 라이브러리, 오래된 JS 모듈에서 들어온 값을 any로 받아 내부 타입까지 오염시키면, 타입스크립트가 해주던 질문이 사라집니다.

ts
function renderUser(user: any) {
  return user.profile.displayName.toUpperCase();
}

이 함수는 모든 호출을 받아들입니다. 리뷰할 때는 “타입이 맞나?”를 볼 수 없고, 런타임에서 터진 뒤에야 경계가 없었다는 사실을 알게 됩니다.

반대로 unknown은 불편합니다. 그 불편함이 장점입니다.

ts
type UserPayload = {
  id: string;
  profile: { displayName: string };
};

function isUserPayload(value: unknown): value is UserPayload {
  if (typeof value !== "object" || value === null) return false;

  const record = value as Record<string, unknown>;
  const profile = record.profile;

  return (
    typeof record.id === "string" &&
    typeof profile === "object" &&
    profile !== null &&
    typeof (profile as Record<string, unknown>).displayName === "string"
  );
}

unknown은 바로 읽을 수 없기 때문에, 검증 함수나 스키마를 경계에 세우도록 압박합니다. 내부로 들어온 뒤에는 UserPayload로 다룰 수 있으니 컴포넌트와 서비스 함수가 덜 방어적으로 됩니다.

타입 단언은 검증이 아니다

ts
const data = (await response.json()) as UserPayload;

이 코드는 짧습니다. 하지만 as UserPayload는 런타임 값을 바꾸지 않습니다. 타입스크립트에게 “내가 맞다고 치자”라고 말하는 것에 가깝습니다. 호출자가 정말 그 형태를 보장한다면 괜찮지만, 외부 API 응답처럼 변할 수 있는 경계에서는 단언만으로 충분하지 않습니다.

코드 리뷰에서는 단언을 보면 이렇게 나눠 봅니다.

단언 위치리뷰 판단
테스트 픽스처의도적으로 좁힌 데이터면 허용 가능
DOM API처럼 TS가 모르는 곳null 체크나 환경 조건이 옆에 있으면 허용 가능
외부 JSON 응답단언만 있으면 위험, 검증 함수/스키마 경계가 필요
내부 도메인 변환 후변환 함수가 검증을 끝냈다면 단언 없이 타입이 좁아져야 함

monkey patching은 타입과 런타임을 같이 바꾼다

브라우저 전역 객체나 라이브러리 객체에 필드를 붙이는 코드는 타입스크립트에서 두 겹의 위험을 만듭니다.

ts
(window as any).analyticsClient = createClient();

런타임 전역 상태도 생기고, 타입 시스템도 우회합니다. 정말 전역 확장이 필요하다면 최소한 타입 선언과 초기화 경계를 같이 둬야 합니다.

ts
declare global {
  interface Window {
    analyticsClient?: AnalyticsClient;
  }
}

window.analyticsClient = createClient();

그래도 리뷰 질문은 남습니다. “전역이어야 하는가?”, “초기화 전 접근은 어떻게 막는가?”, “테스트에서 격리되는가?”입니다.

프론트엔드 코드 리뷰 체크리스트

any가 외부 경계에서 끝나는가, 아니면 컴포넌트 내부 props/state까지 번지는가? unknown을 받은 뒤 실제 검증 또는 narrowing이 있는가? as SomeType이 런타임 검증처럼 쓰이고 있지 않은가? monkey patching이 전역 상태와 타입 선언을 동시에 바꾸는지, 초기화 순서가 안전한가? 타입스크립트가 일부러 막아준 오류를 any/단언으로 침묵시키고 있지 않은가?

any를 완전히 금지하자는 뜻은 아닙니다. 중요한 건 any가 어디서 들어오고 어디서 멈추는지입니다. 외부 입력은 unknown으로 받고, 경계에서 검증하고, 내부에는 도메인 타입만 흘려보내는 쪽이 리뷰 가능한 코드에 가깝습니다.

Day 8 타입 안정성 점검

Quiz1 / 4
Q.외부 API 응답을 처음 받는 타입으로 가장 안전한 기본값은 무엇일까요?

Post Q&A

오케이징에게 물어보기

이펙티브 타입스크립트 2판 Day 8: any를 밖에 세우고 unknown으로 검증하기 전체를 기준으로 질문과 피드백을 받아요.답을 본 뒤에는 이 내용을 댓글로 달아서 서징에게도 물어볼 수 있어요. 작성자가 직접 볼 수 있어요!

0/500

포스트 목록

/study/effective-typescript
파일 8개, 폴더 0개
이펙티브 타입스크립트 2판 Day 1: 타입스크립트를 믿기 전에 알아야 할 경계이펙티브 타입스크립트 2판 Day 2: 타입을 값의 집합으로 보기이펙티브 타입스크립트 2판 Day 3: 타입 반복을 줄이는 리뷰 감각이펙티브 타입스크립트 2판 Day 4: 추론을 살리는 값 생성 패턴이펙티브 타입스크립트 2판 Day 5: 타입 추론을 방해하지 않는 API 설계이펙티브 타입스크립트 2판 Day 6: 유효한 상태만 표현하는 타입 설계이펙티브 타입스크립트 2판 Day 7: 문자열보다 도메인 의미를 좁히기이펙티브 타입스크립트 2판 Day 8: any를 밖에 세우고 unknown으로 검증하기

같은 섹션의 대표 이미지

8 posts · latest first
외부 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: 타입 추론을 방해하지 않는.

Effective TypeScript 2판 Item 19–22를 바탕으로 타입 추론, 타입 넓히기, 함수형 기법, 유니온 설계를 코드 리뷰 관점에서 정리합니다.

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