안녕하세요, 매일 TypeScript와 씨름하는 프론트엔드 개발자입니다. 솔직히 말해서 처음 TypeScript 4.x를 쓸 때만 해도 "이 정도면 충분하지 않나?" 싶었는데, TypeScript 5가 나오고 나서 실무에서 쓰는 타입 패턴이 정말 많이 바뀌었어요. 데코레이터 표준화, const 타입 파라미터, satisfies 연산자 등 한 번 맛보면 돌아갈 수 없는 기능들이 쏟아져 나왔거든요. 오늘은 제가 실무 프로젝트에서 1년 넘게 굴려보면서 정말 자주 쓰게 된 TypeScript 5 패턴들을 정리해보려고 합니다. 단순한 문법 소개가 아니라, 어떤 상황에서 왜 이 패턴을 써야 하는지, 그리고 어떤 함정이 있는지까지 솔직하게 다뤄볼게요.
이 글에서 다루는 패턴은 여전히 그대로 유효하지만, 그사이 버전이 꽤 올라갔습니다. 정리하면 이렇습니다.
- TypeScript 5.9(2025-08): import defer * as 문법과 --module node20이 추가됐고, tsc --init이 nodenext·esnext·strict·moduleDetection force 같은 모던 기본값으로 tsconfig를 만들어줍니다.
- TypeScript 6.0(2026-03-23 정식): 기존 JS 기반 컴파일러의 마지막 메이저이자 7.0으로 가는 전환 릴리스입니다. 기본값이 strict: true, module: esnext, target: es2025로 바뀌었고, outFile·moduleResolution classic·amd/umd/systemjs가 제거돼 모던 ESM 표준으로 정리됐어요.
- TypeScript 7.0 Beta(2026-04-21 공개): 컴파일러를 Go로 재작성한 네이티브 포팅(코드명 Corsa)으로, 약 10배 빠른 빌드를 목표로 합니다. 정식 7.0은 2026년 6~7월경 출시가 예상됩니다.
목차
- 2026년 최신: TS 6.0 정식과 7.0 Beta, 무엇이 달라지나
- satisfies 연산자, 이래서 다들 쓰는구나
- 제네릭 타입 패턴, 실무에서 진짜 쓰는 것들
- 유틸리티 타입 조합으로 코드 줄이기
- 장단점 비교와 추천 대상
2026년 최신: TS 6.0 정식과 7.0 Beta, 무엇이 달라지나
6.0 — 기본값이 "모던"으로 바뀌었다
TypeScript 6.0의 핵심은 신기능보다 기본값 정리입니다. 새 프로젝트를 tsc --init으로 시작하면 이제 strict가 켜진 채로, module은 esnext, target은 es2025로 잡힙니다. 위의 실무 팁에서 "strict는 처음부터 다 켜라"고 했는데, 6.0부터는 아예 기본이 그렇게 됐어요. 반대로 outFile, moduleResolution classic, amd/umd/systemjs처럼 번들러 시대에 거의 안 쓰던 레거시 옵션은 제거됐습니다. 오래된 빌드 스크립트를 쓰고 있다면 6.0 업그레이드 전에 이 부분을 먼저 확인해야 합니다.
7.0 Beta — Go로 다시 쓴 컴파일러, 체감 빌드 10배
7.0은 컴파일러 자체를 Go로 재작성한 네이티브 버전입니다. 실측 수치가 인상적인데, VS Code 코드베이스(약 150만 줄) 기준 tsc 78초가 tsgo로 7.5초, Sentry는 133초에서 16초로 줄었습니다. 설치는 npm install -D @typescript/native-preview@beta 후 tsgo 명령으로 쓰면 되고, 정식 출시 때는 기존 tsc로 통합될 예정입니다.
빠르다고 바로 갈아타기엔 이릅니다. 현재 Beta는 watch 모드, 프로그래밍 API, 일부 선언(declaration) emit이 미완성이라 7.1 이후로 예정돼 있어요. 그래서 지금은 타입 체크나 CI 빌드 가속 용도로 기존 tsc와 병행하며 점진 도입하는 걸 권합니다. 메인 빌드 파이프라인 전체를 tsgo로 바꾸는 건 정식 7.0 출시 이후가 안전합니다.
satisfies 연산자, 이래서 다들 쓰는구나
as 단언과 명시적 타입 지정의 한계
예전에는 객체 리터럴에 타입을 강제하고 싶을 때 두 가지 선택지밖에 없었어요. 변수에 타입을 명시하거나(const config: Config = {...}), as로 단언하는 거죠. 근데 둘 다 문제가 있어요. 타입을 명시하면 리터럴 타입 정보가 다 날아가서 자동완성이 어색해지고, as는 타입 검증 자체를 우회해버려서 위험합니다. 저도 예전에 as Color로 단언했다가 오타 잡지 못해서 프로덕션에 버그 흘려보낸 적이 있어요.
satisfies로 두 마리 토끼 잡기
satisfies 연산자는 "이 값이 해당 타입을 만족하는지 검증은 하되, 실제 추론된 좁은 타입은 그대로 유지"해줍니다. 예를 들어 라우터 설정 객체에서 각 키별 핸들러 타입은 그대로 좁게 유지하면서, 전체적으로는 RouteConfig 타입을 만족하는지 검증하고 싶을 때 딱이에요. 실무에서 디자인 토큰, API 엔드포인트 매핑, 권한 정의 같은 곳에서 정말 많이 씁니다. 한 번 써보면 왜 진작 이게 안 나왔나 싶을 정도예요.
제네릭 타입 패턴, 실무에서 진짜 쓰는 것들
const 타입 파라미터로 추론 정확도 올리기
TypeScript 5에서 추가된 const 제네릭은 정말 신세계입니다. 함수 인자로 배열이나 객체를 넘길 때 자동으로 readonly 튜플 타입으로 추론되도록 해주는 기능인데요, 폼 라이브러리나 라우터 같은 거 만들 때 사용자가 "as const"를 안 붙여도 정확한 타입을 추론할 수 있게 해줍니다. 제가 사내 폼 빌더를 만들면서 이 기능 덕분에 사용자 측 코드가 훨씬 깔끔해졌어요. 라이브러리 만드는 입장이라면 무조건 알아둬야 할 패턴입니다.
조건부 타입과 infer 조합
제네릭의 진짜 힘은 조건부 타입과 infer를 같이 쓸 때 나옵니다. API 응답 타입에서 data 필드만 뽑아낸다든지, 함수의 첫 번째 인자 타입만 추출한다든지 할 때 유용해요. 다만 너무 복잡하게 쓰면 동료들이 코드 리뷰에서 한숨 쉬니까 적당한 선에서 추상화하는 게 좋습니다. 저는 보통 한 파일에 3단계 이상 중첩된 조건부 타입은 안 쓰려고 노력해요. 디버깅 지옥이 펼쳐지거든요.
제네릭 제약 조건 활용
extends 키워드로 제네릭에 제약을 거는 건 기본 중의 기본인데, 의외로 잘 안 쓰는 분들이 많더라고요. T extends keyof Obj 같은 패턴은 객체의 키만 받아야 하는 함수에서 필수예요. 안 그러면 타입스크립트가 너무 관대해져서 런타임 에러가 나기 쉽습니다.
유틸리티 타입 조합으로 코드 줄이기
Pick, Omit, Partial의 실전 조합
이건 거의 매일 쓰는 패턴이에요. 폼 데이터 타입에서 서버로 보낼 때는 일부 필드만 빼고(Omit), 수정 폼에서는 일부만 변경 가능하게(Partial) 하는 식으로요. 저희 팀은 CreateDto, UpdateDto, ReadDto 같은 걸 다 손으로 정의하다가 유틸리티 타입으로 바꾸고 나서 타입 정의 파일이 절반으로 줄었습니다.
NoInfer로 추론 방향 제어하기
TypeScript 5.4에서 추가된 NoInfer는 진짜 숨은 보석이에요. 제네릭 추론할 때 특정 위치에서는 추론에 영향을 주지 않게 하고 싶을 때 쓰는데, defaultValue 같은 거 받을 때 default 때문에 타입이 이상하게 넓어지는 문제를 깔끔하게 해결해줍니다. 알고 있으면 라이브러리 디자인 수준이 한 단계 올라갑니다.
장단점 비교와 추천 대상
주요 패턴 한눈에 보기
| 패턴 | 장점 | 단점 | 추천 상황 |
|---|---|---|---|
| satisfies 연산자 | 타입 안전성과 추론 정확도 동시 확보 | TS 4.9 이하 호환 불가 | 설정 객체, 디자인 토큰 |
| const 제네릭 | 사용자 측 as const 불필요 | 라이브러리 외부 사용 시 체감 적음 | 라이브러리, 유틸 함수 |
| 조건부 타입 + infer | 강력한 타입 추출 가능 | 가독성 급격히 저하 | 타입 헬퍼, 라이브러리 내부 |
| 유틸리티 타입 조합 | 중복 제거, 유지보수 편함 | 타입 추적이 어려워짐 | DTO, 폼 모델 정의 |
| NoInfer | 추론 방향 정밀 제어 | TS 5.4 이상 필요 | 기본값 받는 제네릭 함수 |
실무 활용 팁 3가지
- 첫째, satisfies는 일단 객체 리터럴에 무조건 붙여보세요. 안 써도 되는 곳에선 IDE가 알려주니까 일단 적용해보고 빼는 게 빠릅니다.
- 둘째, 복잡한 타입은 // @ts-expect-error로 의도를 표시하지 말고 별도 타입 헬퍼로 분리하세요. 6개월 뒤의 나를 위한 배려입니다.
- 셋째, tsconfig에서 strict 옵션을 다 켜고 시작하세요. 나중에 켜는 건 정말 지옥입니다. 저도 레거시 프로젝트 마이그레이션하다가 일주일 날린 적 있어요.
- 넷째, 타입 단언(as) 대신 타입 가드 함수를 만드는 습관을 들이면 런타임 안전성이 확 올라갑니다.
이런 분들께 추천합니다
TypeScript 5의 새 패턴들은 단순히 신기능이 아니라 실무 코드 품질을 한 단계 끌어올려주는 도구입니다. 특히 사내 라이브러리나 디자인 시스템을 만드는 분, 폼이나 API 클라이언트처럼 타입 안전성이 중요한 영역을 다루는 분, 그리고 팀 코드의 일관성을 고민하는 시니어 개발자분들께 강력히 추천드려요. 반대로 단순 페이지 작업만 하시거나 빠르게 프로토타입을 만드는 단계라면 굳이 다 익힐 필요는 없습니다. 필요할 때 하나씩 도입하셔도 충분해요. 결국 TypeScript 5의 타입 패턴, 제네릭 활용법은 알면 알수록 코드가 짧아지고 안전해지는 마법 같은 도구입니다. 오늘 소개한 패턴 중 하나만이라도 내일 코드에 적용해보시면, 분명 "아 이래서 쓰는구나" 싶으실 거예요.