๐Ÿง™โ€โ™‚๏ธ 05. ๊ณ ๊ธ‰ ํƒ€์ž… ์กฐ์ž‘: ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ถŒํ•œ ๋งตํ•‘ ํ‘๋งˆ๋ฒ•

2026๋…„ 3์›” 5์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

keyof, typeof, Mapped Types๋ฅผ ํ™œ์šฉํ•ด ์ค‘๋ณต ์—†๋Š” ์„ ์–ธ์ ์ธ ํƒ€์ž… ์‹œ์Šคํ…œ ์„ค๊ณ„ํ•˜๊ธฐ

๐Ÿ“Œ ์ด ๋ฌธ์„œ๋ฅผ ์ฝ๊ธฐ ์ „์—

โฑ๏ธ ์˜ˆ์ƒ ์ฝ๊ธฐ ์‹œ๊ฐ„: 15๋ถ„(์ „์ฒด) / ํ•ต์‹ฌ ํŒŒํŠธ๋งŒ: 8๋ถ„

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ํ๋ฆ„
[typeof์™€ keyof์˜ ์ง„์งœ ์˜๋ฏธ] โ†’ [๋งต๋“œ ํƒ€์ž…(Mapped Types)์œผ๋กœ ๋…ธ๊ฐ€๋‹ค ํƒˆ์ถœํ•˜๊ธฐ] โ†’ [์กฐ๊ฑด๋ถ€ ํƒ€์ž…(Conditional Types) ๋ง›๋ณด๊ธฐ]

๐ŸŽฏ ์ด ๋ฌธ์„œ๋ฅผ ๋‹ค ์ฝ์œผ๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ

  • ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ๊ฐ’(Value) ๊ณต๊ฐ„์—์„œ ํ™œ๋™ํ•˜๋Š” ๋ณ€์ˆ˜๋ฅผ ํƒ€์ž…(Type) ๊ณต๊ฐ„์œผ๋กœ ๊น”๋”ํ•˜๊ฒŒ ๋Œ์–ด์˜ฌ๋ฆด ์ˆ˜ ์žˆ๋‹ค.
  • ์ˆ˜์‹ญ ๊ฐœ์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง„ ๊ฐ์ฒด ํƒ€์ž…์„ ๋‹จ 3์ค„์˜ ์ฝ”๋“œ๋กœ ์ผ๊ด„ ๋ณ€ํ™˜(Mapped Type)ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • 5๋…„ ์ฐจ ์ˆ˜์ค€์˜ ์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํƒ€์ž…(Partial, Pick, Omit์˜ ๋‚ด๋ถ€ ์›๋ฆฌ)์„ ์ดํ•ดํ•˜๊ณ  ์ง์ ‘ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๐Ÿ—บ๏ธ ์ด ๋ฌธ์„œ์˜ ๋ฐฐ๊ฒฝ ์„ธ๊ณ„๊ด€: '์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ'

  • ๐Ÿฃ ์˜์ฒ  ( ์‹ ์ž… ): "๋ฆฌ๋“œ ๋‹˜! ๋ฐฑ์—”๋“œ์—์„œ ์‚ฌ์šฉ์ž ํ”„๋กœํ•„ ์ •๋ณด(UserProfile)๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”๋ฐ, ๊ฐ€์ž…ํ•  ๋•Œ ์“ฐ๋Š” '์ˆ˜์ • ๊ฐ€๋Šฅํ•œ ํผ ๋ฐ์ดํ„ฐ' ํƒ€์ž…์„ ์ƒˆ๋กœ ๋งŒ๋“ค์–ด์•ผ ํ•ด์š”. ๊ธฐ์กด UserProfile ๋ณต์‚ฌํ•ด์„œ id ๋นผ๊ณ  ์ „๋ถ€ boolean์ด๋‚˜ optional๋กœ ํ•˜๋‚˜ํ•˜๋‚˜ ๋ฐ”๊พธ๊ณ  ์žˆ๋Š”๋ฐ ๋ˆˆ ๋น ์ง€๊ฒ ์Šต๋‹ˆ๋‹ค."
  • ๐Ÿฆ ์˜ํ˜ธ ( ๋ฆฌ๋“œ ): "์˜์ฒ  ๋‹˜, ๊ฐœ๋ฐœ์ž์˜ ๋ฏธ๋•์€ ๋„ทํ”Œ๋ฆญ์Šค๋ฅผ ๋ณผ ์‹œ๊ฐ„์„ ๋ฒŒ๊ธฐ ์œ„ํ•ด ์ค‘๋ณต ํƒ€์ดํ•‘์„ ๊ทน๋„๋กœ ํ˜์˜คํ•˜๋Š” ๊ฒ๋‹ˆ๋‹ค. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ๊ธฐ์กด์— ์žˆ๋Š” ํƒ€์ž…์„ ์ด๋ฆฌ์ €๋ฆฌ ์ง€์ง€๊ณ  ๋ณถ์•„์„œ(Manipulation) ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ๋š๋”ฑ ๋งŒ๋“ค์–ด๋‚ด๋Š” 'ํ‘๋งˆ๋ฒ•'์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋Š˜ ๊ทธ ๋งˆ๋„์„œ๋ฅผ ํŽผ์ณ๋ณด์ฃ ."

๐Ÿค” ์™œ ์•Œ์•„์•ผ ํ•˜๋Š”๊ฐ€: '๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ธฐ'์˜ ๋์—†๋Š” ๋Šช

์ดˆ๋ณด ์‹œ์ ˆ์˜ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” "๋‚ด๊ฐ€ ๋งŒ๋“  ๋ณ€์ˆ˜์— ์ธํ„ฐํŽ˜์ด์Šค ํ•˜๋‚˜ ๋‹ฌ์•„์ฃผ๊ธฐ" ์ •๋„๋ฉด ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์ง€๋ฉด "๊ธฐ์กด์— ์žˆ๋Š” A ํƒ€์ž…์„ ์•„์ฃผ ์‚ด์ง๋งŒ ๋ฐ”๊ฟ”์„œ B ํƒ€์ž…์„ ๋งŒ๋“ค๊ณ  ์‹ถ๋‹ค" ๋Š” ์š•๋ง์ด ๋“์–ด์˜ค๋ฆ…๋‹ˆ๋‹ค.

์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๊ถŒํ•œ ๊ฐ์ฒด๊ฐ€ ์žˆ๋‹ค๊ณ  ์นฉ์‹œ๋‹ค.

// ๐Ÿฃ ์˜์ฒ ์ด์˜ ๋ณต๋ถ™ ๋…ธ๊ฐ€๋‹ค
interface UserProfile {
  id: number;
  name: string;
  email: string;
  age: number;
}
 
// ํšŒ์› ์ •๋ณด ์ˆ˜์ • ํผ์„ ์œ„ํ•ด ๋ชจ๋“  ํ•„๋“œ๋ฅผ ์„ ํƒ์ (Optional)์œผ๋กœ ๋งŒ๋“ค๊ณ  ์‹ถ์Œ
interface UserProfileUpdateForm {
  id?: number;
  name?: string;
  email?: string;
  age?: number;
}

๋‚˜์ค‘์— ์˜์ˆ˜(๋ฐฑ์—”๋“œ)๊ฐ€ UserProfile์— phoneNumber: string์„ ์ถ”๊ฐ€ํ•˜๋ฉด ์–ด๋–ป๊ฒŒ ๋ ๊นŒ์š”?
๋„ค, ์˜์ฒ ์ด๋Š” ๋˜ ์•ผ๊ทผํ•˜๋ฉฐ UserProfileUpdateForm์„ ์ฐพ์•„ phoneNumber?: string์„ ์†์ˆ˜ ์ ์–ด ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์ง“์„ ๋ง‰๊ธฐ ์œ„ํ•ด 5๋…„ ์ฐจ ๊ฐœ๋ฐœ์ž๋“ค์€ ํƒ€์ž… ์กฐ์ž‘(Type Manipulation) ์„ ๋ฌด๊ธฐ๋กœ ์‚ผ์Šต๋‹ˆ๋‹ค.


๐Ÿชž 1. ๊ฐ’(Value)๊ณผ ํƒ€์ž…(Type)์˜ ์„ธ๊ณ„๋ฅผ ๊ฐ€๋กœ์ง€๋ฅด๊ธฐ: typeof & keyof

์ด ํ‘๋งˆ๋ฒ•์˜ ์ฒซ ๋‹จ์ถ”๋Š” JS ์„ธ์ƒ์˜ ๋Ÿฐํƒ€์ž„ ๋ฐ์ดํ„ฐ์™€ TS ์„ธ์ƒ์˜ ์ปดํŒŒ์ผ ํƒ€์ž…์„ ์ž์œ ์ž์žฌ๋กœ ๋„˜๋‚˜๋“œ๋Š” ์—ฐ์‚ฐ์ž๋“ค์ž…๋‹ˆ๋‹ค.

typeof: JS ๋ณ€์ˆ˜์—์„œ ํƒ€์ž… ๋ฝ‘์•„์˜ค๊ธฐ

// JS์˜ ๊ฐ’(Value) ์„ธ์ƒ
const ROLE_NAMES = {
  ADMIN: "์ตœ๊ณ  ๊ด€๋ฆฌ์ž",
  MANAGER: "๊ฒŒ์‹œํŒ ๊ด€๋ฆฌ์ž",
  USER: "์ผ๋ฐ˜ ์‚ฌ์šฉ์ž"
};
 
// ๐Ÿฆ ์˜ํ˜ธ: "์ € ๊ฐ์ฒด์˜ ๋ชจ์–‘ํ‘œ๋ฅผ ๊ทธ๋Œ€๋กœ ํƒ€์ž… ์„ธ์ƒ์œผ๋กœ ๋‚ฉ์น˜ํ•ด ๋ด…์‹œ๋‹ค!"
type RoleMap = typeof ROLE_NAMES;
/*
๊ฒฐ๊ณผ:
type RoleMap = {
  ADMIN: string;
  MANAGER: string;
  USER: string;
}
*/

์ด ๊ธฐ๋ฒ•์€ Redux์˜ ์ดˆ๊ธฐ ์ƒํƒœ(initialState)๋‚˜ ๊ณตํ†ต ์ƒ์ˆ˜ ๊ฐ์ฒด์—์„œ๋ถ€ํ„ฐ ํƒ€์ดํ•‘์„ ์‹œ์ž‘ํ•  ๋•Œ ๊ต‰์žฅํžˆ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. JS ์ฝ”๋“œ๋ฅผ ๋จผ์ € ์งœ๊ณ , ๊ทธ ์œ„์— TS๋ฅผ ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ์–น๋Š” ๋ฐฉ์‹์ด์ฃ .

keyof: ๊ฐ์ฒด์˜ 'ํ‚ค'๋“ค๋งŒ ๋ฝ‘์•„์„œ ์œ ๋‹ˆ์–ธ์œผ๋กœ ๋งŒ๋“ค๊ธฐ

๊ฐ์ฒด์˜ ํƒ€์ž…์„ ํ†ต์งธ๋กœ ๋ฝ‘๋Š” ๊ฒŒ typeof๋ผ๋ฉด, ๊ทธ ๊ฐ์ฒด์˜ ํ‚ค(Key)๊ฐ’๋“ค๋งŒ ๋นผ๊ณกํžˆ ๋ฝ‘์•„๋‚ด๊ณ  ์‹ถ์„ ๋•Œ๋Š” keyof๋ฅผ ์”๋‹ˆ๋‹ค.

type UserKeys = keyof UserProfile;
// ๊ฒฐ๊ณผ: "id" | "name" | "email" | "age"
 
// ํ™œ์šฉ: ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฌด์กฐ๊ฑด UserProfile์˜ ํ‚ค๊ฐ’ ์ค‘ ํ•˜๋‚˜๋งŒ ๋“ค์–ด์˜ค๋„๋ก ๊ฐ•์ œ!
function getProperty(user: UserProfile, key: keyof UserProfile) {
  return user[key]; 
}
 
getProperty(myUser, "name"); // โœ… ํ†ต๊ณผ
// getProperty(myUser, "password"); // โŒ ์—๋Ÿฌ: password๋Š” UserProfile์˜ ํ‚ค๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค!

๐ŸŽจ 2. ๋งต๋“œ ํƒ€์ž… (Mapped Types): ํƒ€์ž…๋“ค์˜ ๋Œ€๋Ÿ‰ ์ƒ์‚ฐ ๊ณต์žฅ

์ž, ์ด์ œ ์˜์ฒ ์ด์˜ ์•ผ๊ทผ ์›ํ‰์ด์—ˆ๋˜ ๋ณต๋ถ™ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ๋ด…์‹œ๋‹ค.
๋ฐฐ์—ด์„ ๋Œ ๋•Œ .map()์„ ์“ฐ๋“ฏ, ๊ฐ์ฒด์˜ ๋ชจ๋“  ํ‚ค๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ์†์„ฑ์„ ์ผ๊ด„ ๋ณ€๊ฒฝํ•˜๋Š” ๋งˆ๋ฒ•์ด ๋ฐ”๋กœ ๋งต๋“œ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

// ๐Ÿฆ ์˜ํ˜ธ: "T๋ผ๋Š” ๊ฐ์ฒด๊ฐ€ ๋“ค์–ด์˜ค๋ฉด, ๊ทธ ๊ฐ์ฒด์˜ ๋ชจ๋“  ํ‚ค(K)๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ์˜ต์…”๋„(?)์„ ๋ถ™์—ฌ๋ฒ„๋ ค!"
 
type MakeOptional<T> = {
  [K in keyof T]?: T[K]; // ๋งˆ๋ฒ•์˜ ๊ณต์‹!
};
 
// ์˜์ฒ ์ด์˜ ๊ตฌ์„ธ์ฃผ
type UserProfileUpdateForm = MakeOptional<UserProfile>;
/* 
๊ฒฐ๊ณผ:
type UserProfileUpdateForm = {
    id?: number | undefined;
    name?: string | undefined;
    email?: string | undefined;
    age?: number | undefined;
}
*/

์ด ํŒจํ„ด์€ ๋„ˆ๋ฌด๋‚˜๋„ ๋งŽ์ด ์“ฐ์—ฌ์„œ, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์•„์˜ˆ Partial<T> ๋ผ๋Š” ์ด๋ฆ„์œผ๋กœ ๋‚ด์žฅ ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์„ ๋งŒ๋“ค์–ด ๋‘์—ˆ์Šต๋‹ˆ๋‹ค. Readonly<T>, Pick<T, K>, Omit<T, K> ๋“ฑ ์—ฌ๋Ÿฌ๋ถ„์ด ์“ฐ๋Š” ์œ ์šฉํ•œ ๋ฌธ๋ฒ•๋“ค์ด ์ „๋ถ€ ์ด ๋งต๋“œ ํƒ€์ž…๊ณผ keyof๋กœ ๋งŒ๋“ค์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.


โš–๏ธ 3. ์กฐ๊ฑด๋ถ€ ํƒ€์ž… (Conditional Types): ํƒ€์ž…์—๋„ If๋ฌธ์ด ์žˆ๋‹ค

๋•Œ๋กœ๋Š” ์‚ผํ•ญ ์—ฐ์‚ฐ์ž(A ? B : C)์ฒ˜๋Ÿผ "์ด ํƒ€์ž…์ด ์ €๊ธฐ๋ฅผ ๋งŒ์กฑํ•˜๋ฉด A๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์•„๋‹ˆ๋ฉด B๋ฅผ ๋ฐ˜ํ™˜ํ•ด!" ๋ผ๋Š” ๋กœ์ง์ด ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. (์ฃผ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ œ์ž‘์ž๋“ค์ด ๋งŽ์ด ์”๋‹ˆ๋‹ค.)

// T๊ฐ€ ๋ฌธ์ž์—ด์ด๋ฉด ์ˆซ์ž ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์•„๋‹ˆ๋ฉด ๊ทธ๋ƒฅ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•˜๋ผ!
type NumberIfString<T> = T extends string ? number : string;
 
type Test1 = NumberIfString<"์•ˆ๋…•">; // Test1์€ number ํƒ€์ž…์ด ๋จ
type Test2 = NumberIfString<boolean>; // Test2๋Š” string ํƒ€์ž…์ด ๋จ

์‹ค๋ฌด์—์„œ๋Š” ์ด๋ฅผ ํ™œ์šฉํ•ด ํŠน์ • ํƒ€์ž…๋งŒ ํ•„ํ„ฐ๋งํ•˜๊ฑฐ๋‚˜ ์ถ”์ถœํ•˜๋Š” ๋ฐ ์”๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์œ„์—์„œ ๋งŒ๋“  UserProfile์—์„œ ๊ฐ’์ด string์ธ ํ”„๋กœํผํ‹ฐ ํ‚ค๊ฐ’๋งŒ ๋ฝ‘์•„๋‚ด๊ณ  ์‹ถ์„ ๋•Œ ์ด๋Ÿฐ ์กฐ๊ฑด๋ถ€ ํ‘๋งˆ๋ฒ•์„ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. (์ดˆ๋ณด์ž๋Š” ๋‹น์žฅ ๋ชฐ๋ผ๋„ ๋ฉ๋‹ˆ๋‹ค, ์ด๊ฒƒ์ด 5๋…„ ์ฐจ์˜ ๋ง›๋ณด๊ธฐ์ž…๋‹ˆ๋‹ค!)


๐Ÿ“ ๋งˆ๋ฌด๋ฆฌ ํ€ด์ฆˆ

Q1. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์˜ ์ƒ์ˆ˜ ํŒŒ์ผ(const COLORS = { RED: '#f00', BLUE: '#00f' })์ด ์žˆ์„ ๋•Œ, ์ด ๊ฐ์ฒด์˜ ํ˜•ํƒœ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ type ColorsType์„ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด๋‚ด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์–ด๋–ค ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋‚˜์š”?

โœ… ์ •๋‹ต: typeof ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: type ColorsType = typeof COLORS;)

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • JS์˜ ๋Ÿฐํƒ€์ž„ ๊ฐ’์œผ๋กœ๋ถ€ํ„ฐ TS์˜ ํƒ€์ž… ๊ตฌ์กฐ๋ฅผ ์ถ”์ถœ(์ถ”๋ก )ํ•  ๋•Œ ์ฒซ ๋ฒˆ์งธ ๊ด€๋ฌธ์ด ๋ฐ”๋กœ typeof ํ‚ค์›Œ๋“œ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‚˜์ค‘์— ์ƒ์ˆ˜ ๊ฐ์ฒด์— GREEN: '#0f0'์ด ์ถ”๊ฐ€๋˜๋”๋ผ๋„ ColorsType์— ์ž๋™์œผ๋กœ GREEN์ด ํฌํ•จ๋˜๋ฏ€๋กœ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ๊ทน๋„๋กœ ํŽธํ•ด์ง‘๋‹ˆ๋‹ค.

Q2. keyof ์—ฐ์‚ฐ์ž๋ฅผ ๋ฐฐ์—ด(Array) ํƒ€์ž…์— ์ ์šฉํ•˜๋ฉด ์–ด๋–ค ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋ ๊นŒ์š”? (์˜ˆ: type ArrayKeys = keyof string[];)

โœ… ์ •๋‹ต: ๋ฐฐ์—ด์˜ ์ธ๋ฑ์Šค์ธ number ํ˜•ํƒœ์™€ ๋ฐฐ์—ด ํ”„๋กœํ† ํƒ€์ž…์— ์žˆ๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„๋“ค("length" | "push" | "pop" | "map" ๋“ฑ...)์ด ํ†ต์งธ๋กœ ์œ ๋‹ˆ์–ธ์œผ๋กœ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • keyof๋Š” ๊ฐ์ฒด์˜ "ํ‚ค"๋ฅผ ์ถ”์ถœํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด ์—ญ์‹œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ๋Š” ์ธ๋ฑ์Šค(0, 1, 2...)๋ฅผ ํ‚ค๋กœ ๊ฐ€์ง€๊ณ  ๋ฆฌ์ŠคํŠธ ๊ด€๋ จ ๋ฉ”์„œ๋“œ๋ฅผ ์†์„ฑ์œผ๋กœ ๊ฐ–๋Š” ๊ฑฐ๋Œ€ํ•œ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ ๋ฐฐ์—ด์— ๋Œ€๊ณ  keyof๋ฅผ ์“ฐ๋ฉด ์‚ฌ์‹ค์ƒ ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊น”๋”ํ•œ ๋ฐ์ดํ„ฐ๋ณด๋‹ค ๋‚ด์žฅ ํ•จ์ˆ˜ ์ด๋ฆ„์ด ์Ÿ์•„์ ธ ๋‚˜์˜ค๊ฒŒ ๋˜๋ฏ€๋กœ, ๋ฐฐ์—ด ๋‚ด๋ถ€ ์š”์†Œ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ๋Š” T[number] ํ˜•ํƒœ์˜ ์ธ๋ฑ์Šค๋“œ ์•ก์„ธ์Šค(Indexed Access)๋ฅผ ๋” ์ž์ฃผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Q3. [์˜์ฒ ์ด์˜ ํ…Œ์ŠคํŠธ ํƒ€์ž„: ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํŠธ๋ ˆ์ด๋“œ์˜คํ”„] ์˜์ˆ˜๋„ค ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ API ๊ณตํ†ต ์œ ํ‹ธ ํด๋”๋ฅผ ๋ณด๋˜ ์˜์ฒ ์ด๊ฐ€ ๊นœ์ง ๋†€๋ž๋‹ˆ๋‹ค. "๋ฆฌ๋“œ ๋‹˜! TS ๋‚ด์žฅ ์œ ํ‹ธ๋ฆฌํ‹ฐ์ธ Partial<T>, Required<T>, Readonly<T> ๊ฐ™์€ ๊ฒŒ ์ „๋ถ€ ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ๊นŒ๋ณด๋‹ˆ [P in keyof T] ๋ผ๋Š” ๋˜‘๊ฐ™์€ ๋ฌธ๋ฒ•์œผ๋กœ ์‹œ์ž‘ํ•˜๋„ค์š”? ์ด๊ฑด ๋ญ”๊ฐ€์š”?" ๋ผ๊ณ  ๋ฌป๋Š” ์˜์ฒ ์—๊ฒŒ ์˜ํ˜ธ๋Š” ์–ด๋–ค ๊ฐœ๋…์„ ์„ค๋ช…ํ•ด ์ค„๊นŒ์š”?

โœ… ์ •๋‹ต: "์˜์ฒ  ๋‹˜, ๊ทธ๊ฒŒ ๋ฐ”๋กœ ๋งต๋“œ ํƒ€์ž…(Mapped Type)์˜ ํ•ต์‹ฌ ๊ณจ๊ฒฉ์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด์˜ ํ‚ค๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ์†์„ฑ์„ ์ผ๊ด„ ์กฐ์ž‘ํ•˜๋Š” ๋งˆ๋ฒ•์ด์ฃ ."

๐Ÿ’ก ์ƒ์„ธ ํ•ด์„ค:

  • ์›๋ฆฌ ์„ค๋ช…: [P in keyof T]๋Š” ๋งˆ์น˜ JS์˜ for...in ๋ฐ˜๋ณต๋ฌธ์ฒ˜๋Ÿผ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. T๋ผ๋Š” ๊ฐ์ฒด์˜ ๋ชจ๋“  ํ‚ค(keyof T)๋ฅผ ํ•˜๋‚˜์”ฉ P๋ผ๋Š” ๋ณ€์ˆ˜์— ๋‹ด์•„๊ฐ€๋ฉด์„œ, ๊ทธ ๊ฒฐ๊ณผ๋ฌผ ํƒ€์ž…์„ ์˜ต์…”๋„(?:), ์ฝ๊ธฐ ์ „์šฉ(readonly), ๋˜๋Š” ์›๋ž˜ ํƒ€์ž…(T[P]) ๋“ฑ์œผ๋กœ ํ†ต์งธ๋กœ ๋งตํ•‘(Mapping)ํ•˜๋Š” ๊ฒŒ ๋ฐ”๋กœ ์ € ์œ ์šฐ๋ช…ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋“ค์˜ ๋ฏผ๋‚ฏ์ž…๋‹ˆ๋‹ค.
  • ์˜ค๋‹ต ํ”ผ๋“œ๋ฐฑ: "์ด๊ฑธ ๋ชจ๋ฅด๋ฉด ํ‰์ƒ TS ๊ฐœ๋ฐœ์ž๋“ค์ด ๋งŒ๋“ค์–ด ์ค€ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋งŒ ๊ฐ–๋‹ค ์จ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋งŒ์˜ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง(์˜ˆ: ๋ชจ๋“  API ์‘๋‹ต์„ Nullableํ•˜๊ฒŒ ๋งŒ๋“ค๊ธฐ)์ด ํ•„์š”ํ•  ๋•Œ ์ง์ ‘ ๋งต๋“œ ํƒ€์ž…์„ ์งค ์ค„ ์•Œ์•„์•ผ ์ง„์ •ํ•œ ์‹œ๋‹ˆ์–ด๊ฐ€ ๋˜๋Š” ๊ฒ๋‹ˆ๋‹ค."
  • ๐Ÿ“Œ ํ•ต์‹ฌ ๊ธฐ์–ต๋ฒ•: ๊ฐ์ฒด ํƒ€์ž…์˜ ์ผ๊ด„ ๋…ธ๊ฐ€๋‹ค๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด? in keyof ๋งต๋“œ ํƒ€์ž… ๋น™๋น™ ๋Œ๋ฆฌ๊ธฐ!

๐Ÿฃ ์˜์ฒ ์ด์˜ ํ‡ด๊ทผ ์ผ๊ธฐ

๐Ÿ’ก "๋‚ด ์ฝ”๋“œ๊ฐ€ ๋ฌด์‹ํ•ด ๋ณด์ผ ๋•Œ๋งˆ๋‹ค ๊ธฐ์–ตํ•˜์ž. ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—๋Š” ๋‚ด๊ฐ€ ํ•˜๋ ค๋Š” ๋…ธ๊ฐ€๋‹ค๋ฅผ ์šฐ์•„ํ•˜๊ฒŒ ํ•œ ํ์— ๋๋‚ด์ฃผ๋Š” ํ‘๋งˆ๋ฒ•์ด ์กด์žฌํ•œ๋‹ค."

์™€, typeof๋ž‘ keyof๋Š” ๊ทธ๋ƒฅ ํƒ€์ž… ๊ตฌ๋ณ„ํ•˜๋Š” ๊ฑด ์ค„๋งŒ ์•Œ์•˜์ง€ ์ €๋ ‡๊ฒŒ ๊ธฐ์กด JS ๋ฐ์ดํ„ฐ๋ฅผ ๋œฏ์–ด์„œ ์ƒˆ๋กœ์šด ํƒ€์ž…์„ ์—ฐ์„ฑํ•ด ๋‚ด๋Š” ์—ฐ๊ธˆ์ˆ ์ธ ์ค„์€ ๋ชฐ๋ž๋‹ค.
์˜ค๋Š˜ Partial ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ๋‘ ๋ˆˆ์œผ๋กœ ํ™•์ธํ•˜๊ณ  ๋‚˜๋‹ˆ, ๋ญ”๊ฐ€ ๋ณด์ด์ง€ ์•Š๋˜ ์„ธ์ƒ์ด ์—ด๋ฆฐ ๊ธฐ๋ถ„์ด๋‹ค. ๋‚ด๊ฐ€ ์—ฌํƒœ๊ป ๋ณต์‚ฌ ๋ถ™์—ฌ๋„ฃ๊ธฐ๋กœ ๋งŒ๋“ค์—ˆ๋˜ ๊ทธ ์ˆ˜๋งŽ์€ ํผ ์ž…๋ ฅ(Input) ํฌ๋งท ์ธํ„ฐํŽ˜์ด์Šค๋“ค์ด ์ฃผ๋งˆ๋“ฑ์ฒ˜๋Ÿผ ์Šค์ณ ์ง€๋‚˜๊ฐ„๋‹ค...
๋‚ด์ผ์€ ์ถœ๊ทผํ•˜์ž๋งˆ์ž typeof๋กœ ์ƒ์ˆ˜ ๊ฐ์ฒด๋“ค ์‹น ๋‹ค ํƒ€์ž…์œผ๋กœ ์ž๋™ํ™”์‹œ์ผœ ๋†“๊ณ , Pick์ด๋ž‘ Omit ์จ์„œ ์“ธ๋ฐ์—†๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋“ค ๋‚ ๋ ค๋ฒ„๋ ค์•ผ๊ฒ ๋‹ค. ์•„์‹ธ ์•ผ๊ทผ ์•ˆ ํ•ด๋„ ๋œ๋‹ค! ์น˜ํ‚จ ์‹œ์ผœ ๋จน์–ด์•ผ์ง€!!