๋ณธ๋ฌธ์œผ๋กœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

๐Ÿค Chapter 4: ํƒ€์ž… ์„ค๊ณ„

๐Ÿฅ• ์•„์ดํ…œ 28. ์œ ํšจํ•œ ์ƒํƒœ๋งŒ ํ‘œํ˜„ํ•˜๋Š” ํƒ€์ž…์„ ์ง€ํ–ฅํ•˜๊ธฐโ€‹

ํšจ๊ณผ์ ์œผ๋กœ ํƒ€์ž…์„ ์„ค๊ณ„ํ•˜๋ ค๋ฉด, ์œ ํšจํ•œ ์ƒํƒœ๋งŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ํƒ€์ž…์„ ๋งŒ๋“ค์–ด ๋‚ด๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํŽ˜์ด์ง€๋ฅผ ์„ ํƒํ•˜๋ฉด, ํŽ˜์ด์ง€์˜ ๋‚ด์šฉ์„ ๋กœ๋“œํ•˜๊ณ  ํ™”๋ฉด์— ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ํŽ˜์ด์ง€์˜ ์ƒํƒœ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ ์„ค๊ณ„ํ–ˆ์Šต๋‹ˆ๋‹ค.

interface State {
pageText: string;
isLoading: boolean;
error?: string;
}

function renderPage(state: State) {
if (state.error) {
return `Error! Unable to load ${currentPage}: ${state.error}`;
} else if (state.isLoading) {
return `Loading ${currentPage}...`;
}
return `<h1>${currentPage}</h1>\n${state.pageText}`;
}

์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด ๋ถ„๊ธฐ ์กฐ๊ฑด์ด ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
ํ•œํŽธ ํŽ˜์ด์ง€๋ฅผ ์ „ํ™˜ํ•˜๋Š” changePage ํ•จ์ˆ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

async function changePage(state: State, newPage: string) {
state.isLoading = true;
try {
const response = await fetch(getUrlForPage(newPage));
if (!response.ok) {
throw new Error(`Unable to load ${newPage}: ${response.statusText}`);
}
const text = await response.text();
state.isLoading = false;
state.pageText = text
} catch (e) {
state.error = '' + e;
}
}

changePage์—๋Š” ๋งŽ์€ ๋ฌธ์ œ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ์ •๋ฆฌํ•ด ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ state.isLoading์„ false๋กœ ์„ค์ •ํ•˜๋Š” ๋กœ์ง์ด ๋น ์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.
  • state.error๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์—, ํŽ˜์ด์ง€ ์ „ํ™˜ ์ค‘์— ๋กœ๋”ฉ ๋ฉ”์‹œ์ง€ ๋Œ€์‹  ๊ณผ๊ฑฐ์˜ ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ๋ณด์—ฌ ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ํŽ˜์ด์ง€ ๋กœ๋”ฉ ์ค‘์— ์‚ฌ์šฉ์ž๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ๋ฐ”๊ฟ” ๋ฒ„๋ฆฌ๋ฉด ์–ด๋–ค ์ผ์ด ๋ฒŒ์–ด์งˆ์ง€ ์˜ˆ์ƒํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์ƒˆ ํŽ˜์ด์ง€์— ์˜ค๋ฅ˜๊ฐ€ ๋œจ๊ฑฐ๋‚˜, ์‘๋‹ต์ด ์˜ค๋Š” ์ˆœ์„œ์— ๋”ฐ๋ผ ๋‘๋ฒˆ์งธ ํŽ˜์ด์ง€๊ฐ€ ์•„๋‹Œ ์ฒซ ๋ฒˆ์งธ ํŽ˜์ด์ง€๋กœ ์ „ํ™˜๋  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” ๋ฐ”๋กœ ์ƒํƒœ ๊ฐ’์˜ ๋‘ ๊ฐ€์ง€ ์†์„ฑ์ด ๋™์‹œ์— ์ •๋ณด๊ฐ€ ๋ถ€์กฑํ•˜๊ฑฐ๋‚˜, ๋‘ ๊ฐ€์ง€ ์†์„ฑ์ด ์ถฉ๋Œํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. State ํƒ€์ž…์€ isLoading์ด true์ด๋ฉด์„œ ๋™์‹œ์— error ๊ฐ’์ด ์„ค์ •๋˜๋Š” ๋ฌดํšจํ•œ ์ƒํƒœ๋ฅผ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฌดํšจํ•œ ์ƒํƒœ๊ฐ€ ์กด์žฌํ•˜๋ฉด render()์™€ changePage() ๋‘˜ ๋‹ค ์ œ๋Œ€๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๋‹ค์Œ์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ƒํƒœ๋ฅผ ์ข€ ๋” ์ œ๋Œ€๋กœ ํ‘œํ˜„ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

interface RequestPending {
state: 'pending';
}

interface RequestError {
state: 'error';
error: string;
}
interface RequestSuccess {
state: 'ok';
pageText: string;
}
type RequestState = RequestPending | RequestError | RequestSuccess;

interface State {
currentPage: string;
requests: {[page: string]: RequestState};
}

์ด๋ฒˆ ์˜ˆ์ œ๋Š” ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ํƒ€์ž…์˜ ์ฝ”๋“œ ๊ธธ์ด๊ฐ€ ์„œ๋„ˆ ๋ฐฐ ๊ธธ์–ด์ง€๊ธด ํ–ˆ์ง€๋งŒ, ๋ฌดํšจํ•œ ์ƒํƒœ๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋„๋ก ํฌ๊ฒŒ ๊ฐœ์„ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ํŽ˜์ด์ง€๋Š” ๋ฐœ์ƒํ•˜๋Š” ๋ชจ๋“  ์š”์ฒญ์˜ ์ƒํƒœ๋กœ์„œ, ๋ช…์‹œ์ ์œผ๋กœ ๋ชจ๋ธ๋ง๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ๋กœ ๊ฐœ์„ ๋œ renderPage์™€ changePage ํ•จ์ˆ˜๋Š” ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function renderPage(state: State) {
const { currentPage } = state;
const requestState = state.requests[currentPage];
switch (requestState.state) {
case 'pending':
return `Loading ${currentPage}...`;
case 'error':
return `Error! Unable to load ${currentPage}: ${requestState.error}`;
case 'ok':
return `<h1>${currentPage}</h1>\n${requestState.pageText}`;
}
}

async function changePage(state: State, newPage: string) {
state.requests[newPage] = { state: 'pending' };
state.currentPage = newPage;

try {
const response = await fetch(getUrlForPage(newPage));
if (!response.ok) {
throw new Error(`Unable to load ${newPage}: ${response.statusText}`);
}
const pageText = await response.text();
state.requests[newPage] = { state: 'ok', pageText };
} catch (e) {
state.requests[newPage] = { state: 'error', error: '' + e };
}
}

์ด๋ฒˆ ์•„์ดํ…œ์˜ ์ฒ˜์Œ์— ๋“ฑ์žฅํ–ˆ๋˜ ๋ชจํ˜ธํ•จ์€ ์™„์ „ํžˆ ์‚ฌ๋ผ์กŒ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ํŽ˜์ด์ง€๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋ช…ํ™•ํ•˜๋ฉฐ, ๋ชจ๋“  ์š”์ฒญ์€ ์ •ํ™•ํžˆ ํ•˜๋‚˜์˜ ์ƒํƒœ๋กœ ๋งž์•„ ๋–จ์–ด์ง‘๋‹ˆ๋‹ค. ์š”์ฒญ์ด ์ง„ํ–‰ ์ค‘์ธ ์ƒํƒœ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ํŽ˜์ด์ง€๋ฅผ ๋ณ€๊ฒฝํ•˜๋”๋ผ๊ณ  ๋ฌธ์ œ์—†์Šต๋‹ˆ๋‹ค. ๋ฌดํšจ๊ฐ€ ๋œ ์š”์ฒญ์ด ์‹คํ–‰๋˜๊ธด ํ•˜๊ฒ ์ง€๋งŒ UI์—๋Š” ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํƒ€์ž…์„ ์„ค๊ณ„ํ•  ๋•Œ๋Š” ์–ด๋–ค ๊ฐ’๋“ค์„ ํฌํ•จํ•˜๊ณ  ์–ด๋–ค ๊ฐ’๋“ค์„ ์ œ์™ธํ• ์ง€ ์‹ ์ค‘ํ•˜๊ฒŒ ์ƒ๊ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์œ ํšจํ•œ ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐ’๋งŒ ํ—ˆ์šฉํ•œ๋‹ค๋ฉด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์‰ฌ์›Œ์ง€๊ณ  ํƒ€์ž… ์ฒดํฌ๊ฐ€ ์šฉ์ดํ•ด์ง‘๋‹ˆ๋‹ค. ์œ ํšจํ•œ ์ƒํƒœ๋งŒ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ์€ ๋งค์šฐ ์ผ๋ฐ˜์ ์ธ ์›์น™์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด ํŠน์ •ํ•œ ์ƒํ™ฉ์—์„œ ์ง€์ผœ์•ผํ•  ์›์น™๋“ค๋„ ์žˆ๋Š”๋ฐ, 4์žฅ์˜ ๋‹ค๋ฅธ ์•„์ดํ…œ๋“ค์—์„œ ๋‹ค๋ฃจ๊ฒ ์Šต๋‹ˆ๋‹ค.

์š”์•ฝโ€‹

  • ์œ ํšจํ•œ ์ƒํƒœ์™€ ๋ฌดํšจํ•œ ์ƒํƒœ๋ฅผ ๋‘˜ ๋‹ค ํ‘œํ˜„ํ•˜๋Š” ํƒ€์ž…์€ ํ˜ผ๋ž€์„ ์ดˆ๋ž˜ํ•˜๊ธฐ ์‰ฝ๊ณ  ์˜ค๋ฅ˜๋ฅผ ์œ ๋ฐœํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
  • ์œ ํšจํ•œ ์ƒํƒœ๋งŒ ํ‘œํ˜„ํ•˜๋Š” ํƒ€์ž…์„ ์ง€ํ–ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๊ฑฐ๋‚˜ ํ‘œํ˜„ํ•˜๊ธฐ ์–ด๋ ต์ง€๋งŒ ๊ฒฐ๊ตญ์€ ์‹œ๊ฐ„์„ ์ ˆ์•ฝํ•˜๊ณ  ๊ณ ํ†ต์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿฅ• ์•„์ดํ…œ 29. ์‚ฌ์šฉํ•  ๋•Œ๋Š” ๋„ˆ๊ทธ๋Ÿฝ๊ฒŒ, ์ƒ์„ฑํ•  ๋•Œ๋Š” ์—„๊ฒฉํ•˜๊ฒŒโ€‹

ํ•จ์ˆ˜์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํƒ€์ž…์˜ ๋ฒ”์œ„๊ฐ€ ๋„“์–ด๋„ ๋˜์ง€๋งŒ, ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํƒ€์ž…์˜ ๋ฒ•์œ„๊ฐ€ ๋” ๊ตฌ์ฒด์ ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์ œ P. 163 ~ P. 166 ์ฐธ๊ณ 

์š”์•ฝโ€‹

  • ๋ณดํ†ต ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์€ ๋ฐ˜ํ™˜ ํƒ€์ž…์— ๋น„ํ•ด ๋ฒ”์œ„๊ฐ€ ๋„’์€ ๊ฒฝํ–ฅ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์„ ํƒ์  ์†์„ฑ๊ณผ ์œ ๋‹ˆ์˜จ ํƒ€์ž…์€ ๋ฐ˜ํ™˜ ํƒ€์ž…๋ณด๋‹ค ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์— ๋” ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.
  • ๋งค๊ฐœ๋ณ€์ˆ˜์™€ ๋ฐ˜ํ™˜ ํƒ€์ž…์˜ ์žฌ์‚ฌ์šฉ์„ ์œ„ํ•ด์„œ ๊ธฐ๋ณธ ํ˜•ํƒœ(๋ฐ˜ํ™˜ ํƒ€์ž…)์™€ ๋Š์Šจํ•œ ํ˜•ํƒœ(๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…)๋ฅผ ๋„์ž…ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๐Ÿฅ• ์•„์ดํ…œ 30. ๋ฌธ์„œ์— ํƒ€์ž… ์ •๋ณด๋ฅผ ์“ฐ์ง€ ์•Š๊ธฐโ€‹

๋‹ค์Œ ์ฝ”๋“œ์—์„œ ์ž˜๋ชป๋œ ๋ถ€๋ถ„์„ ์ฐพ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

/**
* ์ „๊ฒฝ์ƒ‰(foreground) ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
* 0 ๊ฐœ ๋˜๋Š” 1 ๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์Šต๋‹ˆ๋‹ค.
* ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ์„ ๋•Œ๋Š” ํŠน์ • ํŽ˜์ด์ง€์˜ ์ „๊ฒฝ์ƒ‰์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
**/
function getForegroundColor(page?: string) {
return page === 'login' ? { r: 127, g: 127, b: 127 } : { r: 0, g: 0, b: 0 };
}

์ฝ”๋“œ์™€ ์ฃผ์„์˜ ์ •๋ณด๊ฐ€ ๋งž์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‘˜ ์ค‘ ์–ด๋Š ๊ฒƒ์ด ์˜ณ์€์ง€ ํŒ๋‹จํ•˜๊ธฐ์—๋Š” ์ •๋ณด๊ฐ€ ๋ถ€์กฑํ•˜๋ฉฐ, ์ž˜๋ชป๋œ ์ƒํƒœ๋ผ๋Š” ๊ฒƒ๋งŒ์€ ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค.
์•ž์˜ ์˜ˆ์ œ์—์„œ ์˜๋„๋œ ๋™์ž‘์ด ์ฝ”๋“œ์— ์ œ๋Œ€๋กœ ๋ฐ˜์˜๋˜๊ณ  ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋ฉด, ์ฃผ์„์—๋Š” ์„ธ ๊ฐ€์ง€ ๋ฌธ์ œ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ํ•จ์ˆ˜๊ฐ€ string ํ˜•ํƒœ์˜ ์ƒ‰๊น”์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ์ ํ˜€ ์žˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” { r, g, b } ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ์ฃผ์„์—๋Š” ํ•จ์ˆ˜๊ฐ€ 0๊ฐœ ๋˜๋Š” 1๊ฐœ์˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›๋Š”๋‹ค๊ณ  ์„ค๋ช…ํ•˜๊ณ  ์žˆ์ง€๋งŒ, ํƒ€์ž… ์‹œ๊ทธ๋‹ˆ์ฒ˜๋งŒ ๋ณด์•„๋„ ๋ช…ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆ˜ ์žˆ๋Š” ์ •๋ณด์ž…๋‹ˆ๋‹ค.
  • ๋ถˆํ•„์š”ํ•˜๊ฒŒ ์žฅํ™ฉํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜ ์„ ์–ธ๊ณผ ๊ตฌํ˜„์ฒด๋ณด๋‹ค ์ฃผ์„์ด ๋” ๊น๋‹ˆ๋‹ค.

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์˜ ํƒ€์ž… ๊ตฌ๋ฌธ ์‹œ์Šคํ…œ์€ ๊ฐ„๊ฒฐํ•˜๊ณ , ๊ตฌ์ฒด์ ์ด๋ฉฐ, ์‰ฝ๊ฒŒ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜์˜ ์ž…๋ ฅ๊ณผ ์ถœ๋ ฅ์˜ ํƒ€์ž…์„ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์ฃผ์„๋ณด๋‹ค ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์ด๋ผ๋Š” ๊ฒƒ์€ ์ž๋ช…ํ•ฉ๋‹ˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ํƒ€์ž… ๊ตฌ๋ฌธ์€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ฒดํฌํ•ด ์ฃผ๊ธฐ ๋•Œ๋ฌธ์—, ์ ˆ๋Œ€๋กœ ๊ตฌํ˜„์ฒด์™€์˜ ์ •ํ•ฉ์„ฑ์ด ์–ด๊ธ‹๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๋ˆ„๊ตฐ๊ฐ€ ๊ฐ•์ œํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ์ฃผ์„์€ ์ฝ”๋“œ์™€ ๋™๊ธฐํ™”๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํƒ€์ž… ๊ตฌ๋ฌธ์€ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ ํƒ€์ž… ์ฒด์ปค๊ฐ€ ํƒ€์ž… ์ •๋ณด๋ฅผ ๋™๊ธฐํ™”ํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์„ ๋Œ€์‹  ํƒ€์ž… ์ •๋ณด๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๋ฉด ์ฝ”๋“œ๊ฐ€ ๋ณ€๊ฒฝ๋œ๋‹ค ํ•˜๋”๋ผ๋„ ์ •๋ณด๊ฐ€ ์ •ํ™•ํžˆ ๋™๊ธฐํ™”๋ฉ๋‹ˆ๋‹ค.
์ฃผ์„์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋˜๋Š” ํŠน์ • ํŽ˜์ด์ง€์˜ ์ „๊ฒฝ์ƒ‰์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.
function getForegroundColor(page?: string): Color {
// ...
}

ํŠน์ • ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์„ค๋ช…ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด JSDoc์˜ @param ๊ตฌ๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
๊ฐ’์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ์„ค๋ช…ํ•˜๋Š” ์ฃผ์„๋„ ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ์ฃผ์„๋„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

// nums๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
function sort(nums: number[]) { /* ... */ }

๊ทธ ๋Œ€์‹ , readonly๋กœ ์„ ์–ธํ•˜์—ฌ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๊ทœ์น™์„ ๊ฐ•์ œํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

function sort(nums: readonly number[]) { /* ... */ }

์ฃผ์„์— ์ ์šฉํ•œ ๊ทœ์น™์€ ๋ณ€์ˆ˜๋ช…์—๋„ ๊ทธ๋Œ€๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ณ€์ˆ˜๋ช…์— ํƒ€์ž… ์ •๋ณด๋ฅผ ๋„ฃ์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ณ€์ˆ˜๋ช…์„ ageNum์œผ๋กœ ํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค๋Š” age๋กœ ํ•˜๊ณ , ๊ทธ ํƒ€์ž…์ด number์ž„์„ ๋ช…์‹œํ•˜๋Š” ๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค.
๊ทธ๋Ÿฌ๋‚˜ ๋‹จ์œ„๊ฐ€ ์žˆ๋Š” ์ˆซ์ž๋“ค์€ ์˜ˆ์™ธ์ž…๋‹ˆ๋‹ค. ๋‹จ์œ„๊ฐ€ ๋ฌด์—‡์ธ์ง€ ํ™•์‹คํ•˜์ง€ ์•Š๋‹ค๋ฉด ๋ณ€์ˆ˜๋ช… ๋˜๋Š” ์†์„ฑ ์ด๋ฆ„์— ๋‹จ์œ„๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด timeMs๋Š” time๋ณด๋‹ค ํ›จ์”ฌ ๋ช…ํ™•ํ•˜๊ณ  temperatureC๋Š” temperature๋ณด๋‹ค ํ›จ์”ฌ ๋ช…ํ™•ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฅ• ์•„์ดํ…œ 31. ํƒ€์ž… ์ฃผ๋ณ€์— null๊ฐ’ ๋ฐฐ์น˜ํ•˜๊ธฐโ€‹

๊ฐ’์ด ์ „๋ถ€ null์ด๊ฑฐ๋‚˜ ์ „๋ถ€ null์ด ์•„๋‹Œ ๊ฒฝ์šฐ๋กœ ๋ถ„๋ช…ํžˆ ๊ตฌ๋ถ„๋œ๋‹ค๋ฉด, ๊ฐ’์ด ์„ž์—ฌ ์žˆ์„ ๋•Œ๋ณด๋‹ค ๋‹ค๋ฃจ๊ธฐ ์‰ฝ์Šต๋‹ˆ๋‹ค. ํƒ€์ž…์— null์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋ฅผ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ˆซ์ž๋“ค์˜ ์ตœ์†Ÿ๊ฐ’๊ณผ ์ตœ๋Œ“๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋Š” extentํ•จ์ˆ˜๋ฅผ ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

function extent(nums: number[]) {
let min, max;
for (const num of nums) {
if (!min) {
min = num;
max = num;
} else {
min = Math.min(min, num);
max = Math.max(max, num);
}
}
return [min, max];
}

์ด ์ฝ”๋“œ๋Š” ํƒ€์ž… ์ฒด์ปค๋ฅผ ํ†ต๊ณผํ•˜๊ณ (strictNullChecks ์—†์ด), ๋ฐ˜ํ™˜ ํƒ€์ž…์€ number[]๋กœ ์ถ”๋ก ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๊ธฐ์—๋Š” ๋ฒ„๊ทธ์™€ ํ•จ๊ป˜ ์„ค๊ณ„์  ๊ฒฐํ•จ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์ตœ์†Ÿ๊ฐ’์ด๋‚˜ ์ตœ๋Œ“๊ฐ’์ด 0์ธ ๊ฒฝ์šฐ, ๊ฐ’์ด ๋ง์”Œ์›Œ์ ธ ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, extent([0, 1, 2])์˜ ๊ฒฐ๊ณผ๋Š” [0, 2]๊ฐ€ ์•„๋‹ˆ๋ผ [1, 2]๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.
  • nums ๋ฐฐ์—ด์ด ๋น„์–ด ์žˆ๋‹ค๋ฉด ํ•จ์ˆ˜๋Š” [undefined, undefined]๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

strictNullChecks ์„ค์ •์„ ์ผœ๋ฉด ์•ž์˜ ๋‘ ๊ฐ€์ง€ ๋ฌธ์ œ์ ์ด ๋“œ๋Ÿฌ๋‚ฉ๋‹ˆ๋‹ค.

function extent(nums: number[]) {
let min, max;
for (const num of nums) {
if (!min) {
min = num;
max = num;
} else {
min = Math.min(min, num);
max = Math.max(max, num);
// ~~~ 'number | undefined' ํ˜•์‹์˜ ์ธ์ˆ˜๋Š” 'number' ํ˜•์‹์˜ ๋งค๊ฐœ๋ณ€์ˆ˜์— ํ• ๋‹น๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
}
}
return [min, max];
}

extent์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์ด (number | undefined)[]๋กœ ์ถ”๋ก ๋˜์–ด์„œ ์„ค๊ณ„์  ๊ฒฐํ•จ์ด ๋ถ„๋ช…ํ•ด์กŒ์Šต๋‹ˆ๋‹ค. ์ด์ œ๋Š” extent๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ณณ๋งˆ๋‹ค ํƒ€์ž… ์˜ค๋ฅ˜์˜ ํ˜•ํƒœ๋กœ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

const [min, max] = extent([0, 1, 2]);
const span = max - min;
// ~~~ ~~~ ๊ฐ์ฒด๊ฐ€ 'undefined'์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋” ๋‚˜์€ ํ•ด๋ฒ•์„ ์ฐพ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. min๊ณผ max๋ฅผ ํ•œ ๊ฐ์ฒด ์•ˆ์— ๋„ฃ๊ณ  null์ด๊ฑฐ๋‚˜ null์ด ์•„๋‹ˆ๊ฒŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

function extent(nums: number[]) {
let result: [number number] | null = null;
for (const num of nums) {
if (!result) {
result = [num, num];
} else {
result = [Math.min(num, result[0]), Math.max(num, result[1])];
}
}
return result;
}

์ด์ œ๋Š” ๋ฐ˜ํ™˜ ํƒ€์ž…์ด [number, number] | null์ด ๋˜์–ด์„œ ์‚ฌ์šฉํ•˜๊ธฐ๊ฐ€ ๋” ์ˆ˜์›”ํ•ด์กŒ์Šต๋‹ˆ๋‹ค.
extent์˜ ๊ฒฐ๊ด๊ฐ’์œผ๋กœ ๋‹จ์ผ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์„ค๊ณ„๋ฅผ ๊ฐœ์„ ํ–ˆ๊ณ , ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ null ๊ฐ’ ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ์œผ๋ฉฐ ๋ฒ„๊ทธ๋„ ์ œ๊ฑฐํ–ˆ์Šต๋‹ˆ๋‹ค. if(!result) ์ฒดํฌ๋Š” ์ด์ œ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฅ• ์•„์ดํ…œ 32. ์œ ๋‹ˆ์˜จ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ณด๋‹ค๋Š” ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ๋‹ˆ์˜จ์„ ์‚ฌ์šฉํ•˜๊ธฐโ€‹

๋ฒกํ„ฐ๋ฅผ ๊ทธ๋ฆฌ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑ ์ค‘์ด๊ณ , ํŠน์ •ํ•œ ๊ธฐํ•˜ํ•™์  ํƒ€์ž…์„ ๊ฐ€์ง€๋Š” ๊ณ„์ธต์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

interface Layer {
layout: FillLayout | LineLayout | PointLayout;
paint: FillPaint | LinePaint | PointPaint;
}

layout์ด LineLayout ํƒ€์ž…์ด๋ฉด์„œ paint ์†์„ฑ์ด FillPaint ํƒ€์ž…์ธ ๊ฒƒ์€ ๋ง์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์กฐํ•ฉ์„ ํ—ˆ์šฉํ•œ๋‹ค๋ฉด ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‹ญ์ƒ์ด๊ณ  ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋‹ค๋ฃจ๊ธฐ๋„ ์–ด๋ ค์šธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์œผ๋กœ ๋ชจ๋ธ๋งํ•˜๋ ค๋ฉด ๊ฐ๊ฐ ํƒ€์ž…์˜ ๊ณ„์ธต์„ ๋ถ„๋ฆฌ๋œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋‘ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

interface FillLayer {
layout: FillLayout;
paint: FillPaint;
}

interface LineLayer {
layout: LineLayout;
paint: LinePaint;
}

interface PaintLayout {
layout: PointLayout;
paint: PointPaint;
}

type Layer = FillLayer | LineLayer | PointLayer;

์ด๋Ÿฐ ํ˜•ํƒœ๋กœ Layer๋ฅผ ์ •์˜ํ•˜๋ฉด layout๊ณผ paint ์†์„ฑ์ด ์ž˜๋ชป๋œ ์กฐํ•ฉ์œผ๋กœ ์„ž์ด๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ํŒจํ„ด์˜ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ์˜ˆ์‹œ๋Š” ํƒœ๊ทธ๋œ ์œ ๋‹ˆ์˜จ์ž…๋‹ˆ๋‹ค. Layer์˜ ๊ฒฝ์šฐ ์†์„ฑ ์ค‘์˜ ํ•˜๋‚˜๋Š” ๋ฌธ์ž์—ด ๋ฆฌํ„ฐ๋Ÿด ํƒ€์ž…์˜ ์œ ๋‹ˆ์˜จ์ด ๋ฉ๋‹ˆ๋‹ค.

interface Layer {
type: 'fill' | 'line' | 'point';
layout: FillLayout | LineLayout | PointLayout;
paint: FillPaint | LinePaint | PointPaint;
}

type: 'fill'๊ณผ ํ•จ๊ป˜ LineLayout๊ณผ PointPaint ํƒ€์ž…์ด ์“ฐ์ด๋Š” ๊ฒƒ์€ ๋ง์ด ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด Layer๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ๋‹ˆ์˜จ์œผ๋กœ ๋ณ€ํ™˜ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

interface FillLayer {
type: 'fill';
layout: FillLayout;
paint: FillPaint;
}

interface LineLayer {
type: 'line';
layout: LineLayout;
paint: LinePaint;
}

interface PaintLayout {
type: 'paint';
layout: PointLayout;
paint: PointPaint;
}

type Layer = FillLayer | LineLayer | PointLayer;

ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ํƒœ๊ทธ๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ Layer์˜ ํƒ€์ž…์˜ ๋ฒ”์œ„๋ฅผ ์ขํž ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

function drawLayer(layer: Layer) {
if (layer.type === 'fill') {
const { paint } = layer; // ํƒ€์ž…์ด FillPaint
const { layout } = layer; // ํƒ€์ž…์ด FillLayout
} else if (layer.type === 'line') {
const { paint } = layer; // ํƒ€์ž…์ด LinePaint
const { layout } = layer; // ํƒ€์ž…์ด LineLayout
} else {
const { paint } = layer; // ํƒ€์ž…์ด PointPaint
const { layout } = layer; // ํƒ€์ž…์ด PointLayout
}
}

๊ฐ ํƒ€์ž…์˜ ์†์„ฑ๋“ค ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์ œ๋Œ€๋กœ ๋ชจ๋ธ๋งํ•˜๋ฉด, ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ฝ”๋“œ์˜ ์ •ํ™•์„ฑ์„ ์ฒดํฌํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ ํƒ€์ž… ๋ถ„๊ธฐ ํ›„ layer๊ฐ€ ํฌํ•จ๋œ ๋™์ผํ•œ ์ฝ”๋“œ๊ฐ€ ๋ฐ˜๋ณต๋˜๋Š” ๊ฒƒ์ด ์–ด์ˆ˜์„ ํ•ด ๋ณด์ž…๋‹ˆ๋‹ค.

์–ด๋–ค ๋ฐ์ดํ„ฐ ํƒ€์ž…์„ ํƒœ๊ทธ๋œ ์œ ๋‹ˆ์˜จ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด, ๋ณดํ†ต์€ ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๋˜๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์„ ํƒ์  ํ•„๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ’์ด ์žˆ๊ฑฐ๋‚˜ ๋™์‹œ์— undefined์ธ ๊ฒฝ์šฐ๋„ ํƒœ๊ทธ๋œ ์œ ๋‹ˆ์˜จ ํŒจํ„ด์ด ์ž˜ ๋งž์Šต๋‹ˆ๋‹ค.

interface Person {
name: string;
// ๋‹ค์Œ์€ ๋‘˜ ๋‹ค ๋™์‹œ์— ์žˆ๊ฑฐ๋‚˜ ๋™์‹œ์— ์—†์Šต๋‹ˆ๋‹ค.
placeOfBirth?: string;
dateOfBirth?: Date;
}

ํƒ€์ž… ์ •๋ณด๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ์ฃผ์„์€ ๋ฌธ์ œ๊ฐ€ ๋  ์†Œ์ง€๊ฐ€ ๋งค์šฐ ๋†’์Šต๋‹ˆ๋‹ค. ๋‘ ๊ฐœ์˜ ์†์„ฑ์„ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๋ชจ์œผ๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ์„ค๊ณ„์ž…๋‹ˆ๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ null ๊ฐ’์„ ๊ฒฝ๊ณ„๋กœ ๋‘๋Š” ๋ฐฉ๋ฒ•๊ณผ ๋น„์Šทํ•ฉ๋‹ˆ๋‹ค.

interface Person {
name: string;
birth?: {
place: string;
date: Date;
}
}

Person ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜๋Š” birth ํ•˜๋‚˜๋งŒ ์ฒดํฌํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

ํƒ€์ž…์˜ ๊ตฌ์กฐ๋ฅผ ์† ๋Œˆ ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์ด๋ฉด, ์•ž์„œ ๋‹ค๋ฃฌ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ๋‹ˆ์˜จ์„ ์‚ฌ์šฉํ•ด์„œ ์†์„ฑ ์‚ฌ์ด์˜ ๊ด€๊ณ„๋ฅผ ๋ชจ๋ธ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface Name {
name: string;
}

interface PersonWithBirth extends Name {
placeOfBirth: string;
dateOfBirth: Date;
}

type Person = Name | PersonWithBirth;

์ด์ œ ์ค‘์ฒฉ๋œ ๊ฐ์ฒด์—์„œ๋„ ๋™์ผํ•œ ํšจ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function eulogize(p: Person) {
if ('placeOfBirth' in p) {
const { dateOfBirth } = p; // ์ •์ƒ, ํƒ€์ž…์ด Date
}
}

๐Ÿฅ• ์•„์ดํ…œ 33. string ํƒ€์ž…๋ณด๋‹ค ๋” ๊ตฌ์ฒด์ ์ธ ํƒ€์ž… ์‚ฌ์šฉํ•˜๊ธฐโ€‹

string ํƒ€์ž…์œผ๋กœ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋ ค ํ•œ๋‹ค๋ฉด, ํ˜น์‹œ ๊ทธ๋ณด๋‹ค ๋” ์ข์€ ํƒ€์ž…์ด ์ ์ ˆํ•˜์ง€๋Š” ์•Š์„์ง€ ๊ฒ€ํ† ํ•ด ๋ณด์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
์Œ์•… ์ปฌ๋ ‰์…˜์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์•จ๋ฒ”์˜ ํƒ€์ž…์„ ์ •์˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

interface Album {
artist: string;
title: string;
releaseDate: string; // YYYY-MM-DD
recordingType: string; // ์˜ˆ๋ฅผ ๋“ค์–ด, "live" ๋˜๋Š” "studio"
}

string ํƒ€์ž…์ด ๋‚จ๋ฐœ๋œ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์ฃผ์„์— ํƒ€์ž…์„ ์ •๋ณด๋ฅผ ์ ์–ด ๋‘” ๊ฑธ ๋ณด๋ฉด ํ˜„์žฌ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ž˜๋ชป๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. string ํƒ€์ž…์˜ ๋ฒ”์œ„๊ฐ€ ๋„“๊ธฐ ๋•Œ๋ฌธ์— ์ œ๋Œ€๋กœ ๋œ Album ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋”๋ผ๋„ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ˆœ์„œ๊ฐ€ ์ž˜๋ชป๋œ ๊ฒƒ์ด ์˜ค๋ฅ˜๋กœ ๋“œ๋Ÿฌ๋‚˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

function recordRelease(title: string, date: string) { /* ... */ }
recordRelease(kindOfBlue.releaseDate, kindOfBlue.title); // ์˜ค๋ฅ˜์—ฌ์•ผ ํ•˜์ง€๋งŒ ์ •์ƒ

releaseDate ํ•„๋“œ๋Š” Date ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋‚ ์งœ ํ˜•์‹์œผ๋กœ๋งŒ ์ œํ•œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. recordingType ํ•„๋“œ๋Š” "live"์™€ "studio", ๋‹จ ๋‘ ๊ฐœ์˜ ๊ฐ’์œผ๋กœ ์œ ๋‹ˆ์˜จ ํƒ€์ž…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.(enum์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ์ถ”์ฒœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์•„์ดํ…œ 53 ์ฐธ๊ณ )

type RecordingType = 'studio' | 'live';

interface Album {
artist: string;
title: string;
releaseDate: Date;
recordingType: RecordingType;
}

์ด๋Ÿฌํ•œ ๋ฐฉ์‹์—๋Š” ์„ธ ๊ฐ€์ง€ ์žฅ์ ์ด ๋” ์žˆ์Šต๋‹ˆ๋‹ค.
์ฒซ ๋ฒˆ์งธ, ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜ํ•จ์œผ๋กœ์จ ๋‹ค๋ฅธ ๊ณณ์œผ๋กœ ๊ฐ’์ด ์ „๋‹ฌ๋˜์–ด๋„ ํƒ€์ž… ์ •๋ณด๊ฐ€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
๋‘ ๋ฒˆ์งธ, ํƒ€์ž…์„ ๋ช…์‹œ์ ์œผ๋กœ ์ •์˜ํ•˜๊ณ  ํ•ด๋‹น ํƒ€์ž…์˜ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•˜๋Š” ์ฃผ์„์„ ๋ถ™์—ฌ ๋„ฃ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.(์•„์ดํ…œ 48)

/** ์ด ๋…น์Œ์€ ์–ด๋–ค ํ™˜๊ฒฝ์—์„œ ์ด๋ฃจ์–ด์กŒ๋Š”์ง€? */
type RecordingType = 'live' | 'studio';

ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ณณ์—์„œ RecordingType์˜ ์„ค๋ช…์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์„ธ ๋ฒˆ์งธ, keyof์—ฐ์‚ฐ์ž๋กœ ๋”์šฑ ์„ธ๋ฐ€ํ•˜๊ฒŒ ๊ฐ์ฒด์˜ ์†์„ฑ ์ฒดํฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง‘๋‹ˆ๋‹ค.

type K = keyof Album;
// ํƒ€์ž…์ด "artist" | "title" | "releaseDate" | "recordingType"

๊ทธ๋Ÿฌ๋ฏ€๋กœ string์„ keyof T๋กœ ๋ฐ”๊พธ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

function pluck<T>(records: T[], key: keyof T) {
return records.map(r => r[key]);
}

์ด ์ฝ”๋“œ๋Š” ํƒ€์ž… ์ฒด์ปค๋ฅผ ํ†ต๊ณผํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๋ฐ˜ํ™˜ ํƒ€์ž…์„ ์ถ”๋ก ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค. pluck ํ•จ์ˆ˜์— ๋งˆ์šฐ์Šค๋ฅผ ์˜ฌ๋ ค ๋ณด๋ฉด, ์ถ”๋ก ๋œ ํƒ€์ž…์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ key์˜ ๊ฐ’์œผ๋กœ ํ•˜๋‚˜์˜ ๋ฌธ์ž์—ด์„ ๋„ฃ๊ฒŒ ๋˜๋ฉด, ๊ทธ ๋ฒ”์œ„๊ฐ€ ๋„ˆ๋ฌด ๋„“์–ด์„œ ์ ์ ˆํ•œ ํƒ€์ž…์ด๋ผ๊ณ  ๋ณด๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

const releaseDates = pluck(albums, 'releaseDate'); // ํƒ€์ž…์ด (string | Date)[]

releaseDates์˜ ํƒ€์ž…์€ (string | Date)[]๊ฐ€ ์•„๋‹ˆ๋ผ Date[]์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. keyof T๋Š” string์— ๋น„ํ•˜๋ฉด ํ›จ์”ฌ ๋ฒ”์œ„๊ฐ€ ์ข๊ธฐ๋Š” ํ•˜์ง€๋งŒ ๊ทธ๋ž˜๋„ ์—ฌ์ „ํžˆ ๋„“์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฒ”์œ„๋ฅผ ๋” ์ขํžˆ๊ธฐ ์œ„ํ•ด์„œ, keyof T์˜ ๋ถ€๋ถ„ ์ง‘ํ•ฉ์œผ๋กœ ๋‘ ๋ฒˆ์งธ ์ œ๋„ˆ๋ฆญ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋„์ž…ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

function pluck<T, K extends keyof T>(records: T[], key: K): T[K][] {
return records.map(r => r[key]);
}

์ด์ œ ํƒ€์ž… ์‹œ๊ทธ๋‹ˆ์ฒ˜๊ฐ€ ์™„๋ฒฝํ•ด์กŒ์Šต๋‹ˆ๋‹ค.
๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์ด ์ •๋ฐ€ํ•ด์ง„ ๋•๋ถ„์— ์–ธ์–ด ์„œ๋น„์Šค๋Š” Album์˜ ํ‚ค์— ์ž๋™ ์™„์„ฑ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด ์ค๋‹ˆ๋‹ค.
string์€ any์™€ ๋น„์Šทํ•œ ๋ฌธ์ œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ๋ฌดํšจํ•œ ๊ฐ’์„ ํ—ˆ์šฉํ•˜๊ณ  ํƒ€์ž… ๊ฐ„์˜ ๊ด€๊ณ„๋„ ๊ฐ์ถ”์–ด ๋ฒ„๋ฆฝ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ์ ์€ ํƒ€์ž… ์ฒด์ปค๋ฅผ ๋ฐฉํ•ดํ•˜๊ณ  ์‹ค์ œ ๋ฒ„๊ทธ๋ฅผ ์ฐพ์ง€ ๋ชปํ•˜๊ฒŒ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๋ณด๋‹ค ์ •ํ™•ํ•œ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๋ฉด ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๋„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿฅ• ์•„์ดํ…œ 34. ๋ถ€์ •ํ™•ํ•œ ํƒ€์ž…๋ณด๋‹ค๋Š” ๋ฏธ์™„์„ฑ ํƒ€์ž…์„ ์‚ฌ์šฉํ•˜๊ธฐโ€‹

interface Point {
type: 'Point';
coordinates: number[];
}
interface LineString {
type: 'LineString';
coordinates: number[][];
}
interface Polygon {
type: 'Polygon';
coordinates: number[][][];
}
type Geometry = Point | LineString | Polygon; // ๋‹ค๋ฅธ ๊ฒƒ๋“ค๋„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํฐ ๋ฌธ์ œ๋Š” ์—†์ง€๋งŒ ์ขŒํ‘œ์— ์“ฐ์ด๋Š” number[]๊ฐ€ ์•ฝ๊ฐ„ ์ถ”์ƒ์ ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ number[]๋Š” ๊ฒฝ๋„์™€ ์œ„๋„๋ฅผ ๋‚˜ํƒ€๋‚ด๋ฏ€๋กœ ํŠœํ”Œ ํƒ€์ž…์œผ๋กœ ์„ ์–ธํ•˜๋Š” ๊ฒŒ ๋‚ซ์Šต๋‹ˆ๋‹ค.

type GeoPosition = [number, number];
interface Point {
type: 'Point';
coordinates: GeoPosition;
}
// ...

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

์ด๋ ‡๊ฒŒ ๋ถ€์ •ํ™•ํ•จ์„ ๋ฐ”๋กœ์žก๋Š” ๋ฐฉ๋ฒ•์„ ์“ฐ๋Š” ๋Œ€์‹ , ํ…Œ์ŠคํŠธ ์„ธํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ๋†“์นœ ๋ถ€๋ถ„์ด ์—†๋Š”์ง€ ํ™•์ธํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์œผ๋กœ ๋ณต์žกํ•œ ์ฝ”๋“œ๋Š” ๋” ๋งŽ์€ ํ…Œ์ŠคํŠธ๊ฐ€ ํ•„์š”ํ•˜๊ณ  ํƒ€์ž…์˜ ๊ด€์ ์—์„œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

๐Ÿฅ• ์•„์ดํ…œ 35. ๋ฐ์ดํ„ฐ๊ฐ€ ์•„๋‹Œ, API์™€ ๋ช…์„ธ๋ฅผ ๋ณด๊ณ  ํƒ€์ž… ๋งŒ๋“ค๊ธฐโ€‹

ํŒŒ์ผ ํ˜•์‹, API, ๋ช…์„ธ ๋“ฑ ์šฐ๋ฆฌ๊ฐ€ ๋‹ค๋ฃจ๋Š” ํƒ€์ž… ์ค‘ ์ตœ์†Œํ•œ ๋ช‡ ๊ฐœ๋Š” ํ”„๋กœ์ ํŠธ ์™ธ๋ถ€์—์„œ ๋น„๋กฏ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ๋Š” ํƒ€์ž…์„ ์ง์ ‘ ์ž‘์„ฑํ•˜์ง€ ์•Š๊ณ  ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ช…์„ธ๋ฅผ ์ฐธ๊ณ ํ•ด ํƒ€์ž…์„ ์ƒ์„ฑํ•˜๋ฉด ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์‹ค์ˆ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ค๋‹ˆ๋‹ค.
๋ช…์„ธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํƒ€์ž…์„ ์ž‘์„ฑํ•œ๋‹ค๋ฉด ํ˜„์žฌ๊นŒ์ง€ ๊ฒฝํ—˜ํ•œ ๋ฐ์ดํ„ฐ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ฐ’์— ๋Œ€ํ•ด์„œ ์ž‘๋™ํ•œ๋‹ค๋Š” ํ™•์‹ ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

API ํ˜ธ์ถœ์—๋„ ๋น„์Šทํ•œ ๊ณ ๋ ค ์‚ฌํ•ญ๋“ค์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. API์˜ ๋ช…์„ธ๋กœ๋ถ€ํ„ฐ ํƒ€์ž…์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํŠนํžˆ GraphQL์ฒ˜๋Ÿผ ์ž์ฒด์ ์œผ๋กœ ํƒ€์ž…์ด ์ •์˜๋œ API์—์„œ ์ž˜ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ๋ช…์„ธ ์ •๋ณด๋‚˜ ๊ณต์‹ ์Šคํ‚ค๋งˆ๊ฐ€ ์—†๋‹ค๋ฉด ๋ฐ์ดํ„ฐ๋กœ๋ถ€ํ„ฐ ํƒ€์ž…์„ ์ƒ์„ฑํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด quicktype ๊ฐ™์€ ๋„๊ตฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ƒ์„ฑ๋œ ํƒ€์ž…์ด ์‹ค์ œ ๋ฐ์ดํ„ฐ์™€ ์ผ์น˜ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์™ธ์ ์ธ ๊ฒฝ์šฐ๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ์ž๋™ ํƒ€์ž… ์ƒ์„ฑ์˜ ์ด์ ์„ ๋ˆ„๋ฆฌ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ธŒ๋ผ์šฐ์ € DOM API์— ๋Œ€ํ•œ ํƒ€์ž… ์„ ์–ธ์€ ๊ณต์‹ ์ธํ„ฐํŽ˜์ด์Šค๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.(์•„์ดํ…œ 55) ์ด๋ฅผ ํ†ตํ•ด ๋ณต์žกํ•œ ์‹œ์Šคํ…œ์„ ์ •ํ™•ํžˆ ๋ชจ๋ธ๋งํ•˜๊ณ  ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์˜ค๋ฅ˜๊ฐ€ ์ฝ”๋“œ์ƒ์˜ ์˜๋„์น˜ ์•Š์€ ์‹ค์ˆ˜๋ฅผ ์žก์„ ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿฅ• ์•„์ดํ…œ 36. ํ•ด๋‹น ๋ถ„์•ผ์˜ ์šฉ์–ด๋กœ ํƒ€์ž… ์ด๋ฆ„ ์ง“๊ธฐโ€‹

์ปดํ“จํ„ฐ ๊ณผํ•™์—์„œ ์–ด๋ ค์šด ์ผ์€ ๋‹จ ๋‘ ๊ฐ€์ง€๋ฟ์ด๋‹ค. ์บ์‹œ ๋ฌดํšจํ™”์™€ ์ด๋ฆ„ ์ง“๊ธฐ. - ํ•„ ์นผํŠผ

์ด๋ฆ„ ์ง“๊ธฐ ์—ญ์‹œ ํƒ€์ž… ์„ค๊ณ„์—์„œ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์ž…๋‹ˆ๋‹ค. ์—„์„ ๋œ ํƒ€์ž…, ์†์„ฑ, ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์€ ์˜๋„๋ฅผ ๋ช…ํ™•ํžˆ ํ•˜๊ณ  ์ฝ”๋“œ์™€ ํƒ€์ž…์˜ ์ถ”์ƒํ™” ์ˆ˜์ค€์„ ๋†’์—ฌ ์ค๋‹ˆ๋‹ค. ์ž˜๋ชป ์„ ํƒํ•œ ํƒ€์ž… ์ด๋ฆ„์€ ์ฝ”๋“œ์˜ ์˜๋„๋ฅผ ์™œ๊ณกํ•˜๊ณ  ์ž˜๋ชป๋œ ๊ฐœ๋…์„ ์‹ฌ์–ด ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

๋™๋ฌผ๋“ค์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ตฌ์ถ•ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

interface Animal {
name: string;
endangered: boolean;
habitat: string;
}

const leopard: Animal = {
name: 'Snow Leopard',
endangered: false,
habitat: 'tundra',
};

์ด ์ฝ”๋“œ์—๋Š” ๋„ค ๊ฐ€์ง€ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

  • name์€ ๋งค์šฐ ์ผ๋ฐ˜์ ์ธ ์šฉ์–ด์ž…๋‹ˆ๋‹ค. ๋™๋ฌผ์˜ ํ•™๋ช…์ธ์ง€ ์ผ๋ฐ˜์ ์ธ ๋ช…์นญ์ธ์ง€ ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
  • endangered ์†์„ฑ์ด ๋ฉธ์ข… ์œ„๊ธฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•ด boolean ํƒ€์ž…์„ ์‚ฌ์šฉํ•œ ๊ฒƒ์ด ์ด์ƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฏธ ๋ฉธ์ข…๋œ ๋™๋ฌผ์„ true๋กœ ํ•ด์•ผ ํ•˜๋Š”์ง€ ํŒ๋‹จํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. endangered ์†์„ฑ์˜ ์˜๋„๋ฅผ "๋ฉธ์ข… ์œ„๊ธฐ ๋˜๋Š” ๋ฉธ์ข…"์œผ๋กœ ์ƒ๊ฐํ•œ ๊ฒƒ์ผ์ง€๋„ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.
  • ์„œ์‹์ง€๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” habitat ์†์„ฑ์€ ๋„ˆ๋ฌด ๋ฒ”์œ„๊ฐ€ ๋„“์€ string ํƒ€์ž…์ผ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์„œ์‹์ง€๋ผ๋Š” ๋œป ์ž์ฒด๋„ ๋ถˆ๋ถ„๋ช…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ์†์„ฑ๋“ค๋ณด๋‹ค๋„ ํ›จ์”ฌ ๋ชจํ˜ธํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ์ฒด์˜ ๋ณ€์ˆ˜๋ช…์ด leopard์ด์ง€๋งŒ, name ์†์„ฑ์˜ ๊ฐ’์€ 'Snow Leopard' ์ž…๋‹ˆ๋‹ค. ๊ฐ์ฒด์˜ ์ด๋ฆ„๊ณผ ์†์„ฑ์˜ name์ด ๋‹ค๋ฅธ ์˜๋„๋กœ ์‚ฌ์šฉ๋œ ๊ฒƒ์ธ์ง€ ๋ถˆ๋ถ„๋ช…ํ•ฉ๋‹ˆ๋‹ค.

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

interface Animal {
commonName: string;
genus: string;
species: string;
status: ConservationStatus;
climates: KoppenClimate[];
}

const snowLeopard: Animal = {
commonName: 'Snow LeoPard',
genus: 'Panthera',
species: 'Uncia',
status: 'VU', // ์ทจ์•ฝ์ข…
climates: ['ET', 'EF', 'Dfd'], // ๊ณ ์‚ฐ๋Œ€ ๋˜๋Š” ์•„๊ณ ์‚ฐ๋Œ€
}

์ด ์ฝ”๋“œ๋Š” ๋‹ค์Œ ์„ธ ๊ฐ€์ง€๋ฅผ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • name์€ commonName, genus, species๋“ฑ ๋” ๊ตฌ์ฒด์ ์ธ ์šฉ์–ด๋กœ ๋Œ€์ฒดํ–ˆ์Šต๋‹ˆ๋‹ค.
  • endangered๋Š” ๋™๋ฌผ ๋ณดํ˜ธ ๋“ฑ๊ธ‰์— ๋Œ€ํ•œ IUCN์˜ ํ‘œ์ค€ ๋ถ„๋ฅ˜ ์ฒด๊ณ„์ธ ConservationStatus ํƒ€์ž…์˜ status๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • habitat์€ ๊ธฐํ›„๋ฅผ ๋œปํ•˜๋Š” climates๋กœ ๋ณ€๊ฒฝ๋˜์—ˆ์œผ๋ฉฐ, ์พจํŽœ ๊ธฐํ›„ ๋ถ„๋ฅ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ํ‘œํ˜„ํ•˜๊ณ ์ž ํ•˜๋Š” ๋ชจ๋“  ๋ถ„์•ผ์—๋Š” ์ฃผ์ œ๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•œ ์ „๋ฌธ ์šฉ์–ด๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์ฒด์ ์œผ๋กœ ์šฉ์–ด๋ฅผ ๋งŒ๋“ค์–ด ๋‚ด๋ ค๊ณ  ํ•˜์ง€ ๋ง๊ณ , ํ•ด๋‹น ๋ถ„์•ผ์— ์ด๋ฏธ ์กด์žฌํ•˜๋Š” ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์šฉ์–ด๋“ค์„ ์‚ฌ์šฉํ•˜๋ฉด ์‚ฌ์šฉ์ž์™€ ์†Œํ†ต์— ์œ ๋ฆฌํ•˜๋ฉฐ ํƒ€์ž…์˜ ๋ช…ํ™•์„ฑ์„ ์˜ฌ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
์ „๋ฌธ ๋ถ„์•ผ์˜ ์šฉ์–ด๋Š” ์ •ํ™•ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํŠน์ • ์šฉ์–ด๋ฅผ ๋‹ค๋ฅธ ์˜๋ฏธ๋กœ ์ž˜๋ชป ์“ฐ๊ฒŒ ๋˜๋ฉด, ์ง์ ‘ ๋งŒ๋“ค์–ด ๋‚ธ ์šฉ์–ด๋ณด๋‹ค ๋” ํ˜ผ๋ž€์„ ์ฃผ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

ํƒ€์ž…, ์†์„ฑ, ๋ณ€์ˆ˜์— ์ด๋ฆ„์„ ๋ถ™์ผ ๋•Œ ๋ช…์‹ฌํ•ด์•ผ ํ•  ์„ธ ๊ฐ€์ง€ ๊ทœ์น™์ด ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋™์ผํ•œ ์˜๋ฏธ๋ฅผ ๋‚˜ํƒ€๋‚ผ ๋•Œ๋Š” ๊ฐ™์€ ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ธ€์„ ์“ธ ๋•Œ๋‚˜ ๋ง์„ ํ•  ๋•Œ, ๊ฐ™์€ ๋‹จ์–ด๋ฅผ ๋ฐ˜๋ณตํ•ด์„œ ์‚ฌ์šฉํ•˜๋ฉด ์ง€๋ฃจํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋™์˜์–ด๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฝ”๋“œ์—์„œ๋Š” ์ข‹์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ •๋ง๋กœ ์˜๋ฏธ์ ์œผ๋กœ ๊ตฌ๋ถ„์ด ๋˜์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ๋‹ค๋ฅธ ์šฉ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • data, info, thing, item, object, entity ๊ฐ™์€ ๋ชจํ˜ธํ•˜๊ณ  ์˜๋ฏธ ์—†๋Š” ์ด๋ฆ„์€ ํ”ผํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ entity๋ผ๋Š” ์šฉ์–ด๊ฐ€ ํ•ด๋‹น ๋ถ„์•ผ์—์„œ ํŠน๋ณ„ํ•œ ์˜๋ฏธ๋ฅผ ๊ฐ€์ง„๋‹ค๋ฉด ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ฆ„์„ ์ง€์„ ๋•Œ๋Š” ํฌํ•จ๋œ ๋‚ด์šฉ์ด๋‚˜ ๊ณ„์‚ฐ ๋ฐฉ์‹์ด ์•„๋‹ˆ๋ผ ๋ฐ์ดํ„ฐ ์ž์ฒด๊ฐ€ ๋ฌด์—‡์ธ์ง€๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, INodeList๋ณด๋‹ค๋Š” Directory๊ฐ€ ๋” ์˜๋ฏธ ์žˆ๋Š” ์ด๋ฆ„์ž…๋‹ˆ๋‹ค. Directory๋Š” ๊ตฌํ˜„์˜ ์ธก๋ฉด์ด ์•„๋‹ˆ๋ผ ๊ฐœ๋…์ ์ธ ์ธก๋ฉด์—์„œ ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ์ƒ๊ฐํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค. ์ข‹์€ ์ด๋ฆ„์€ ์ถ”์ƒํ™”์˜ ์ˆ˜์ค€์„ ๋†’์ด๊ณ  ์˜๋„์น˜ ์•Š์€ ์ถฉ๋Œ์˜ ์œ„ํ—˜์„ฑ์„ ์ค„์—ฌ ์ค๋‹ˆ๋‹ค.

๐Ÿฅ• ์•„์ดํ…œ 37. ๊ณต์‹ ๋ช…์นญ์—๋Š” ์ƒํ‘œ๋ฅผ ๋ถ™์ด๊ธฐโ€‹

๊ตฌ์กฐ์  ํƒ€์ดํ•‘(์•„์ดํ…œ 4)์˜ ํŠน์„ฑ ๋•Œ๋ฌธ์— ๊ฐ€๋” ์ฝ”๋“œ๊ฐ€ ์ด์ƒํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

interface Vector2D {
x: number;
y: number;
}
function calculateNorm(p: Vector2D) {
return Math.sqrt(p.x * p.x + p.y * p.y);
}

calculateNorm({ x: 3, y: 4 }); // ์ •์ƒ, ๊ฒฐ๊ณผ๋Š” 5
const vec3D = { x: 3, y: 4, z: 1 };
calculateNorm(vec3D); // ์ •์ƒ! ๊ฒฐ๊ณผ๋Š” ๋™์ผํ•˜๊ฒŒ 5

์ด ์ฝ”๋“œ๋Š” ๊ตฌ์กฐ์  ํƒ€์ดํ•‘ ๊ด€์ ์—์„œ๋Š” ๋ฌธ์ œ๊ฐ€ ์—†๊ธฐ๋Š” ํ•˜์ง€๋งŒ, ์ˆ˜ํ•™์ ์œผ๋กœ ๋”ฐ์ง€๋ฉด 2์ฐจ์› ๋ฒกํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ์ด์น˜์— ๋งž์Šต๋‹ˆ๋‹ค.
calculateNorm ํ•จ์ˆ˜๊ฐ€ 3์ฐจ์› ๋ฒกํ„ฐ๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ฒŒ ํ•˜๋ ค๋ฉด ๊ณต์‹ ๋ช…์นญ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๊ณต์‹ ๋ช…์นญ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€, ํƒ€์ž…์ด ์•„๋‹ˆ๋ผ ๊ฐ’์˜ ๊ด€์ ์—์„œ Vector2D๋ผ๊ณ  ๋งํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ณต์‹ ๋ช…์นญ ๊ฐœ๋…์„ ํƒ€์ž…์Šคํฌ๋ฆฝํŠธ์—์„œ ํ‰๋‚ด ๋‚ด๋ ค๋ฉด "์ƒํ‘œ(brand)"๋ฅผ ๋ถ™์ด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

interface Vector2D {
_brand: '2d';
x: number;
y: number;
}
function vec2D(x: number, y: number): Vector2D {
return { x, y, _brand: '2d' };
}
function calculateNorm(p: Vector2D) {
return Math.sqrt(p.x * p.x + p.y * p.y);
}

calculateNorm(vec2D(3, 4)); // ์ •์ƒ, ๊ฒฐ๊ณผ๋Š” 5
const vec3D = { x: 3, y: 4, z: 1 };
calculateNorm(vec3D);
// ~~~~~ '_brand' ์†์„ฑ์ด ... ํ˜•์‹์— ์—†์Šต๋‹ˆ๋‹ค.

์ƒํ‘œ(_brand)๋ฅผ ์‚ฌ์šฉํ•ด์„œ calculateNorm ํ•จ์ˆ˜๊ฐ€ Vector2D ํƒ€์ž…๋งŒ ๋ฐ›๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ vec3D ๊ฐ’์— _brand: '2d'๋ผ๊ณ  ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ ๊ฐ™์€ ์•…์˜์ ์ธ ์‚ฌ์šฉ์„ ๋ง‰์„ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค๋งŒ ๋‹จ์ˆœํ•œ ์‹ค์ˆ˜๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ์—๋Š” ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค.
์ƒํ‘œ ๊ธฐ๊ฒ์€ ํƒ€์ž… ์‹œ์Šคํ…œ์—์„œ ๋™์ž‘ํ•˜์ง€๋งŒ ๋Ÿฐํƒ€์ž„์— ์ƒํ‘œ๋ฅผ ๊ฒ€์‚ฌํ•˜๋Š” ๊ฒƒ๊ณผ ๋™์ผํ•œ ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํƒ€์ž… ์‹œ์Šคํ…œ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์—†์•จ ์ˆ˜ ์žˆ๊ณ  ์ถ”๊ฐ€ ์†์„ฑ์„ ๋ถ™์ผ ์ˆ˜ ์—†๋Š” string์ด๋‚˜ number ๊ฐ™์€ ๋‚ด์žฅ ํƒ€์ž…๋„ ์ƒํ‘œํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.