TypeScript 실무 효율을 200% 높이는 유틸리티 타입 핵심 정리
🎯 타겟 독자: TypeScript를 사용하지만 매번 interface를 새로 만드는 것이 귀찮은 프론트엔드/백엔드 개발자, 중복 코드를 줄이고 타입 안정성을 높이고 싶은 실무자.
📝 요약: TypeScript의 Utility Types는 기존 타입을 변형하여 새로운 타입을 만들어내는 강력한 기능입니다. 이 글에서는 실무에서 가장 빈번하게 사용되는 Pick, Omit, Partial, Record의 정확한 사용법과, 이를 조합하여 API 요청/응답 타입을 효율적으로 관리하는 패턴을 소개합니다.
1. 왜 유틸리티 타입을 써야 하나요?
개발을 하다 보면 하나의 User 인터페이스가 상황에 따라 조금씩 다르게 필요할 때가 있습니다.
- 회원가입 시: ID와 생성일은 필요 없음 (아직 안 만들어졌으니까)
- 프로필 수정 시: 이메일은 수정 불가 (Readonly 필요)
- 목록 조회 시: 비밀번호 필드는 제외 (보안상)
이때마다 UserSignupDto, UserUpdateDto를 일일이 새로 만드는 것은 중복이며 유지보수의 악몽입니다. 유틸리티 타입을 쓰면 원본 타입 하나로 모든 파생 타입을 만들어낼 수 있습니다.
2. 필수 유틸리티 타입 Best 4
① Pick <Type, Keys> : 쏙쏙 골라내기
거대한 타입에서 필요한 몇 가지 속성만 선택해서 새로운 타입을 만듭니다.
② Omit <Type, Keys> : 콕 집어 빼기
Pick의 반대입니다. 특정 속성만 제거하고 나머지는 다 가져옵니다.
③ Partial <Type> : 모두 선택 사항으로
모든 속성을 Optional (?) 상태로 만듭니다. 주로 PATCH(수정) API 요청 타입에 쓰입니다.
④ Record <Keys, Type> : 객체 사전 만들기
키(Key)와 값(Value)의 타입이 고정된 객체(Dictionary/Map)를 정의할 때 가장 깔끔합니다.
3. 실무 응용 패턴 (조합해서 쓰기)
유틸리티 타입은 중첩해서 쓸 때 진가를 발휘합니다.
예를 들어, "회원 정보를 수정하되, ID는 수정 못 하고, 나머지 필드는 선택적으로 보내도 된다"는 요구사항을 코드로 표현하면 다음과 같습니다.
4. 결론
TypeScript의 유틸리티 타입을 잘 활용하면 "단 하나의 진실된 타입(Single Source of Truth)"을 유지할 수 있습니다.
원본 인터페이스인 User가 바뀌면, Pick이나 Omit으로 파생된 DTO들도 자동으로 같이 바뀝니다. 코드를 복사-붙여넣기 하지 마세요. 타입에게 계산을 맡기세요.