๐ ๊ณ ๊ธ ํ์ : Partial, Readonly, Record, Pick ํ์ฉํ๊ธฐ ๐

์๋ , ํ์ ์คํฌ๋ฆฝํธ ์น๊ตฌ๋ค! ์ค๋์ ์ ๋ง ์ฌ๋ฐ๊ณ ์ ์ฉํ ์ฃผ์ ๋ฅผ ๊ฐ์ง๊ณ ์์ด. ๋ฐ๋ก ํ์ ์คํฌ๋ฆฝํธ์ ๊ณ ๊ธ ํ์ ๋ค์ธ Partial, Readonly, Record, Pick์ ๋ํด ๊น์ด ํํค์ณ๋ณผ ๊ฑฐ์ผ. ์ด ๋ ์๋ค์ ์ ๋๋ก ์๋ฉด ๋์ ์ฝ๋ฉ ์ค๋ ฅ์ด ํ๋์ ์ฐ๋ฅผ ๊ฑฐ๋ผ๊ณ ! ๐
๊ทธ๋ผ ์ฐ๋ฆฌ ํจ๊ป ํ์ ์คํฌ๋ฆฝํธ์ ์ธ๊ณ๋ก ๋น ์ ธ๋ณผ๊น? ์ด ์ฌ์ ์ ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ์ฌ๋ฅ์ ๋ฐ๊ฒฌํ๋ ๊ฒ์ฒ๋ผ ์ ์ ํ๊ณ ํฅ๋ฏธ์ง์งํ ๊ฑฐ์ผ. ์, ์์ ๋ฒจํธ ๋งค๊ณ ์ถ๋ฐ~! ๐๐จ
๐ ์์ญ๋ฌ์ญ ํ์ ์คํฌ๋ฆฝํธ tip: ํ์ ์คํฌ๋ฆฝํธ์ ๊ณ ๊ธ ํ์ ๋ค์ ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ์ฐพ๋ ๊ฒ์ฒ๋ผ, ์ฝ๋์ ๋ค์ํ "์ฌ๋ฅ"์ ๋ถ์ฌํด์ฃผ๋ ๋๊ตฌ๋ค์ด์ผ. ์ด๋ค์ ์ ํ์ฉํ๋ฉด ๋ค ์ฝ๋๊ฐ ๋์ฑ ์ ์ฐํ๊ณ ๊ฐ๋ ฅํด์ง ๊ฑฐ์ผ!
๐งฉ Partial<T>: ๋ถ๋ถ์ ์ผ๋ก ์ฑ์๋ฃ๋ ๋ง๋ฒ ๐งฉ
์, ์ฒซ ๋ฒ์งธ๋ก ๋ง๋๋ณผ ๋ ์์ ๋ฐ๋ก Partial์ด์ผ. Partial์ ๋ง ๊ทธ๋๋ก "๋ถ๋ถ์ "์ด๋ผ๋ ๋ป์ ๊ฐ์ง๊ณ ์์ด. ์ด ๋ ์์ด ํ๋ ์ผ์ ์ ๋ง ๋๋จํด. ์ด๋ค ํ์ ์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์ ํ์ ์ผ๋ก ๋ง๋ค์ด์ฃผ๋ ๊ฑฐ์ง!
์๋ฅผ ๋ค์ด๋ณผ๊น? ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ค๋ฃจ๋ ์ธํฐํ์ด์ค๊ฐ ์๋ค๊ณ ์๊ฐํด๋ณด์.
interface User {
name: string;
age: number;
email: string;
}
์ด๋ ๊ฒ ์์ ๋, Partial์ ์ฌ์ฉํ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
type PartialUser = Partial<User>;
์ง์! ์ด์ PartialUser๋ ์ด๋ ๊ฒ ๋ณํ์ด:
{
name?: string;
age?: number;
email?: string;
}
๋ชจ๋ ํ๋กํผํฐ๊ฐ ์ ํ์ (optional)์ด ๋์์ง? ์ด๊ฒ ๋ฐ๋ก Partial์ ๋ง๋ฒ์ด์ผ! ๐ฉโจ
๐ก ์ ์ด๊ฒ ์ ์ฉํ ๊น? ๊ฐ์ฒด์ ์ผ๋ถ๋ถ๋ง ์ ๋ฐ์ดํธํ๊ณ ์ถ์ ๋ ์ ๋ง ํธ๋ฆฌํด. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ์ ๋ณด ์ค ์ด๋ฉ์ผ๋ง ๋ณ๊ฒฝํ๊ณ ์ถ๋ค๋ฉด ์ด๋ ๊ฒ ํ ์ ์์ง:
function updateUser(id: string, updates: Partial<User>) {
// ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ฌ์ฉ์๋ฅผ ์ฐพ์ ์
๋ฐ์ดํธํ๋ ๋ก์ง
}
updateUser('123', { email: 'new@email.com' });
์ด๋ ๊ฒ Partial์ ์ฌ์ฉํ๋ฉด, ๋ชจ๋ ํ๋๋ฅผ ๋ค ์ฑ์ธ ํ์ ์์ด ์ํ๋ ํ๋๋ง ์ ๋ฐ์ดํธํ ์ ์์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ํ๋ ์ฌ๋ฅ๋ง ๊ณจ๋ผ์ ๋ฐฐ์ฐ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ! ๐
๐จ Partial ํ์ฉ ์์: ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ ์ฑ
์, ์ด์ Partial์ ์ค์ ๋ก ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์ฌ๋ฏธ์๋ ์์๋ฅผ ๋ค์ด๋ณผ๊ฒ. ์ฐ๋ฆฌ๊ฐ ๊ฐ๋จํ ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ ์ฑ์ ๋ง๋ ๋ค๊ณ ์๊ฐํด๋ณด์!
interface DrawingOptions {
color: string;
thickness: number;
tool: 'pencil' | 'brush' | 'eraser';
opacity: number;
}
function draw(options: DrawingOptions) {
// ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๋ ๋ก์ง
}
์ด๋ ๊ฒ ์์ ๋, ๋งค๋ฒ ๋ชจ๋ ์ต์ ์ ์ง์ ํ๋ ๊ฑด ๋๋ฌด ๊ท์ฐฎ๊ฒ ์ง? ๊ทธ๋์ ์ฐ๋ฆฌ๋ Partial์ ์ฌ์ฉํด์ ๊ธฐ๋ณธ๊ฐ์ ์ค์ ํ๊ณ , ์ฌ์ฉ์๊ฐ ์ํ๋ ์ต์ ๋ง ๋ณ๊ฒฝํ ์ ์๊ฒ ๋ง๋ค ์ ์์ด.
const defaultOptions: DrawingOptions = {
color: 'black',
thickness: 1,
tool: 'pencil',
opacity: 1
};
function drawWithDefaults(options: Partial<DrawingOptions>) {
const finalOptions = { ...defaultOptions, ...options };
draw(finalOptions);
}
// ์ด์ ์ด๋ ๊ฒ ์ฌ์ฉํ ์ ์์ด!
drawWithDefaults({ color: 'red' });
drawWithDefaults({ tool: 'brush', thickness: 3 });
์! ์ด์ ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ๊ฐ ํจ์ฌ ๋ ์ ์ฐํด์ก์ด. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ํ๋ ์ฌ๋ฅ๋ง ๊ณจ๋ผ ๋ฐฐ์ฐ๋ ๊ฒ์ฒ๋ผ, ์ํ๋ ์ต์ ๋ง ์ ํํด์ ๊ทธ๋ฆผ์ ๊ทธ๋ฆด ์ ์๊ฒ ๋ ๊ฑฐ์ง. ๐จโ๐จ๐จ
์ด SVG๋ ์ฐ๋ฆฌ๊ฐ ๋ฐฉ๊ธ ๋ง๋ ๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ ์ฑ์ ์ฃผ์ ์ต์ ๋ค์ ์๊ฐํํ ๊ฑฐ์ผ. ์์, ๋๊ป, ๋๊ตฌ๋ฅผ ๊ฐ๊ฐ ์, ์ฌ๊ฐํ, ์ผ๊ฐํ์ผ๋ก ํํํ์ง. ์ด๋ ๊ฒ Partial์ ์ฌ์ฉํ๋ฉด ์ด ์ต์ ๋ค์ ์์ ๋กญ๊ฒ ์กฐํฉํด์ ์ฌ์ฉํ ์ ์๋ ๊ฑฐ์ผ!
๐ Partial์ ์ง๊ฐ: Partial์ ํนํ ํฐ ๊ฐ์ฒด๋ฅผ ๋ค๋ฃฐ ๋ ๊ทธ ์ง๊ฐ๋ฅผ ๋ฐํํด. ์๋ฅผ ๋ค์ด, ์ฌ์ฉ์ ์ค์ ์ด๋ ์ฑ์ ์ํ๋ฅผ ๊ด๋ฆฌํ ๋ ์์ฃผ ์ ์ฉํ์ง. ๋ชจ๋ ์ค์ ์ ํ ๋ฒ์ ๋ค ๋ฐ๊พธ๋ ๊ฒฝ์ฐ๋ ๋๋ฌผ์์? Partial์ ์ฌ์ฉํ๋ฉด ํ์ํ ๋ถ๋ถ๋ง ์์ ๊ณจ๋ผ์ ์ ๋ฐ์ดํธํ ์ ์์ด!
๐ง Partial ์ฌํ: ์ค์ฒฉ๋ ๊ฐ์ฒด ๋ค๋ฃจ๊ธฐ
์, ์ด์ ์ข ๋ ๋ณต์กํ ์ํฉ์ ์๊ฐํด๋ณด์. ๊ฐ์ฒด ์์ ๊ฐ์ฒด๊ฐ ์๋ ๊ฒฝ์ฐ๋ ์ด๋จ๊น? ์ด๋ฐ ๊ฒฝ์ฐ์ Partial์ ์ด๋ป๊ฒ ํ์ฉํ ์ ์์์ง ์์๋ณด์!
interface AdvancedDrawingOptions {
brush: {
color: string;
size: number;
};
canvas: {
width: number;
height: number;
};
effects: {
blur: number;
saturation: number;
};
}
์ด๋ฐ ๋ณต์กํ ๊ฐ์ฒด๊ฐ ์์ ๋, ๋จ์ํ Partial<AdvancedDrawingOptions>๋ฅผ ์ฌ์ฉํ๋ฉด ์ต์์ ํ๋กํผํฐ๋ง ์ ํ์ ์ด ๋ผ. ํ์ ๊ฐ์ฒด์ ํ๋กํผํฐ๋ ์ฌ์ ํ ํ์์ผ. ์ด๋ด ๋ ์ฐ๋ฆฌ๋ ์ฌ๊ท์ Partial ํ์ ์ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์์ด!
type DeepPartial<T> = {
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};
function updateAdvancedDrawingOptions(options: DeepPartial<AdvancedDrawingOptions>) {
// ์
๋ฐ์ดํธ ๋ก์ง
}
// ์ด์ ์ด๋ ๊ฒ ์ฌ์ฉํ ์ ์์ด!
updateAdvancedDrawingOptions({
brush: { color: 'blue' },
effects: { blur: 5 }
});
์์ฐ! ์ด์ ์ ๋ง ๊น์ํ ๊ณณ์ ์๋ ์ต์ ๊น์ง ์์ ์์ฌ๋ก ์ ๋ฐ์ดํธํ ์ ์๊ฒ ๋์ด. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ "๊ทธ๋ฆผ ๊ทธ๋ฆฌ๊ธฐ" ๋ผ๋ ํฐ ์นดํ ๊ณ ๋ฆฌ ์์์ "์์ฑํ ๊ธฐ๋ฒ" ๊ฐ์ ์ธ๋ถ ๊ธฐ์ ๋ง ์ ๊ณจ๋ผ ๋ฐฐ์ฐ๋ ๊ฒ๊ณผ ๊ฐ์! ๐
์ด ๋ค์ด์ด๊ทธ๋จ์ ์ฐ๋ฆฌ์ AdvancedDrawingOptions ๊ตฌ์กฐ๋ฅผ ์๊ฐํํ ๊ฑฐ์ผ. ์ต์์ ๊ฐ์ฒด ์๋์ brush, canvas, effects๋ผ๋ ํ์ ๊ฐ์ฒด๋ค์ด ์๊ณ , ๊ฐ๊ฐ์ ํ์ ๊ฐ์ฒด๋ ๋ ์์ ๋ง์ ํ๋กํผํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ง. DeepPartial์ ์ฌ์ฉํ๋ฉด ์ด ๊ตฌ์กฐ์ ์ด๋ค ๋ถ๋ถ์ด๋ ์ ํ์ ์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์์ด!
๐ Partial์ ํ: Partial, ํนํ DeepPartial์ ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ์ผ. ๋ณต์กํ ์ค์ ๊ฐ์ฒด๋ฅผ ๋ค๋ฃฐ ๋, API ์๋ต์ ์ผ๋ถ๋ง ์ฌ์ฉํด์ผ ํ ๋, ๋๋ ํฐ ์ํ ๊ฐ์ฒด์ ์ผ๋ถ๋ง ์ ๋ฐ์ดํธํด์ผ ํ ๋ ์์ฃผ ์ ์ฉํ์ง. ์ด๊ฑธ ์ ํ์ฉํ๋ฉด ์ฝ๋์ ์ ์ฐ์ฑ์ด ์์ฒญ๋๊ฒ ๋์์ง ๊ฑฐ์ผ!
๐ญ Partial๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ข์ ์น๊ตฌ๋ค
Partial์ ํผ์์๋ ๊ฐ๋ ฅํ์ง๋ง, ๋ค๋ฅธ ํ์ ์ ํธ๋ฆฌํฐ๋ค๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋์ฑ ๊ฐ๋ ฅํด์ ธ. ๋ช ๊ฐ์ง ์๋ฅผ ์ดํด๋ณผ๊น?
- Required<T>: Partial์ ๋ฐ๋์ผ. ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ํ์๋ก ๋ง๋ค์ด์ค.
- Pick<T, K>: ํน์ ํ๋กํผํฐ๋ง ์ ํํด์ ์๋ก์ด ํ์ ์ ๋ง๋ค์ด.
- Omit<T, K>: ํน์ ํ๋กํผํฐ๋ฅผ ์ ์ธํ ์๋ก์ด ํ์ ์ ๋ง๋ค์ด.
์ด๋ค์ Partial๊ณผ ์กฐํฉํด์ ์ฌ์ฉํ๋ฉด ์ ๋ง ๋ค์ํ ์ํฉ์ ๋์ํ ์ ์์ด. ์๋ฅผ ๋ค์ด๋ณผ๊น?
interface User {
id: number;
name: string;
email: string;
age: number;
address: string;
}
// id๋ฅผ ์ ์ธํ ๋๋จธ์ง ํ๋๋ฅผ ์ ํ์ ์ผ๋ก ๋ง๋ค๊ธฐ
type UpdateUser = { id: number } & Partial<Omit<User, 'id'>>;
function updateUser(user: UpdateUser) {
// ์
๋ฐ์ดํธ ๋ก์ง
}
// ์ด๋ ๊ฒ ์ฌ์ฉํ ์ ์์ด!
updateUser({ id: 1, name: "New Name" });
updateUser({ id: 2, email: "new@email.com", age: 30 });
์ด๋ ๊ฒ ํ๋ฉด id๋ ํญ์ ํ์ํ์ง๋ง, ๋๋จธ์ง ํ๋๋ ์ ํ์ ์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์๊ฒ ๋ผ. ์์ ์ ์ฐํ์ง ์์? ๐
์ด ๋ค์ด์ด๊ทธ๋จ์ Partial๊ณผ ๋ค๋ฅธ ํ์ ์ ํธ๋ฆฌํฐ๋ค์ ๊ด๊ณ๋ฅผ ๋ณด์ฌ์ค. Partial์ด ์ค์ฌ์ ์๊ณ , ๋ค๋ฅธ ์ ํธ๋ฆฌํฐ๋ค์ด ์ฃผ๋ณ์ ๋๋ฌ์ธ๊ณ ์์ด. ์ด๋ค์ ์ ์ ํ ์กฐํฉํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ํ์ ์ ๋ง๋ค ์ ์์ง!
๐ก ์ค์ ํ: ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ฐ ํ์ ์กฐํฉ์ ์์ฃผ ์ฌ์ฉํ๊ฒ ๋ ๊ฑฐ์ผ. ํนํ API์ ์ํธ์์ฉํ ๋, ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ์ ๋ค๋ฃฐ ๋, ๋๋ ๋ณต์กํ ์ํ ๊ด๋ฆฌ๋ฅผ ํ ๋ ์ด๋ฐ ๊ธฐ์ ์ด ๋น์ ๋ฐํ์ง. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ์ฌ๋ฅ์ ์กฐํฉํด ์๋ก์ด ๊ฐ์น๋ฅผ ๋ง๋ค์ด๋ด๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ!
์, ์ด์ Partial์ ๋ํด ๊ฝค ๊น์ด ์์๋ดค์ด. ์ด ๋ ์์ ์ ํ์ฉํ๋ฉด ๋ค ์ฝ๋๊ฐ ํจ์ฌ ๋ ์ ์ฐํด์ง ๊ฑฐ์ผ. ๋ค์์ผ๋ก๋ Readonly์ ๋ํด ์์๋ณผ ํ ๋ฐ, ์ด๊ฒ๋ ์ ๋ง ์ฌ๋ฐ์ ๊ฑฐ์ผ! ๊ณ์ ๋ฐ๋ผ์์ค! ๐
๐ Readonly<T>: ๋ถ๋ณ์ฑ์ ๋ง๋ฒ์ฌ ๐
์, ์ด์ ์ฐ๋ฆฌ์ ๋ ๋ฒ์งธ ์ฃผ์ธ๊ณต Readonly๋ฅผ ๋ง๋๋ณผ ์๊ฐ์ด์ผ! Readonly๋ ๋ง ๊ทธ๋๋ก "์ฝ๊ธฐ ์ ์ฉ"์ ๋ง๋ค์ด์ฃผ๋ ๋ง๋ฒ์ฌ์ผ. ์ด ๋ ์์ด ํ๋ ์ผ์ ๊ฐ์ฒด์ ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค์ด์ฃผ๋ ๊ฑฐ์ง. ํ ๋ฒ ์ค์ ํ๋ฉด ๋ณ๊ฒฝํ ์ ์๊ฒ ๋๋ ๊ฑฐ์ผ!
์๋ฅผ ๋ค์ด๋ณผ๊น? ์ฐ๋ฆฌ๊ฐ ์ฑ ์ ๋ณด๋ฅผ ๋ค๋ฃจ๋ ์ธํฐํ์ด์ค๊ฐ ์๋ค๊ณ ์๊ฐํด๋ณด์.
interface Book {
title: string;
author: string;
publishYear: number;
}
์ด์ Readonly๋ฅผ ์ฌ์ฉํด๋ณด๋ฉด:
type ReadonlyBook = Readonly<Book>;
์ง์! ReadonlyBook์ ์ด๋ ๊ฒ ๋ณํ์ด:
{
readonly title: string;
readonly author: string;
readonly publishYear: number;
}
๋ชจ๋ ํ๋กํผํฐ ์์ readonly๊ฐ ๋ถ์์ง? ์ด์ ์ด ๊ฐ์ฒด์ ํ๋กํผํฐ๋ค์ ํ ๋ฒ ์ค์ ๋๋ฉด ๋ณ๊ฒฝํ ์ ์์ด. ๋ง์น ๋์๊ด์ ์ฑ ์ฒ๋ผ, ๋ณผ ์๋ ์์ง๋ง ๋ด์ฉ์ ๋ฐ๊ฟ ์ ์์ง! ๐
๐ก ์ ์ด๊ฒ ์ ์ฉํ ๊น? ๋ถ๋ณ์ฑ(Immutability)์ ํ๋ก๊ทธ๋๋ฐ์์ ์ ๋ง ์ค์ํ ๊ฐ๋ ์ด์ผ. ๋ฐ์ดํฐ๊ฐ ์์์น ๋ชปํ๊ฒ ๋ณ๊ฒฝ๋๋ ๊ฑธ ๋ฐฉ์งํ๊ณ , ์ฝ๋์ ์์ธก ๊ฐ๋ฅ์ฑ์ ๋์ฌ์ฃผ์ง. ํนํ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์์ ๋ง์ด ์ฌ์ฉ๋๋ ๊ฐ๋ ์ด์ผ.
Readonly๋ฅผ ์ฌ์ฉํ๋ฉด, ๊ฐ์ฒด๊ฐ ์์ฑ๋ ํ์ ์ค์๋ก ๊ฐ์ด ๋ณ๊ฒฝ๋๋ ๊ฒ์ ๋ฐฉ์งํ ์ ์์ด. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ํ ๋ฒ ๋ฑ๋กํ ์ฌ๋ฅ์ ํจ๋ถ๋ก ์์ ํ ์ ์๊ฒ ํ๋ ๊ฒ๊ณผ ๋น์ทํด. ์ ๋ขฐ์ฑ์ด ๋์์ง๋ ๊ฑฐ์ง! ๐
๐ Readonly ํ์ฉ ์์: ๋์๊ด ์์คํ
์, ์ด์ Readonly๋ฅผ ์ค์ ๋ก ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์ฌ๋ฏธ์๋ ์์๋ฅผ ๋ค์ด๋ณผ๊ฒ. ์ฐ๋ฆฌ๊ฐ ์์ ๋์๊ด ์์คํ ์ ๋ง๋ ๋ค๊ณ ์๊ฐํด๋ณด์!
interface LibraryBook {
id: number;
title: string;
author: string;
isbn: string;
publishYear: number;
}
type CatalogBook = Readonly<LibraryBook>;
const book: CatalogBook = {
id: 1,
title: "TypeScript ๋ง์คํฐํ๊ธฐ",
author: "๊ฐ๋ฐ์",
isbn: "123-456-789",
publishYear: 2023
};
// ์ด๋ ๊ฒ ํ๋ฉด ์๋ฌ๊ฐ ๋ฐ์ํด!
// book.title = "JavaScript ๋ง์คํฐํ๊ธฐ"; // Error: Cannot assign to 'title' because it is a read-only property.
์! ์ด์ ์ฐ๋ฆฌ์ ๋์ ์นดํ๋ก๊ทธ๋ ์์ ํด์ก์ด. ํ ๋ฒ ๋ฑ๋ก๋ ์ฑ ์ ๋ณด๋ ๋ณ๊ฒฝํ ์ ์์ผ๋๊น ์ค์๋ก ์ ๋ณด๊ฐ ๋ฐ๋๋ ์ผ์ ์์ ๊ฑฐ์ผ. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ํ ๋ฒ ๋ฑ๋ก๋ ์ฌ๋ฅ์ ํต์ฌ ์ ๋ณด๋ฅผ ๋ณดํธํ๋ ๊ฒ๊ณผ ๊ฐ์. ์ ๋ขฐํ ์ ์๋ ์ ๋ณด๋ง ์ ๊ณตํ ์ ์๊ฒ ๋๋ ๊ฑฐ์ง! ๐๐
์ด SVG๋ ์ฐ๋ฆฌ์ CatalogBook์ ์๊ฐํํ ๊ฑฐ์ผ. ๋ณด์ด์ง? ๋ชจ๋ ํ๋กํผํฐ ์์ ์์ ์๋ฌผ์ ์ด๋ชจ์ง๊ฐ ์์ด. ์ด๊ฑด ๊ฐ ํ๋กํผํฐ๊ฐ ์ฝ๊ธฐ ์ ์ฉ์ด๋ผ๋ ๊ฑธ ๋ํ๋ด๋ ๊ฑฐ์ผ. ํฐ ์๋ฌผ์ ๋ ์ ์ฒด ๊ฐ์ฒด๊ฐ ๋ณดํธ๋๊ณ ์๋ค๋ ๊ฑธ ์๋ฏธํด. ์ด๋ ๊ฒ Readonly๋ฅผ ์ฌ์ฉํ๋ฉด ์ฐ๋ฆฌ์ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฒ ๋ณดํธํ ์ ์์ด!
๐ Readonly์ ์ง๊ฐ: Readonly๋ ํนํ ์ํ ๊ด๋ฆฌ๋ ๋ถ๋ณ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ค๋ฃฐ ๋ ๋น์ ๋ฐํด. ์๋ฅผ ๋ค์ด, Redux๊ฐ์ ์ํ ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ํ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ์๋ก์ด ์ํ๋ฅผ ๋ฐํํ๋ ํจํด์ ๊ฐ์ ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ง. ์ด๋ ๊ฒ ํ๋ฉด ์์ธก ๊ฐ๋ฅํ๊ณ ๋๋ฒ๊น ํ๊ธฐ ์ฌ์ด ์ฝ๋๋ฅผ ์์ฑํ ์ ์์ด!
๐ง Readonly ์ฌํ: ์ค์ฒฉ๋ ๊ฐ์ฒด ๋ค๋ฃจ๊ธฐ
์, ์ด์ ์ข ๋ ๋ณต์กํ ์ํฉ์ ์๊ฐํด๋ณด์. ๊ฐ์ฒด ์์ ๊ฐ์ฒด๊ฐ ์๋ ๊ฒฝ์ฐ๋ ์ด๋จ๊น? ์ด๋ฐ ๊ฒฝ์ฐ์ Readonly๋ฅผ ์ด๋ป๊ฒ ํ์ฉํ ์ ์์์ง ์์๋ณด์!
interface Author {
name: string;
birthYear: number;
}
interface DetailedBook {
title: string;
author: Author;
genres: string[];
}
์ด๋ฐ ๋ณต์กํ ๊ฐ์ฒด๊ฐ ์์ ๋, ๋จ์ํ Readonly
type DeepReadonly<t> = {
readonly [P in keyof T]: T[P] extends object ? DeepReadonly<t> : T[P];
};
const book: DeepReadonly<detailedbook> = {
title: "TypeScript ์ฌํ",
author: {
name: "๊ฐ๋ฐ์",
birthYear: 1990
},
genres: ["Programming", "Technology"]
};
// ์ด์ ์ด๋ ๊ฒ ํ๋ฉด ๋ชจ๋ ์๋ฌ๊ฐ ๋ฐ์ํด!
// book.title = "JavaScript ์ฌํ"; // Error
// book.author.name = "์ฝ๋ฉ์"; // Error
// book.genres.push("Education"); // Error
</detailedbook></t></t>
์์ฐ! ์ด์ ์ ๋ง ๊น์ํ ๊ณณ์ ์๋ ํ๋กํผํฐ๊น์ง ๋ชจ๋ ์ฝ๊ธฐ ์ ์ฉ์ด ๋์ด. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ "ํ๋ก๊ทธ๋๋ฐ" ์ด๋ผ๋ ํฐ ์นดํ ๊ณ ๋ฆฌ๋ถํฐ "TypeScript" ๊ฐ์ ์ธ๋ถ ๊ธฐ์ ๊น์ง ๋ชจ๋ ์ ๋ณด๋ฅผ ์์ ํ๊ฒ ๋ณดํธํ๋ ๊ฒ๊ณผ ๊ฐ์! ๐ก๏ธ
์ด ๋ค์ด์ด๊ทธ๋จ์ ์ฐ๋ฆฌ์ DeepReadonly
๐ Readonly์ ํ: Readonly, ํนํ DeepReadonly๋ ์ ๋ง ๊ฐ๋ ฅํ ๋๊ตฌ์ผ. ๋ณต์กํ ๊ฐ์ฒด ๊ตฌ์กฐ์์ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ์ ์ ์งํ๊ณ ์ถ์ ๋, ๋๋ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ํจ๋ฌ๋ค์์ ๋ฐ๋ฅด๊ณ ์ถ์ ๋ ์์ฃผ ์ ์ฉํ์ง. ์ด๊ฑธ ์ ํ์ฉํ๋ฉด ๋ฒ๊ทธ๋ฅผ ์ค์ด๊ณ ์ฝ๋์ ์์ ์ฑ์ ํฌ๊ฒ ๋์ผ ์ ์์ด!
๐ญ Readonly์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ข์ ์น๊ตฌ๋ค
Readonly๋ ๋ค๋ฅธ ํ์ ์ ํธ๋ฆฌํฐ๋ค๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋์ฑ ๊ฐ๋ ฅํด์ ธ. ๋ช ๊ฐ์ง ์๋ฅผ ์ดํด๋ณผ๊น?
- Partial
: ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์ ํ์ ์ผ๋ก ๋ง๋ค์ด์ค. - Pick
: ํน์ ํ๋กํผํฐ๋ง ์ ํํด์ ์๋ก์ด ํ์ ์ ๋ง๋ค์ด. - Record
: ํค์ ์งํฉ K๋ก ํ์ T์ ํ๋กํผํฐ ๋งต์ ๋ง๋ค์ด.
์ด๋ค์ Readonly์ ์กฐํฉํด์ ์ฌ์ฉํ๋ฉด ์ ๋ง ๋ค์ํ ์ํฉ์ ๋์ํ ์ ์์ด. ์๋ฅผ ๋ค์ด๋ณผ๊น?
interface User {
id: number;
name: string;
email: string;
preferences: {
newsletter: boolean;
darkMode: boolean;
};
}
// id์ name๋ง ์ ํํ๊ณ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค๊ธฐ
type ReadonlyUserBasicInfo = Readonly<pick>>;
// ์ ํ์ ์ด๋ฉด์ ์ฝ๊ธฐ ์ ์ฉ์ธ ์ฌ์ฉ์ ์ค์
type ReadonlyPartialPreferences = Readonly<partial>>;
function displayUserInfo(user: ReadonlyUserBasicInfo) {
console.log(`User: ${user.id}, ${user.name}`);
// user.name = "New Name"; // Error: Cannot assign to 'name' because it is a read-only property.
}
function updatePreferences(prefs: ReadonlyPartialPreferences) {
console.log(prefs.newsletter); // OK
// prefs.darkMode = true; // Error: Cannot assign to 'darkMode' because it is a read-only property.
}
</partial></pick>
์ด๋ ๊ฒ ํ๋ฉด ํ์ํ ์ ๋ณด๋ง ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค ์ ์๊ณ , ๋์์ ์ ํ์ ์ธ ์์ฑ๋ ๊ฐ์ง ์ ์์ด. ์์ ์ ์ฐํ๋ฉด์๋ ์์ ํ์ง ์์? ๐
์ด ๋ค์ด์ด๊ทธ๋จ์ Readonly์ ๋ค๋ฅธ ํ์ ์ ํธ๋ฆฌํฐ๋ค์ ๊ด๊ณ๋ฅผ ๋ณด์ฌ์ค. Readonly๊ฐ ์ค์ฌ์ ์๊ณ , ๋ค๋ฅธ ์ ํธ๋ฆฌํฐ๋ค์ด ์ฃผ๋ณ์ ๋๋ฌ์ธ๊ณ ์์ด. ์ด๋ค์ ์ ์ ํ ์กฐํฉํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ๊ณ ์์ ํ ํ์ ์ ๋ง๋ค ์ ์์ง!
๐ก ์ค์ ํ: ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ฐ ํ์ ์กฐํฉ์ ์์ฃผ ์ฌ์ฉํ๊ฒ ๋ ๊ฑฐ์ผ. ํนํ ์ํ ๊ด๋ฆฌ, ์ค์ ๊ฐ์ฒด ๋ค๋ฃจ๊ธฐ, API ์๋ต ์ฒ๋ฆฌ ๋ฑ์์ ์ด๋ฐ ๊ธฐ์ ์ด ๋น์ ๋ฐํ์ง. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ๋ฌ ์ฌ๋ฅ์ ์กฐํฉํด ์๋ก์ด ๊ฐ์น๋ฅผ ๋ง๋ค์ด๋ด๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ!
์, ์ด์ Readonly์ ๋ํด ๊ฝค ๊น์ด ์์๋ดค์ด. ์ด ๋ ์์ ์ ํ์ฉํ๋ฉด ๋ค ์ฝ๋๊ฐ ํจ์ฌ ๋ ์์ ํ๊ณ ์์ธก ๊ฐ๋ฅํด์ง ๊ฑฐ์ผ. ๋ค์์ผ๋ก๋ Record์ ๋ํด ์์๋ณผ ํ ๋ฐ, ์ด๊ฒ๋ ์ ๋ง ์ฌ๋ฐ์ ๊ฑฐ์ผ! ๊ณ์ ๋ฐ๋ผ์์ค! ๐
๐๏ธ Record: ํค-๊ฐ ์์ ๋ง๋ฒ์ฌ ๐๏ธ
์, ์ด์ ์ฐ๋ฆฌ์ ์ธ ๋ฒ์งธ ์ฃผ์ธ๊ณต Record๋ฅผ ๋ง๋๋ณผ ์๊ฐ์ด์ผ! Record๋ ์ ๋ง ํน๋ณํ ๋ ์์ด์ผ. ์ด ํ์ ์ ํค-๊ฐ ์์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉ๋ผ. ํค์ ํ์ ๊ณผ ๊ฐ์ ํ์ ์ ์ง์ ํ ์ ์์ด์ ์์ฃผ ์ ์ฐํ์ง!
Record์ ๊ธฐ๋ณธ ํํ๋ ์ด๋ ๊ฒ ์๊ฒผ์ด:
Record<k t></k>
์ฌ๊ธฐ์ K๋ ํค์ ํ์ ์ด๊ณ , T๋ ๊ฐ์ ํ์ ์ด์ผ. ์๋ฅผ ๋ค์ด๋ณผ๊น?
type Fruit = "apple" | "banana" | "orange";
type FruitInfo = { color: string; taste: string };
type FruitCatalog = Record<fruit fruitinfo>;
const fruits: FruitCatalog = {
apple: { color: "red", taste: "sweet" },
banana: { color: "yellow", taste: "sweet" },
orange: { color: "orange", taste: "citrusy" }
};
</fruit>
์ง์! ์ด๋ ๊ฒ ํ๋ฉด FruitCatalog ํ์ ์ Fruit ํ์ ์ ํค์ FruitInfo ํ์ ์ ๊ฐ์ ๊ฐ์ง ๊ฐ์ฒด๊ฐ ๋ผ. ๋ง์น ๊ณผ์ผ ๋ฐฑ๊ณผ์ฌ์ ๊ฐ์ง ์์? ๐๐๐
๐ก ์ ์ด๊ฒ ์ ์ฉํ ๊น? Record๋ ๊ฐ์ฒด์ ๊ตฌ์กฐ๋ฅผ ๋ช ํํ๊ฒ ์ ์ํ๊ณ ์ถ์ ๋ ์์ฃผ ์ ์ฉํด. ํนํ ํค์ ์งํฉ์ด ๋ฏธ๋ฆฌ ์๋ ค์ ธ ์๊ณ , ๋ชจ๋ ํค๊ฐ ๋์ผํ ํ์ ์ ๊ฐ์ ๊ฐ์ ธ์ผ ํ ๋ ์๋ฒฝํด. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ์ฌ๋ฅ ์นดํ ๊ณ ๋ฆฌ๋ณ๋ก ์ ๋ณด๋ฅผ ๊ตฌ์กฐํํ๋ ๊ฒ๊ณผ ๋น์ทํด!
Record๋ฅผ ์ฌ์ฉํ๋ฉด, ๊ฐ์ฒด์ ๊ตฌ์กฐ๋ฅผ ๋ช ํํ๊ฒ ์ ์ํ ์ ์๊ณ , ํ์ ์์ ์ฑ๋ ๋ณด์ฅ๋ฐ์ ์ ์์ด. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ์ฌ๋ฅ ์นดํ ๊ณ ๋ฆฌ๋ง๋ค ์ผ๊ด๋ ์ ๋ณด ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ก ํ๋ ๊ฒ๊ณผ ๊ฐ์. ์ฒด๊ณ์ ์ด๊ณ ์์ธก ๊ฐ๋ฅํ์ง! ๐
๐จ Record ํ์ฉ ์์: ์์ ํ๋ ํธ ์์คํ
์, ์ด์ Record๋ฅผ ์ค์ ๋ก ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์ฌ๋ฏธ์๋ ์์๋ฅผ ๋ค์ด๋ณผ๊ฒ. ์ฐ๋ฆฌ๊ฐ ๋์์ธ ์์คํ ์ ์ํ ์์ ํ๋ ํธ๋ฅผ ๋ง๋ ๋ค๊ณ ์๊ฐํด๋ณด์!
type Color = "primary" | "secondary" | "success" | "error" | "warning" | "info";
type Shade = "light" | "main" | "dark";
type ColorShades = Record<shade string>;
type ColorPalette = Record<color colorshades>;
const palette: ColorPalette = {
primary: { light: "#7986cb", main: "#3f51b5", dark: "#303f9f" },
secondary: { light: "#ff4081", main: "#f50057", dark: "#c51162" },
success: { light: "#81c784", main: "#4caf50", dark: "#388e3c" },
error: { light: "#e57373", main: "#f44336", dark: "#d32f2f" },
warning: { light: "#ffb74d", main: "#ff9800", dark: "#f57c00" },
info: { light: "#64b5f6", main: "#2196f3", dark: "#1976d2" }
};
function getColor(color: Color, shade: Shade): string {
return palette[color][shade];
}
console.log(getColor("primary", "main")); // "#3f51b5"
console.log(getColor("error", "light")); // "#e57373"
</color></shade>
์์ฐ! ์ด์ ์ฐ๋ฆฌ๋ ์ฒด๊ณ์ ์ด๊ณ ํ์ ์์ ํ ์์ ํ๋ ํธ ์์คํ ์ ๊ฐ์ง๊ฒ ๋์ด. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ์ฌ๋ฅ ์นดํ ๊ณ ๋ฆฌ๋ง๋ค ์ธ๋ถ ๋ ๋ฒจ์ ๊ตฌ๋ถํ๊ณ , ๊ฐ ๋ ๋ฒจ์ ๋ง๋ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ๊ฒ๊ณผ ๊ฐ์. ์ฒด๊ณ์ ์ด๊ณ ์ฌ์ฉํ๊ธฐ ์ฝ์ง! ๐จ๐๏ธ
์ด SVG๋ ์ฐ๋ฆฌ์ ColorPalette๋ฅผ ์๊ฐํํ ๊ฑฐ์ผ. ๊ฐ ์์ ์นดํ ๊ณ ๋ฆฌ๊ฐ ํ๋์ ์ด์ ์ฐจ์งํ๊ณ ์๊ณ , ๊ทธ ์์ light, main, dark ์ธ ๊ฐ์ง shade๊ฐ ํฌํจ๋์ด ์์ด. ์ด๋ ๊ฒ Record๋ฅผ ์ฌ์ฉํ๋ฉด ๋ณต์กํ ๊ตฌ์กฐ๋ ๋ช ํํ๊ณ ์ผ๊ด๋๊ฒ ํํํ ์ ์์ง!
๐ Record์ ์ง๊ฐ: Record๋ ํนํ ์ค์ ๊ฐ์ฒด, ๋งคํ ํ ์ด๋ธ, ๋๋ lookup ๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋ ๋น์ ๋ฐํด. API ์๋ต์ ๋ชจ๋ธ๋งํ๊ฑฐ๋, ์ํ ๊ด๋ฆฌ ์์คํ ์ ์ค๊ณํ ๋๋ ์์ฃผ ์ ์ฉํ์ง. ์ด๊ฑธ ์ ํ์ฉํ๋ฉด ์ฝ๋์ ๊ตฌ์กฐ๋ฅผ ๋ช ํํ ํ๊ณ , ํ์ ์์ ์ฑ์ ๋์ผ ์ ์์ด!
๐ง Record ์ฌํ: ๋์ ํค ๋ค๋ฃจ๊ธฐ
์, ์ด์ ์ข ๋ ๋ณต์กํ ์ํฉ์ ์๊ฐํด๋ณด์. ํค๊ฐ ๋ฏธ๋ฆฌ ์ ํด์ ธ ์์ง ์๊ณ ๋์ ์ผ๋ก ์์ฑ๋๋ ๊ฒฝ์ฐ๋ ์ด๋จ๊น? Record๋ ์ด๋ฐ ์ํฉ์์๋ ์์ฃผ ์ ์ฉํด!
type DynamicKey = string;
type UserData = { name: string; age: number };
type UserDatabase = Record<dynamickey userdata>;
const users: UserDatabase = {
"user_001": { name: "Alice", age: 28 },
"user_002": { name: "Bob", age: 32 },
// ์ฐ๋ฆฌ๋ ๊ณ์ํด์ ์๋ก์ด ์ฌ์ฉ์๋ฅผ ์ถ๊ฐํ ์ ์์ด!
};
function addUser(id: string, data: UserData) {
users[id] = data;
}
addUser("user_003", { name: "Charlie", age: 45 });
</dynamickey>
์์ฐ! ์ด์ ์ฐ๋ฆฌ๋ ๋์ ์ผ๋ก ํค๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ ์ ์๋ ์ ์ฐํ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ฒ ๋์ด. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ์ฌ์ฉ์๊ฐ ๊ฐ์ ํ ๋๋ง๋ค ๊ทธ๋ค์ ์ ๋ณด๋ฅผ ์ผ๊ด๋ ๊ตฌ์กฐ๋ก ์ ์ฅํ๋ ๊ฒ๊ณผ ๊ฐ์! ๐๏ธ๐ฅ
์ด ๋ค์ด์ด๊ทธ๋จ์ ์ฐ๋ฆฌ์ UserDatabase๋ฅผ ์๊ฐํํ ๊ฑฐ์ผ. ๊ฐ ์ฌ์ฉ์๊ฐ ๊ณ ์ ํ ํค๋ฅผ ๊ฐ์ง๊ณ ์๊ณ , ๊ทธ์ ํด๋นํ๋ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์์ด. Record๋ฅผ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ๋์ ์ผ๋ก ํ์ฅ ๊ฐ๋ฅํ ๊ตฌ์กฐ๋ฅผ ํ์ ์์ ํ๊ฒ ๋ง๋ค ์ ์์ง!
๐ก ์ค์ ํ: ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ฐ ๋์ ํค ๊ตฌ์กฐ๋ฅผ ์์ฃผ ์ฌ์ฉํ๊ฒ ๋ ๊ฑฐ์ผ. ํนํ ๋ฐ์ดํฐ ์บ์ฑ, ์ํ ๊ด๋ฆฌ, ๋๋ ๋๊ท๋ชจ ๋ฐ์ดํฐ ์งํฉ์ ๋ค๋ฃฐ ๋ ์ด๋ฐ ๊ธฐ์ ์ด ๋น์ ๋ฐํ์ง. ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ์ฌ๋ฅ ์นดํ ๊ณ ๋ฆฌ๊ฐ ์ถ๊ฐ๋ ๋๋ง๋ค ์ ์ฐํ๊ฒ ๋์ํ ์ ์๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ!
๐ญ Record์ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ข์ ์น๊ตฌ๋ค
Record๋ ๋ค๋ฅธ ํ์ ์ ํธ๋ฆฌํฐ๋ค๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋์ฑ ๊ฐ๋ ฅํด์ ธ. ๋ช ๊ฐ์ง ์๋ฅผ ์ดํด๋ณผ๊น?
- Partial
: Record์ ๊ฐ ํ์ ์ ์ ํ์ ์ผ๋ก ๋ง๋ค ์ ์์ด. - Readonly
: Record์ ํค-๊ฐ ์์ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค ์ ์์ด. - Pick
: Record์ ํน์ ํค๋ง ์ ํํด์ ์๋ก์ด ํ์ ์ ๋ง๋ค ์ ์์ด.
์ด๋ค์ Record์ ์กฐํฉํด์ ์ฌ์ฉํ๋ฉด ์ ๋ง ๋ค์ํ ์ํฉ์ ๋์ํ ์ ์์ด. ์๋ฅผ ๋ค์ด๋ณผ๊น?
type UserRole = "admin" | "moderator" | "user";
type Permission = "read" | "write" | "delete";
type RolePermissions = Record<userrole readonly boolean>>>>;
const permissions: RolePermissions = {
admin: { read: true, write: true, delete: true },
moderator: { read: true, write: true },
user: { read: true }
};
// permissions.admin.read = false; // Error: Cannot assign to 'read' because it is a read-only property.
// permissions.user.delete = true; // OK: We can add missing permissions
</userrole>
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ ์ญํ ์ ๋ํ ๊ถํ์ ์ ์ฐํ๊ฒ ์ ์ํ ์ ์์ผ๋ฉด์๋, ํ๋ฒ ์ค์ ๋ ๊ถํ์ ๋ณ๊ฒฝํ ์ ์๊ฒ ๋ง๋ค ์ ์์ด. ์์ ์์ ํ๋ฉด์๋ ์ ์ฐํ์ง ์์? ๐
์ด ๋ค์ด์ด๊ทธ๋จ์ Record์ ๋ค๋ฅธ ํ์ ์ ํธ๋ฆฌํฐ๋ค์ ๊ด๊ณ๋ฅผ ๋ณด์ฌ์ค. Record๊ฐ ์ค์ฌ์ ์๊ณ , ๋ค๋ฅธ ์ ํธ๋ฆฌํฐ๋ค์ด ์ฃผ๋ณ์ ๋๋ฌ์ธ๊ณ ์์ด. ์ด๋ค์ ์ ์ ํ ์กฐํฉํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ํ์ ์ ๋ง๋ค ์ ์์ง!
๐ Record์ ํ: Record๋ ํนํ ๋ณต์กํ ๊ฐ์ฒด ๊ตฌ์กฐ๋ฅผ ๋ค๋ฃฐ ๋ ๋น์ ๋ฐํด. API ์๋ต ๋ชจ๋ธ๋ง, ์ํ ๊ด๋ฆฌ ์์คํ ์ค๊ณ, ์ค์ ๊ฐ์ฒด ์์ฑ ๋ฑ์์ ์์ฃผ ์ ์ฉํ์ง. ์ด๊ฑธ ์ ํ์ฉํ๋ฉด ์ฝ๋์ ๊ตฌ์กฐ๋ฅผ ๋ช ํํ ํ๊ณ , ํ์ ์์ ์ฑ์ ํฌ๊ฒ ๋์ผ ์ ์์ด!
์, ์ด์ Record์ ๋ํด ๊ฝค ๊น์ด ์์๋ดค์ด. ์ด ๋ ์์ ์ ํ์ฉํ๋ฉด ๋ค ์ฝ๋๊ฐ ํจ์ฌ ๋ ๊ตฌ์กฐ์ ์ด๊ณ ํ์ ์์ ํด์ง ๊ฑฐ์ผ. ๋ค์์ผ๋ก๋ Pick์ ๋ํด ์์๋ณผ ํ ๋ฐ, ์ด๊ฒ๋ ์ ๋ง ์ฌ๋ฐ์ ๊ฑฐ์ผ! ๊ณ์ ๋ฐ๋ผ์์ค! ๐
๐ Pick: ํ๋กํผํฐ ์ ๋ณ์ ๋ฌ์ธ ๐
์, ์ด์ ์ฐ๋ฆฌ์ ๋ง์ง๋ง ์ฃผ์ธ๊ณต Pick์ ๋ง๋๋ณผ ์๊ฐ์ด์ผ! Pick์ ์ ๋ง ์ฌ๋ฏธ์๋ ๋ ์์ด์ผ. ์ด ํ์ ์ ๊ฐ์ฒด์์ ํน์ ํ๋กํผํฐ๋ง์ ์ ํํด์ ์๋ก์ด ํ์ ์ ๋ง๋ค์ด๋ด๋ ๋ฐ ์ฌ์ฉ๋ผ. ๋ง์น ๊ณผ์ผ ๋ฐ๊ตฌ๋์์ ์ํ๋ ๊ณผ์ผ๋ง ๊ณจ๋ผ๋ด๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ!
Pick์ ๊ธฐ๋ณธ ํํ๋ ์ด๋ ๊ฒ ์๊ฒผ์ด:
Pick<t k></t>
์ฌ๊ธฐ์ T๋ ์๋ณธ ํ์ ์ด๊ณ , K๋ ์ ํํ๊ณ ์ถ์ ํ๋กํผํฐ์ ์ ๋์จ ํ์ ์ด์ผ. ์๋ฅผ ๋ค์ด๋ณผ๊น?
interface Person {
name: string;
age: number;
address: string;
email: string;
phone: string;
}
type ContactInfo = Pick<person>;
// ContactInfo๋ ์ด๋ ๊ฒ ๋ฉ๋๋ค:
// {
// email: string;
// phone: string;
// }
</person>
์ง์! ์ด๋ ๊ฒ ํ๋ฉด ContactInfo ํ์ ์ Person ํ์ ์์ email๊ณผ phone ํ๋กํผํฐ๋ง์ ๊ฐ์ ธ์จ ์๋ก์ด ํ์ ์ด ๋ผ. ๋ง์น ์ฐ๋ฝ์ฒ ์ ๋ณด๋ง ํ์ํ ๋ ์ฌ์ฉํ๊ธฐ ๋ฑ ์ข๊ฒ ์ง? ๐โ๏ธ
๐ก ์ ์ด๊ฒ ์ ์ฉํ ๊น? Pick์ ํฐ ๊ฐ์ฒด์์ ํ์ํ ๋ถ๋ถ๋ง ์ถ์ถํด์ผ ํ ๋ ์์ฃผ ์ ์ฉํด. API ์๋ต์์ ํน์ ํ๋๋ง ์ฌ์ฉํ๊ณ ์ถ์ ๋, ๋๋ ํฐ ๊ฐ์ฒด์ ์ผ๋ถ๋ถ๋ง ํจ์์ ์ ๋ฌํ๊ณ ์ถ์ ๋ ์๋ฒฝํ์ง. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ์ฉ์์ ๋ชจ๋ ์ ๋ณด ์ค์์ ํ๋กํ์ ํ์ํ ์ ๋ณด๋ง ๊ณจ๋ผ๋ด๋ ๊ฒ๊ณผ ๋น์ทํด!
Pick์ ์ฌ์ฉํ๋ฉด, ํ์ํ ํ๋กํผํฐ๋ง ์ ํํ๊ฒ ์ ํํ ์ ์์ด. ์ด๋ ์ฝ๋์ ๋ช ํ์ฑ์ ๋์ด๊ณ , ๋ถํ์ํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ์ค์ฌ์ค. ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ์ํฉ์ ๊ผญ ํ์ํ ์ฌ์ฉ์ ์ ๋ณด๋ง ์ฌ์ฉํ๋ ๊ฒ์ฒ๋ผ ํจ์จ์ ์ด์ง! ๐
๐จ Pick ํ์ฉ ์์: ์ฌ์ฉ์ ํ๋กํ ์์คํ
์, ์ด์ Pick์ ์ค์ ๋ก ์ด๋ป๊ฒ ํ์ฉํ ์ ์๋์ง ์ฌ๋ฏธ์๋ ์์๋ฅผ ๋ค์ด๋ณผ๊ฒ. ์ฐ๋ฆฌ๊ฐ ์์ ๋ฏธ๋์ด ํ๋ซํผ์ ์ฌ์ฉ์ ํ๋กํ ์์คํ ์ ๋ง๋ ๋ค๊ณ ์๊ฐํด๋ณด์!
interface User {
id: number;
username: string;
email: string;
password: string;
firstName: string;
lastName: string;
bio: string;
birthDate: Date;
registrationDate: Date;
lastLoginDate: Date;
}
type PublicProfile = Pick<user>;
type LoginCredentials = Pick<user>;
function displayProfile(profile: PublicProfile) {
console.log(`${profile.firstName} ${profile.lastName} (@${profile.username})`);
console.log(`Bio: ${profile.bio}`);
}
function login(credentials: LoginCredentials) {
// ๋ก๊ทธ์ธ ๋ก์ง
console.log(`Logging in ${credentials.email}...`);
}
const user: User = {
id: 1,
username: "codingguru",
email: "guru@code.com",
password: "supersecret",
firstName: "Coding",
lastName: "Guru",
bio: "I love TypeScript!",
birthDate: new Date(1990, 1, 1),
registrationDate: new Date(2020, 1, 1),
lastLoginDate: new Date()
};
displayProfile(user);
login(user);
</user></user>
์์ฐ! ์ด์ ์ฐ๋ฆฌ๋ ์ํฉ์ ๋ฐ๋ผ ํ์ํ ์ฌ์ฉ์ ์ ๋ณด๋ง ์ ํํ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ๋์ด. ๊ณต๊ฐ ํ๋กํ์๋ ๋ฏผ๊ฐํ ์ ๋ณด๊ฐ ํฌํจ๋์ง ์๊ณ , ๋ก๊ทธ์ธ ์์๋ ํ์ํ ์ ๋ณด๋ง ์ฌ์ฉํ๊ณ ์์ง. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ๊ฐ ํ์ด์ง๋ ๊ธฐ๋ฅ์ ๋ง๋ ์ฌ์ฉ์ ์ ๋ณด๋ง ๊ณจ๋ผ์ ์ฌ์ฉํ๋ ๊ฒ๊ณผ ๊ฐ์. ์์ ํ๊ณ ํจ์จ์ ์ด์ผ! ๐ก๏ธ๐
์ด SVG๋ ์ฐ๋ฆฌ์ ์ฌ์ฉ์ ํ๋กํ ์์คํ ์ ์๊ฐํํ ๊ฑฐ์ผ. ์ผ์ชฝ์ ๊ณต๊ฐ ํ๋กํ์ ์ฌ์ฉ๋๋ ์ ๋ณด๋ฅผ, ์ค๋ฅธ์ชฝ์ ๋ก๊ทธ์ธ์ ์ฌ์ฉ๋๋ ์ ๋ณด๋ฅผ ๋ํ๋ด๊ณ ์์ด. Pick์ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ํฐ User ๊ฐ์ฒด์์ ํ์ํ ๋ถ๋ถ๋ง ์ ํํ๊ฒ ์ถ์ถํด์ ์ฌ์ฉํ ์ ์์ง!
๐ Pick์ ์ง๊ฐ: Pick์ ํนํ ํฐ ๊ฐ์ฒด๋ ๋ณต์กํ ํ์ ์ ๋ค๋ฃฐ ๋ ๋น์ ๋ฐํด. API ์๋ต์ ์ฒ๋ฆฌํ๊ฑฐ๋, ์ปดํฌ๋ํธ์ props๋ฅผ ์ ๋ฌํ ๋, ๋๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ชจ๋ธ์ ์ผ๋ถ๋ง ์ฌ์ฉํด์ผ ํ ๋ ์์ฃผ ์ ์ฉํ์ง. ์ด๊ฑธ ์ ํ์ฉํ๋ฉด ์ฝ๋์ ํ์ ์์ ์ฑ์ ๋์ด๊ณ , ์๋๋ฅผ ๋ช ํํ ํํํ ์ ์์ด!
๐ง Pick ์ฌํ: ์กฐ๊ฑด๋ถ ํ์ ๊ณผ ํจ๊ป ์ฌ์ฉํ๊ธฐ
์, ์ด์ ์ข ๋ ๋ณต์กํ ์ํฉ์ ์๊ฐํด๋ณด์. Pick์ ์กฐ๊ฑด๋ถ ํ์ ๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋์ฑ ๊ฐ๋ ฅํ ํ์ ์ ๋ง๋ค ์ ์์ด. ์๋ฅผ ๋ค์ด, ํน์ ์กฐ๊ฑด์ ๋ฐ๋ผ ๋ค๋ฅธ ํ๋กํผํฐ๋ฅผ ์ ํํ๊ณ ์ถ๋ค๋ฉด ์ด๋ป๊ฒ ํ ๊น?
type UserRoles = 'admin' | 'moderator' | 'user';
interface UserData {
id: number;
username: string;
email: string;
role: UserRoles;
adminToken?: string;
moderatorCode?: string;
}
type RoleSpecificInfo<t extends userroles> = Pick<userdata extends : t never>;
function getUserInfo<t extends userroles>(user: UserData, role: T): RoleSpecificInfo<t> {
return user as RoleSpecificInfo<t>;
}
const adminUser: UserData = {
id: 1,
username: "superadmin",
email: "admin@example.com",
role: "admin",
adminToken: "secret-token"
};
const userInfo = getUserInfo(adminUser, "admin");
console.log(userInfo.adminToken); // OK
// console.log(userInfo.moderatorCode); // Error: Property 'moderatorCode' does not exist on type 'RoleSpecificInfo<"admin">'
</t></t></t></userdata></t>
์์ฐ! ์ด์ ์ฐ๋ฆฌ๋ ์ฌ์ฉ์์ ์ญํ ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ ๋ณด๋ฅผ ํฌํจํ๋ ํ์ ์ ๋์ ์ผ๋ก ์์ฑํ ์ ์๊ฒ ๋์ด. ์ด๊ฑด ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ์ฉ์์ ์ญํ ์ ๋ฐ๋ผ ๋ค๋ฅธ ๋์๋ณด๋๋ฅผ ์ ๊ณตํ๋ ๊ฒ๊ณผ ๊ฐ์! ๐
์ด ๋ค์ด์ด๊ทธ๋จ์ ์ฐ๋ฆฌ์ ์ญํ ๋ณ ์ฌ์ฉ์ ์ ๋ณด ์์คํ ์ ์๊ฐํํ ๊ฑฐ์ผ. ๊ฐ ์ญํ ๋ง๋ค ๊ณตํต ์ ๋ณด์ ํจ๊ป ์ญํ ํน์ ์ ๋ณด๊ฐ ํฌํจ๋์ด ์์ด. Pick๊ณผ ์กฐ๊ฑด๋ถ ํ์ ์ ์ฌ์ฉํ๋ฉด ์ด๋ ๊ฒ ๋ณต์กํ ํ์ ๊ตฌ์กฐ๋ ์ ์ฐํ๊ฒ ๋ง๋ค ์ ์์ง!
๐ก ์ค์ ํ: ์ค์ ํ๋ก์ ํธ์์๋ ์ด๋ฐ ๋์ ํ์ ์์ฑ์ ์์ฃผ ์ฌ์ฉํ๊ฒ ๋ ๊ฑฐ์ผ. ํนํ ๊ถํ ๊ด๋ฆฌ, ์กฐ๊ฑด๋ถ UI ๋ ๋๋ง, ๋๋ ๋ค์ํ API ์๋ํฌ์ธํธ ์ฒ๋ฆฌ ๋ฑ์์ ์ด๋ฐ ๊ธฐ์ ์ด ๋น์ ๋ฐํ์ง. ๋ง์น ์ฌ๋ฅ๋ท์์ ์ฌ์ฉ์์ ์ญํ ์ด๋ ๊ตฌ๋ ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ!
๐ญ Pick๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ์ข์ ์น๊ตฌ๋ค
Pick์ ๋ค๋ฅธ ํ์ ์ ํธ๋ฆฌํฐ๋ค๊ณผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋์ฑ ๊ฐ๋ ฅํด์ ธ. ๋ช ๊ฐ์ง ์๋ฅผ ์ดํด๋ณผ๊น?
- Omit
: Pick์ ๋ฐ๋๋ก, ํน์ ํ๋กํผํฐ๋ฅผ ์ ์ธํ ํ์ ์ ๋ง๋ค์ด. - Partial
: ์ ํํ ํ๋กํผํฐ๋ฅผ ๋ชจ๋ ์ ํ์ ์ผ๋ก ๋ง๋ค ์ ์์ด. - Readonly
: ์ ํํ ํ๋กํผํฐ๋ฅผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค ์ ์์ด.
์ด๋ค์ Pick๊ณผ ์กฐํฉํด์ ์ฌ์ฉํ๋ฉด ์ ๋ง ๋ค์ํ ์ํฉ์ ๋์ํ ์ ์์ด. ์๋ฅผ ๋ค์ด๋ณผ๊น?
interface Article {
id: number;
title: string;
content: string;
author: string;
createdAt: Date;
updatedAt: Date;
tags: string[];
likes: number;
}
type ArticlePreview = Readonly<pick>>;
type EditableArticleFields = Partial<pick>>;
function displayArticlePreview(preview: ArticlePreview) {
console.log(`${preview.title} by ${preview.author}`);
}
function updateArticle(id: number, fields: EditableArticleFields) {
// ์
๋ฐ์ดํธ ๋ก์ง
console.log(`Updating article ${id} with:`, fields);
}
const articlePreview: ArticlePreview = {
id: 1,
title: "TypeScript is Awesome",
author: "Coding Guru"
};
displayArticlePreview(articlePreview);
updateArticle(1, { title: "TypeScript is Super Awesome", tags: ["typescript", "programming"] });
</pick></pick>
์ด๋ ๊ฒ ํ๋ฉด ์ํฐํด ๋ฏธ๋ฆฌ๋ณด๊ธฐ์๋ ํ์ํ ์ ๋ณด๋ง ํฌํจ๋๊ณ , ์์ ๊ฐ๋ฅํ ํ๋๋ ๋ณ๋๋ก ์ ์ํ ์ ์์ด. ์์ ์ ์ฐํ๋ฉด์๋ ํ์ ์์ ํ์ง ์์? ๐
์ด ๋ค์ด์ด๊ทธ๋จ์ Pick๊ณผ ๋ค๋ฅธ ํ์ ์ ํธ๋ฆฌํฐ๋ค์ ๊ด๊ณ๋ฅผ ๋ณด์ฌ์ค. Pick์ด ์ค์ฌ์ ์๊ณ , ๋ค๋ฅธ ์ ํธ๋ฆฌํฐ๋ค์ด ์ฃผ๋ณ์ ๋๋ฌ์ธ๊ณ ์์ด. ์ด๋ค์ ์ ์ ํ ์กฐํฉํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ๊ณ ์ ์ฐํ ํ์ ์ ๋ง๋ค ์ ์์ง!
๐ Pick์ ํ: Pick์ ํนํ ํฐ ์ธํฐํ์ด์ค๋ ํ์ ์์ ํ์ํ ๋ถ๋ถ๋ง ์ถ์ถํด์ผ ํ ๋ ๋น์ ๋ฐํด. API ์๋ต ์ฒ๋ฆฌ, ํผ ๋ฐ์ดํฐ ๊ด๋ฆฌ, ์ํ ์ ๋ฐ์ดํธ ๋ฑ์์ ์์ฃผ ์ ์ฉํ์ง. ์ด๊ฑธ ์ ํ์ฉํ๋ฉด ์ฝ๋์ ํ์ ์์ ์ฑ์ ๋์ด๊ณ , ์๋๋ฅผ ๋ช ํํ ํํํ ์ ์์ด!
์, ์ด์ Pick์ ๋ํด ๊ฝค ๊น์ด ์์๋ดค์ด. ์ด ๋ ์์ ์ ํ์ฉํ๋ฉด ๋ค ์ฝ๋๊ฐ ํจ์ฌ ๋ ๋ช ํํ๊ณ ํ์ ์์ ํด์ง ๊ฑฐ์ผ. ์ฐ๋ฆฌ๊ฐ ์ง๊ธ๊น์ง ๋ฐฐ์ด Partial, Readonly, Record, Pick ์ด ๋ค ๊ฐ์ง ํ์ ์ ํธ๋ฆฌํฐ๋ฅผ ์ ์กฐํฉํ๋ฉด ์ ๋ง ๊ฐ๋ ฅํ ํ์ ์์คํ ์ ๊ตฌ์ถํ ์ ์์ด. ๊ณ์ ์ฐ์ตํ๊ณ ์คํํด๋ด! ๐
๐ ๊ฒฐ๋ก : ํ์ ์คํฌ๋ฆฝํธ ๋ง์คํฐ์ ๊ธธ ๐
์ฐ์, ์ ๋ง ๊ธด ์ฌ์ ์ด์์ด! ์ฐ๋ฆฌ๋ ํ์ ์คํฌ๋ฆฝํธ์ ๊ฐ๋ ฅํ ํ์ ์ ํธ๋ฆฌํฐ ๋ค ๊ฐ์ง๋ฅผ ๊น์ด ์๊ฒ ์ดํด๋ดค์ง. ์ด์ ๋๋ Partial, Readonly, Record, Pick์ ์์ ์์ฌ๋ก ๋ค๋ฃฐ ์ ์๋ ์ค๋ ฅ์๊ฐ ๋์ด! ๐
์ด ๋ค ๊ฐ์ง ์ ํธ๋ฆฌํฐ๋ ๊ฐ๊ฐ ๋ค์๊ณผ ๊ฐ์ ํน์ง์ ๊ฐ์ง๊ณ ์์ด:
- Partial
: ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์ ํ์ ์ผ๋ก ๋ง๋ค์ด ์ ์ฐ์ฑ์ ๋์ฌ์ค. - Readonly
: ๋ชจ๋ ํ๋กํผํฐ๋ฅผ ์ฝ๊ธฐ ์ ์ฉ์ผ๋ก ๋ง๋ค์ด ๋ถ๋ณ์ฑ์ ๋ณด์ฅํด์ค. - Record
: ํค-๊ฐ ์์ ๊ฐ์ฒด๋ฅผ ์ฝ๊ฒ ์ ์ํ ์ ์๊ฒ ํด์ค. - Pick
: ์ํ๋ ํ๋กํผํฐ๋ง ์ ํํด์ ์๋ก์ด ํ์ ์ ๋ง๋ค ์ ์๊ฒ ํด์ค.
์ด ๋๊ตฌ๋ค์ ์ ํ์ฉํ๋ฉด, ๋์ ์ฝ๋๋ ๋์ฑ ์์ ํ๊ณ , ๋ช ํํ๋ฉฐ, ์ ์ฐํด์ง ๊ฑฐ์ผ. ๋ง์น ์ฌ๋ฅ๋ท์์ ๋ค์ํ ์ฌ๋ฅ์ ์กฐํฉํด ์๋ก์ด ๊ฐ์น๋ฅผ ์ฐฝ์ถํ๋ ๊ฒ์ฒ๋ผ ๋ง์ด์ผ! ๐
๐ก ์ต์ข ํ: ์ด ์ ํธ๋ฆฌํฐ๋ค์ ์ค์ ํ๋ก์ ํธ์ ์ ์ฉํด๋ณด๋ฉด์ ๊ฒฝํ์ ์์๊ฐ๋ ๊ฒ ์ค์ํด. ์ฒ์์๋ ์ด์ํ ์ ์์ง๋ง, ์ฌ์ฉํ๋ฉด ์ฌ์ฉํ ์๋ก ๊ทธ ๊ฐ์น๋ฅผ ๋ ๊น์ด ์ดํดํ๊ฒ ๋ ๊ฑฐ์ผ. ๊ทธ๋ฆฌ๊ณ ์ด๋ค์ ์กฐํฉํด์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ๋ ๊ณ์ ํ๊ตฌํด๋ด. ๋ฌด๊ถ๋ฌด์งํ ๊ฐ๋ฅ์ฑ์ด ์์ผ๋๊น!
ํ์ ์คํฌ๋ฆฝํธ์ ์ธ๊ณ๋ ์ ๋ง ๋๊ณ ๊น์ด. ์ฐ๋ฆฌ๊ฐ ์ค๋ ๋ฐฐ์ด ๊ฒ์ ๊ทธ ์ค ์ผ๋ถ์ ๋ถ๊ณผํด. ํ์ง๋ง ์ด ๊ธฐ์ด๋ฅผ ์ ๋ค์ ธ๋์ผ๋ฉด, ์์ผ๋ก ๋ ๋ณต์กํ๊ณ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค๋ ์ฝ๊ฒ ์ต๋ํ ์ ์์ ๊ฑฐ์ผ.
๊ณ์ํด์ ๊ณต๋ถํ๊ณ , ์คํํ๊ณ , ์ฝ๋๋ฅผ ์์ฑํด๋ด. ๊ทธ๋ฆฌ๊ณ ๊ฐ์ฅ ์ค์ํ ๊ฑด, ์ฆ๊ธฐ๋ ๊ฑฐ์ผ! ์ฝ๋ฉ์ ๊ฒฐ๊ตญ ์ฐฝ์กฐ์ ๊ณผ์ ์ด๋๊น. ๋ง์น ์ฌ๋ฅ๋ท์์ ์๋ก์ด ์ฌ๋ฅ์ ๋ฐ๊ฒฌํ๊ณ ๋ฐ์ ์ํค๋ ๊ฒ์ฒ๋ผ, ๋์ ํ์ ์คํฌ๋ฆฝํธ ์ค๋ ฅ๋ ๊ณ์ํด์ ์ฑ์ฅํ ๊ฑฐ์ผ. ๐ฑ
์, ์ด์ ๋์ ์ฐจ๋ก์ผ. ๊ฐ์ ๋ฉ์ง ์ฝ๋๋ฅผ ์์ฑํด๋ด! ํ์ ์คํฌ๋ฆฝํธ ๋ง์คํฐ์ ๊ธธ์ ํฅํด ๊ณ์ ์ ์งํ์! ํ์ดํ ! ๐๐
- ์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์ฌ๋ฅ๋ท์ ์ต์ AI ๊ธฐ์ ๊ณผ ๋ฒ๋ฅ ์ ๊ธฐ๋ฐํ์ฌ ์์ฌ์ ์ง์ ์ฌ์ฐ๊ถ์ ์ ๊ทน์ ์ผ๋ก ๋ณดํธํ๋ฉฐ,
๋ฌด๋จ ์ฌ์ฉ ๋ฐ ์นจํด ํ์์ ๋ํด ๋ฒ์ ๋์์ ํ ๊ถ๋ฆฌ๋ฅผ ๋ณด์ ํฉ๋๋ค.
ยฉ 2025 ์ฌ๋ฅ๋ท | All rights reserved.
๋๊ธ 0๊ฐ