[JSTS-008][중급] 여러 타입을 안전하게 구분하고 재사용하기 > IT 기술 공유

본문 바로가기
사이트 내 전체검색

IT 기술 공유

[JSTS-008][중급] 여러 타입을 안전하게 구분하고 재사용하기

페이지 정보

profile_image
작성자 기술팀장
댓글 0건 조회 158회 작성일 26-09-03 06:33

본문

[이번 수업]
하나의 함수가 문자열과 숫자처럼 여러 타입을 다루거나, 요청 결과가 성공과 실패 중 하나일 때 any로 처리하면 실수를 놓치기 쉽습니다. 이번에는 제네릭으로 타입 정보를 유지하고, 유니언과 타입 좁히기로 가능한 경우를 안전하게 나누는 방법을 배웁니다.

[선수지식]
JavaScript 함수·배열·객체와 TypeScript의 기본 타입을 알아야 합니다. Node.js와 npm이 필요합니다. 연습 폴더에서 npm init -y와 npm install --save-dev typescript를 한 번 실행하세요. 이 명령은 Windows PowerShell, macOS, Linux에서 같습니다.

[학습목표]
1. 제네릭 타입 매개변수로 입력과 반환 타입의 관계를 보존한다.
2. 유니언 타입으로 값이 가질 수 있는 경우를 제한한다.
3. 판별 필드와 조건문으로 각 경우의 타입을 좁힌다.

[핵심개념]
제네릭(generic)은 실제 타입이 들어갈 자리를 T 같은 이름으로 표시해 코드를 재사용하는 방법입니다. first<T>(items: T[])의 T는 문자열 배열을 받으면 string, 숫자 배열을 받으면 number가 됩니다. any와 달리 입력 타입 정보가 반환값에도 이어집니다.

유니언(union)은 A | B처럼 여러 타입 중 하나임을 나타냅니다. 성공 객체와 실패 객체를 묶은 ApiResult<T>가 예입니다. 두 객체에 공통으로 있는 ok 필드가 각각 true와 false라는 리터럴 값을 가지면 판별 유니언(discriminated union)이 됩니다. if (result.ok) 조건 안에서는 컴파일러가 성공 객체로, else에서는 실패 객체로 범위를 줄입니다. 이것이 타입 좁히기(narrowing)입니다. typeof, in, instanceof 검사도 좁히기에 사용할 수 있습니다.

[따라하기]
새 폴더에 result.ts를 만들고 아래를 저장하세요.

```typescript
type ApiResult<T> =
  | { ok: true; data: T }
  | { ok: false; error: string };

function first<T>(items: T[]): T | undefined {
  return items[0];
}

function summarize(result: ApiResult<string[]>): string {
  if (result.ok) {
    const item = first(result.data);
    return item === undefined ? "항목 없음" : `첫 항목: ${item}`;
  }
  return `오류: ${result.error}`;
}

console.log(summarize({ ok: true, data: ["로그", "타입"] }));
console.log(summarize({ ok: false, error: "연결 실패" }));
```

Windows PowerShell과 macOS·Linux 모두 다음 두 명령을 실행합니다.

```text
npx tsc result.ts --strict --target ES2020
node result.js
```

첫 명령은 타입을 엄격하게 검사하고 JavaScript 파일을 만듭니다. 두 번째 명령의 예상 결과는 다음과 같습니다.

```text
첫 항목: 로그
오류: 연결 실패
```

first는 빈 배열에서 undefined를 돌려줄 수 있으므로 반환 타입에 이를 적고, summarize에서 먼저 검사했습니다. result.error는 실패 쪽에서만 안전하게 읽을 수 있습니다.

[흔한 실수]
편하다는 이유로 T 대신 any를 쓰면 입력과 출력 타입의 관계가 사라집니다. result.data와 result.error를 조건 검사 전에 읽거나, 빈 배열 가능성을 무시하는 것도 흔한 오류입니다. as로 타입을 강제로 단언하면 실제 값이 바뀌는 것이 아니므로 컴파일 오류를 숨기는 용도로 쓰지 마세요. 가능한 모든 경우를 유니언에 적고 판별 필드를 먼저 검사합니다.

[보안 주의]
TypeScript 타입은 컴파일 뒤 사라지므로 네트워크 응답과 JSON이 선언한 모양이라고 보장하지 않습니다. 외부 값은 먼저 unknown으로 받고, 객체 여부·ok·data·error의 실제 타입과 길이를 실행 중에 검증한 뒤 ApiResult로 바꾸세요. 오류 문자열에 토큰·비밀번호·개인정보를 담지 않고, 값을 확인하려고 eval을 사용하지 않습니다. 방어 목적의 본인 소유 로컬 예제에서만 실습하세요.

[직접 해볼 과제]
ApiResult<number[]>를 받는 summarizeNumbers 함수를 만드세요. 성공이면 첫 숫자를, 빈 배열이면 ‘숫자 없음’을, 실패면 오류 문구를 반환하게 하고 세 경우를 모두 실행해 보세요. 이어서 잘못된 성공 객체에서 data 대신 error를 읽으면 컴파일러가 어떤 오류를 내는지 확인하세요.

[확인문제]
1. 제네릭과 any의 가장 중요한 차이는 무엇인가요?
2. ok 필드가 성공과 실패 타입을 구분하는 데 어떻게 쓰이나요?
3. 외부 JSON을 타입 단언만으로 신뢰하면 안 되는 이유는 무엇인가요?

[다음 학습]
WEB-008에서 컴포넌트 기반 UI와 React 기초를 배우며 타입이 있는 화면 구성 요소를 만들어 봅니다.

[공식 참고 자료]
TypeScript 제네릭
https://www.typescriptlang.org/docs/handbook/2/generics.html

TypeScript 유니언 타입
https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types

TypeScript 타입 좁히기
https://www.typescriptlang.org/docs/handbook/2/narrowing.html

TypeScript unknown 타입
https://www.typescriptlang.org/docs/handbook/2/functions.html#unknown

댓글목록

등록된 댓글이 없습니다.

회원로그인

회원가입

사이트 정보

회사명 : 회사명 / 대표 : 대표자명
주소 : OO도 OO시 OO구 OO동 123-45
사업자 등록번호 : 123-45-67890
전화 : 02-123-4567 팩스 : 02-123-4568
통신판매업신고번호 : 제 OO구 - 123호
개인정보관리책임자 : 정보책임자명

접속자집계

오늘
1,857
어제
5,103
최대
16,772
전체
772,911
Copyright © 소유하신 도메인. All rights reserved.