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

2026๋…„ 4์›” 30์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

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

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

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

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

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

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

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

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

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

์ดˆ๋ณด ์‹œ์ ˆ์˜ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” "๋‚ด๊ฐ€ ๋งŒ๋“  ๋ณ€์ˆ˜์— ์ธํ„ฐํŽ˜์ด์Šค ํ•˜๋‚˜ ๋‹ฌ์•„์ฃผ๊ธฐ" ์ •๋„๋ฉด ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์ง€๋ฉด "๊ธฐ์กด์— ์žˆ๋Š” 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์ธ ํ”„๋กœํผํ‹ฐ ํ‚ค๊ฐ’๋งŒ ๋ฝ‘์•„๋‚ด๊ณ  ์‹ถ์„ ๋•Œ ์กฐ๊ฑด๋ถ€ ํƒ€์ž…์„ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹น์žฅ ๋ชจ๋“  ํŒจํ„ด์„ ์™ธ์šธ ํ•„์š”๋Š” ์—†์ง€๋งŒ, ๊ถŒํ•œ/ํผ/์‘๋‹ต ํƒ€์ž…์„ ์„ค๊ณ„ํ•  ๋•Œ ์ด๋Ÿฐ ์กฐํ•ฉ์ด ๋ฐ˜๋ณตํ•ด์„œ ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.


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

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)ํ•˜๋Š” ๊ฒŒ ๋ฐ”๋กœ ์ € ์œ ์šฐ๋ช…ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋“ค์˜ ๋ฏผ๋‚ฏ์ž…๋‹ˆ๋‹ค.
  • ๋‚ด์žฅ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์“ฐ๋Š” ๊ฒƒ์—์„œ ๋๋‚˜์ง€ ์•Š๊ณ , ์šฐ๋ฆฌ ์„œ๋น„์Šค ๊ทœ์น™์— ๋งž์ถ˜ ํŒŒ์ƒ ํƒ€์ž…์„ ๋งŒ๋“ค ๋•Œ๋„ ๊ฐ™์€ ์›๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ชจ๋“  ํผ ํ•„๋“œ๋ฅผ nullableํ•˜๊ฒŒ ๋งŒ๋“ค๊ฑฐ๋‚˜, ์„œ๋ฒ„ ์‘๋‹ต์—์„œ ์ฝ๊ธฐ ์ „์šฉ ํ•„๋“œ๋ฅผ ๋ถ„๋ฆฌํ•  ๋•Œ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ํ•ต์‹ฌ์€ ๊ฐ์ฒด ํƒ€์ž…์˜ ํ‚ค๋ฅผ ํ•œ ๋ฒˆ์”ฉ ์ˆœํšŒํ•˜๋ฉด์„œ ๊ฐ ์†์„ฑ์˜ ์„ ํƒ์„ฑ, ์ฝ๊ธฐ ์ „์šฉ ์—ฌ๋ถ€, ๊ฐ’ ํƒ€์ž…์„ ์ผ๊ด€๋˜๊ฒŒ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

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

์˜ค๋Š˜์€ ํƒ€์ž…์„ ๋ณต์‚ฌํ•ด์„œ ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ์Šต๊ด€์ด ์–ผ๋งˆ๋‚˜ ์œ„ํ—˜ํ•œ์ง€ ์•Œ์•˜๋‹ค. UserProfile์ด ๋ฐ”๋€Œ์—ˆ๋Š”๋ฐ UserProfileUpdateForm์ด ๊ทธ๋Œ€๋กœ ๋‚จ์•„ ์žˆ์œผ๋ฉด, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์•„๋‹ˆ๋ผ ๋‚ด๊ฐ€ ์ค‘๋ณต์„ ๋งŒ๋“  ํƒ“์ด๋‹ค.

typeof๋Š” ๊ฐ’์—์„œ ํƒ€์ž…์„ ๋Œ์–ด์˜ค๊ณ , keyof๋Š” ํ‚ค ๋ชฉ๋ก์„ ์œ ๋‹ˆ์–ธ์œผ๋กœ ๋งŒ๋“ค๊ณ , ๋งต๋“œ ํƒ€์ž…์€ ๊ทธ ํ‚ค๋“ค์„ ๋”ฐ๋ผ ์ƒˆ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ ๋‹ค. Partial, Pick, Omit์ด ๊ฐ‘์ž๊ธฐ ์™ธ์›Œ์•ผ ํ•  ์ด๋ฆ„์ด ์•„๋‹ˆ๋ผ ์ฝ์„ ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋ณด์ด๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.

๐Ÿ’ก "ํŒŒ์ƒ ํƒ€์ž…์€ ์›๋ณธ ํƒ€์ž…๊ณผ ํ•จ๊ป˜ ์›€์ง์—ฌ์•ผ ํ•œ๋‹ค. ๋ณต์‚ฌ๋ณธ์„ ๋Š˜๋ฆฌ๋Š” ๋Œ€์‹  keyof, ๋งต๋“œ ํƒ€์ž…, ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์œผ๋กœ ๊ด€๊ณ„๋ฅผ ์„ ์–ธํ•˜์ž."

๋‚ด์ผ์€ ๊ถŒํ•œ ์ƒ์ˆ˜์™€ ํ”„๋กœํ•„ ํผ ํƒ€์ž…๋ถ€ํ„ฐ ํ™•์ธํ•ด๋ณด๋ ค๊ณ  ํ•œ๋‹ค. ์›๋ณธ ๊ฐ์ฒด๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ๋ฐ”๋กœ ํŒŒ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์€ ์†์œผ๋กœ ๋‹ค์‹œ ์“ฐ์ง€ ์•Š๊ณ , ๋ณ€๊ฒฝ์ด ํ•œ ๊ณณ์—์„œ ํ๋ฅด๋„๋ก ๋งŒ๋“œ๋Š” ๊ฒŒ ๋ชฉํ‘œ๋‹ค.