TypeScript 유틸리티 타입 Omit<T, K> – 필요 없는 필드만 쏙 빼고 쓰기

2025. 12. 14. 19:35·FrontEnd/TypeScript

이번에는 Pick의 반대 방향 느낌인 Omit<T, K>를 정리해 본다

  • Pick
    기존 타입에서 필요한 것만 골라서 새 타입 만들기
  • Omit
    기존 타입에서 필요 없는 것만 빼고 새 타입 만들기

현실에서 더 자주 떠오르는 건 오히려 Omit일 때도 많다.


1. Omit<T, K>를 한 줄로 설명하면

Omit<T, K>는

타입 T에서 K에 해당하는 키들을 빼고
나머지 프로퍼티로만 새로운 타입을 만드는 도구

라고 보면 된다.


2. 기본 사용법부터 보기

type User = {
  id: number
  name: string
  email: string
  password: string
  isAdmin: boolean
}

// 비밀번호만 빼고 쓰고 싶을 때
type UserWithoutPassword = Omit<User, "password">

const user: UserWithoutPassword = {
  id: 1,
  name: "홍길동",
  email: "hong@example.com",
  isAdmin: false,
  // password는 아예 타입에 없음
}

느낌은 딱 이것이다.

  • 원본 타입을 기준으로 하고
  • "이 필드만 없었으면 좋겠다" 싶은 키를 빼서 새 타입을 만든다

3. Pick vs Omit 간단 비교

동일한 결과를 다른 방향에서 만드는 것도 가능하다.

type User = {
  id: number
  name: string
  email: string
  password: string
}

// 비밀번호를 제외한 타입

// 1) Omit으로 만들기
type UserWithoutPasswordByOmit = Omit<User, "password">

// 2) Pick으로 만들기
type UserWithoutPasswordByPick = Pick<User, "id" | "name" | "email">

두 타입은 결과적으로 같은 구조가 된다.

  • 숨길 필드가 몇 개 안 되면 Omit
  • 가져올 필드가 몇 개 안 되면 Pick

이 정도 느낌으로 선택해도 크게 문제 없다.
중요한 건 읽는 사람이 의도를 바로 이해할 수 있느냐다.


4. 실무에서 자주 쓰는 패턴들

4-1. API 응답에서 민감한 필드 제거

백엔드 타입 그대로 프론트에 노출시키고 싶지 않을 때가 많다.

type UserFromApi = {
  id: number
  name: string
  email: string
  passwordHash: string
  socialSecurityNumber: string
  // 기타 민감 정보들
}

// 프론트 앱에서만 쓸 "안전한" User 타입
type SafeUser = Omit<UserFromApi, "passwordHash" | "socialSecurityNumber">

이렇게 해두면

  • 프론트 코드에서 실수로 민감 필드를 쓰려고 하면 컴파일 단계에서 막힌다.
  • "이쪽 레이어에서는 이 정도 정보까지만 쓴다"라는 경계를 타입으로 표현할 수 있다.

물론 실제 데이터에서 민감 값을 완전히 제거하려면
런타임에서 따로 가공이 필요하지만,
타입 단계에서부터 의도를 보여주는 것도 꽤 도움이 된다.


4-2. 생성용 타입과 수정용 타입 나누기

신규 생성할 때와 수정할 때 필요한 필드가 다를 때가 많다.

type Post = {
  id: string
  title: string
  content: string
  createdAt: string
  updatedAt: string
}

// 새 글 만들 때 서버로 보내는 payload
type CreatePostPayload = Omit<Post, "id" | "createdAt" | "updatedAt">

// 글 수정할 때 쓸 수 있는 필드만 열어 둔 타입
type UpdatePostPayload = Partial<Pick<Post, "title" | "content">>

여기서 포인트는

  • "서버가 만들어 주는 값"은 생성용 타입에서 빼버리고
  • 클라이언트에서 직접 입력하는 값만 남기는 것

이렇게 해두면

  • 프론트에서 실수로 id나 createdAt 같은 값을 직접 건드리는 일을 줄일 수 있다.
  • 타입만 봐도 "이 API 호출 때 내가 보내야 할 데이터 범위"가 바로 보인다.

4-3. UI 전용 타입 만들 때

화면마다 보여주고 싶은 정보가 다를 수 있다.
User 전체를 넘겨도 되긴 하지만, 딱 필요한 것만 남기는 편이 읽기 좋을 때가 있다.

type User = {
  id: number
  name: string
  email: string
  isAdmin: boolean
}

// 일반 사용자 목록 화면에서는 관리자 여부가 중요하지 않을 때
type UserListItem = Omit<User, "isAdmin">

type UserListItemProps = {
  user: UserListItem
}

이렇게 해두면

  • 이 컴포넌트는 isAdmin에 관심이 없다는 게 타입으로 드러난다.
  • 관리자 여부가 바뀌더라도 이 화면과는 무관하다는 신호를 줄 수 있다.

5. Omit을 쓸 때 한 번 더 생각해 볼 점

5-1. 너무 많은 필드를 빼고 있다면

type UserPublic = Omit<
  User,
  "password" | "passwordHash" | "token" | "refreshToken" | "deletedAt"
>

이렇게 뺄 필드가 길어지면 읽는 사람이 힘들다.

  • "도대체 이 타입은 무엇을 위한 타입인가?"
  • "원본에서 거의 다 빼고 남은 건 뭔가?"

이런 생각이 드는 순간이 오면

  • 차라리 도메인에 맞게 새 타입을 선언하거나
  • 중간에 한 번 타입을 나눠서 이름을 붙이는 것도 방법이다.
type UserSensitiveFields = "password" | "passwordHash" | "token" | "refreshToken" | "deletedAt"

type UserPublic = Omit<User, UserSensitiveFields>

이렇게만 해도 의도가 훨씬 읽기 좋아진다.

5-2. Pick과 섞어 쓸 때

아주 자주 나오는 패턴 하나만 기억해 두면 좋다.

type User = {
  id: number
  name: string
  email: string
  password: string
}

// 특정 필드만 선택 + 일부만 optional
type UserUpdatePayload = Partial<Pick<User, "name" | "email">>

 

Omit도 비슷하게 섞어서 쓸 수 있다.

// 비밀번호는 제거하고, 나머지는 전부 optional 업데이트
type SoftUserUpdatePayload = Partial<Omit<User, "password">>

여기서 중요한 건

  • 유틸리티 타입을 얼마든지 합성할 수 있지만
  • 너무 과하면 "타입 퍼즐"이 돼서 나중에 본 사람이 해석하느라 고생한다는 점

"한 번에 이해되느냐"를 기준으로 끊어주는 게 좋다.


6. 정리 – Omit을 떠올리면 좋은 순간

나중에 이 글 다시 봤을 때를 위한 메모.

이럴 때 Omit을 먼저 떠올려 보기.

  • "이 타입에서 몇 개 필드만 빼고 나머지는 그대로 쓰고 싶다"
  • "민감한 필드나 서버 전용 필드를 프론트 타입에서 숨기고 싶다"
  • "생성용 타입에서 id, createdAt 같은 서버 전용 필드만 빼고 싶다"
  • "특정 화면에서는 일부 필드에 아예 접근하지 않는다는 걸 타입으로 표현하고 싶다"

반대로

  • 빠지는 필드가 너무 많아지면
    → 아예 도메인에 맞는 새 타입을 정의하는 것도 고려하기
  • Omit, Pick, Partial 등을 너무 많이 합성하면
    → 잠깐 볼 때 해석하기 어려운 타입이 될 수 있으니 중간에 이름 한 번 붙여 주기

Pick이 "필요한 것만 담는 가벼운 가방"이라면,
Omit은 "필요 없는 것만 빼고 정리한 배낭" 정도 느낌으로 기억해 두면 쓸 자리 구분하기가 조금 더 쉽다

저작자표시 비영리 변경금지 (새창열림)

'FrontEnd > TypeScript' 카테고리의 다른 글

TypeScript as const 이게 뭘까  (0) 2025.12.18
TypeScript 유틸리티 타입 Partial<T> – 부분만 채워도 되는 타입 만들기  (1) 2025.12.14
타입연산자 typeof, keyof, keyof typeof 패턴 정리  (0) 2025.12.14
TypeScript 유틸리티 타입 Pick<T, K> – 객체 타입에서 필요한 것만 뽑아 쓰기  (0) 2025.12.13
setTimeout() 반환값 정리 – 브라우저 vs Node에서 뭐가 다른지  (0) 2024.11.24
'FrontEnd/TypeScript' 카테고리의 다른 글
  • TypeScript as const 이게 뭘까
  • TypeScript 유틸리티 타입 Partial<T> – 부분만 채워도 되는 타입 만들기
  • 타입연산자 typeof, keyof, keyof typeof 패턴 정리
  • TypeScript 유틸리티 타입 Pick<T, K> – 객체 타입에서 필요한 것만 뽑아 쓰기
프론트엔드 개발자 jbeat
프론트엔드 개발자 jbeat
프론트엔드 개발자 블로그인데 일상도 쪼그으믐
  • 프론트엔드 개발자 jbeat
    jbeat 님의 블로그
    프론트엔드 개발자 jbeat
  • 전체
    오늘
    어제
    • 분류 전체보기 (44)
      • FrontEnd (43)
        • TypeScript (6)
        • JavaScript (18)
        • Next.js (3)
        • React (1)
        • Testing (2)
        • Third Party (1)
        • web (10)
        • Tooling (1)
        • coding test (0)
        • A.I (1)
      • 일상 (1)
        • wedding (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 인기 글

  • 태그

    javascript
    Android
    배열
    omit
    컬렉션
    pick
    코테
    CrossOrigin
    TypeScript
    preconnect
    yjs
    고차함수
    타입스크립트
    CRDT
    playwright
    Utility
    주니어
    Next.js
    이터러블
    WebSocket
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
프론트엔드 개발자 jbeat
TypeScript 유틸리티 타입 Omit<T, K> – 필요 없는 필드만 쏙 빼고 쓰기
상단으로

티스토리툴바