๐ง 01. ํ์ ์คํฌ๋ฆฝํธ ๋ฉํ ๋ชจ๋ธ: JS์ TS์ ์คํ ๊ฒฝ๊ณ
๐ ๊ฐ์
๋ฐํ์๊ณผ ๋น๋ํ์ ๊ตฌ๋ถ, ๊ตฌ์กฐ์ ํ์ดํ ๋ฑ TS์ ํต์ฌ ๋์ ์๋ฆฌ ํ์ ํ๊ธฐ
๐ ์ด ๋ฌธ์๋ฅผ ์ฝ๊ธฐ ์ ์
โฑ๏ธ ์์ ์ฝ๊ธฐ ์๊ฐ: 10๋ถ(์ ์ฒด) / ํต์ฌ ํํธ๋ง: 5๋ถ
๐บ๏ธ ์ด ๋ฌธ์์ ํ๋ฆ
[๋ฐํ์๊ณผ ๋น๋ํ์์ ์ดํด] โ [๊ตฌ์กฐ์ ํ์ดํ(Duck Typing)์ ๋น๋ฐ] โ [ํ์
์คํฌ๋ฆฝํธ์ ๋ฐฐ์ (any)]
๐ฏ ์ด ๋ฌธ์๋ฅผ ๋ค ์ฝ์ผ๋ฉด ํ ์ ์๋ ๊ฒ
- ๋ธ๋ผ์ฐ์ ์์ ์คํ๋๋ ์ฝ๋์ TS ์ปดํ์ผ๋ฌ๊ฐ ๊ฒ์ฌํ๋ ์ฝ๋์ ์ฐจ์ด๋ฅผ ์ค๋ช ํ ์ ์๋ค.
- ๊ตฌ์กฐ์ ํ์ดํ์ด ์ ์ค๋ฌด์์ ์ ์ฉํ์ง (๊ทธ๋ฆฌ๊ณ ์ ๊ฐ๋ ์ํํ์ง) ์ดํดํ๋ค.
- ์์๋ค ์ปค๋ฎค๋ํฐ ์ฝ๋์์ ํํ ๋ฐ์ํ๋ ํ์ ๊ตฌ๋ฉ์ ์ด๋ป๊ฒ ๋ง๋์ง ์ฒด๋ํ๋ค.
๐บ๏ธ ์ด ๋ฌธ์์ ๋ฐฐ๊ฒฝ ์ธ๊ณ๊ด: '์์๋ค ์ปค๋ฎค๋ํฐ'
- ๐ฃ ์์ฒ ( ํ์
์คํฌ๋ฆฝํธ ์
๋ฌธ ๋จ๊ณ ): "๋ฆฌ๋ ๋! ๋ฐฉ๊ธ ๋ฐฐํฌํ ํ๋กํ ์์ ๊ธฐ๋ฅ์์
Cannot read properties of undefined (reading 'nickname')์๋ฌ ๋๋๋ฐ์?! ์ปดํ์ผํ ๋๋ ์๋ฌด ์๋ฌ ์์๋จ ๋ง์ด์์!" - ๐ฆ ์ํธ ( ๋ฆฌ๋ ): "์์ฒ ๋, ํ์ ์คํฌ๋ฆฝํธ๋ ์ ์ธ๋ ํ์ ์ ๊ธฐ์ค์ผ๋ก ๊ฒ์ฌํด์. ๊ทธ๋ฐ๋ฐ API ์๋ต๊ฐ์ ๋ฐํ์์ ๋์ฐฉํ๋, ์ ์ธ๋ง์ผ๋ก๋ ์ค์ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฅํ ์ ์์ฃ . ๋น๋ํ์๊ณผ ๋ฐํ์์ ์ฐจ์ด์ , ์ค๋ ํ์คํ๊ฒ ์ง๊ณ ๋์ด๊ฐ์๋ค."
๐ค ์ ์์์ผ ํ๋๊ฐ: '์๋ฌ'๋ ๋๊ตฌ์ ์๋ชป์ธ๊ฐ?
์์ฒ ์ด์ ์ต์ธํจ์ ๋น์ฐํฉ๋๋ค. VScode์๋ ๋นจ๊ฐ์ค ํ๋ ์์๊ณ , npm run build๋ ์๋ฒฝํ ํต๊ณผํ์ผ๋๊น์. ํ์ง๋ง ์ฌ์ฉ์์ ๋ธ๋ผ์ฐ์ ์์๋ ํ๋กํ ํ๋ฉด์ด ์์ธ๋ฅผ ๋ง๋ ๋น์ด ๋ณด์
๋๋ค. ๋๋์ฒด ๋ฌด์์ด ๋ฌธ์ ์์๊น์?
์ด ํ์์ ์ดํดํ๋ ค๋ฉด, ๋จผ์ ํ์ ์คํฌ๋ฆฝํธ๋ ๋ธ๋ผ์ฐ์ ์์ ์คํ๋๋ ์ง์ง ์ฝ๋๊ฐ ์๋๋ผ๋ ์ฌ์ค์ ๋ผ์ ๋ฆฌ๊ฒ ๋๊ปด์ผ ํฉ๋๋ค. ํ์ ์คํฌ๋ฆฝํธ๋ ๋จ์ง ์ปดํ์ผ๋ฌ(๊ฒ๋ฌธ์)์ผ ๋ฟ, ์ค์ ๋ก ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ฌ๋ฆฌ๋ ๊ฑด 100% ์์ํ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋๋ค.
์ด **๋ฉํ ๋ชจ๋ธ(Mental Model)**์ ์ ๋๋ก ์ ์ฐฉ์ํค์ง ๋ชปํ๋ฉด, 5๋
์ฐจ๊ฐ ๋์ด๋ any์ as๋ฅผ ๋จ๋ฐํ๋ฉฐ ํ์
์คํฌ๋ฆฝํธ์ ๋งค์ผ ์ธ์ฐ๊ฒ ๋ฉ๋๋ค.
๐๏ธ 1. ๋น๋ํ์ vs ๋ฐํ์ (ํํ์ธ๊ณ์ ์ดํด)
๊ฐ์ฅ ํํ๊ฒ ์ฐฉ๊ฐํ๋ ๋ถ๋ถ์ ๋๋ค. ํ์ ํ ์คํธ๋ ์ค๋ก์ง ๊ฐ๋ฐ ํ๊ฒฝ(๋น๋ ํ์) ์๋ง ์กด์ฌํฉ๋๋ค.
๐ฃ ์์ฒ ์ด์ ์คํด ์ฝ๋
// ๐ฃ ์์ฒ : "์ ์ ์ ๋ณด๋ ๋ฌด์กฐ๊ฑด User ํ์
์ด๋๊น ์์ ํ๊ฒ ์ง!"
type User = {
id: number;
nickname: string;
};
// ๋ฐฑ์๋(์์)๊ฐ ๋ณด๋ด์ค ๋ฐ์ดํฐ๋ฅผ ๋ณ์์ ํ ๋น
async function fetchUser() {
const response = await fetch('/api/user/1');
const data: User = await response.json(); // ๋ฐํ์ ๊ฒ์ฆ ์์ด User๋ผ๊ณ ์ฝ์ํ ์ํ
return data;
}๐ฆ ์ํธ์ ๋ฆฌ๋ทฐ ์ฝ๋ฉํธ
์ ์ฝ๋์์ const data: User๋ ๋ฐ์ดํฐ ๋ฐํ์ ๊ฒ์ฆ์ด ์๋๋๋ค. ์ด ๋ฌธ์ฅ์ ์ปดํ์ผ๋ฌ์๊ฒ ์ด๋ ๊ฒ ์์ญ์ด๋ ๊ฒ๊ณผ ๊ฐ์ต๋๋ค.
"TS, ์ด API ์๋ต์ User ๋ชจ์์ด๋ผ๊ณ ๋ด๊ฐ ๋ณด์ฅํ ๊ฒ. ์ฌ๊ธฐ์๋ ๋ ์์ฌํ์ง ์์๋ ๋ผ."
์ค์ ์๋ฐ์คํฌ๋ฆฝํธ๋ก ๋ณํ๋ ์ฝ๋๋ ์ถฉ๊ฒฉ์ ์ผ ๋งํผ ํ๋ฌดํฉ๋๋ค.
// ํธ๋์คํ์ผ ํ์ ์์ JS ์ฝ๋
async function fetchUser() {
const response = await fetch('/api/user/1');
const data = await response.json(); // ํ์
์ด ํ์ ๋ ์์ด ์ฌ๋ผ์ง!
return data;
}๋ง์ฝ ๋ฐฑ์๋์ ์์ ๋์ด ์ค์๋ก nickname ๋์ name์ ๋๊ฒจ์ฃผ๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
- ๋น๋ํ์ (TS): ์์ฒ ์ด๊ฐ
User๋ผ๊ณ ์ฅ๋ดํ์ผ๋ ํต๊ณผ. - ๋ฐํ์ (๋ธ๋ผ์ฐ์ ):
data.nickname์ ์ ๊ทผํ๋ ์๊ฐundefined๋๋ฌธ์ ํ๋ฉด ๋ก์ง์ด ์คํจํ ์ ์์.
๐ก TS์ ํ๊ณ: ํ์ ์คํฌ๋ฆฝํธ๋ ๋คํธ์ํฌ ํต์ ๊ฒฐ๊ณผ, ๋ก์ปฌ ์คํ ๋ฆฌ์ง ๋ฐ์ดํฐ, ์ฌ์ฉ์์ ์ ๋ ฅ๊ฐ ๊ฐ์ '๋ฐํ์'์ ๋์ ๋ฐ์ดํฐ๋ฅผ ์ค์ค๋ก ์ ์ ์์ต๋๋ค. ๊ฐ๋ฐ์๊ฐ ์ ํํ ๊ฐ์ด๋ํด์ฃผ๊ฑฐ๋,
Zod๊ฐ์ ๋ฐํ์ ๊ฒ์ฆ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์จ์ผ ํฉ๋๋ค.
๐ฆ 2. ๊ตฌ์กฐ์ ํ์ดํ (Duck Typing): ๋ ์ด๋ป๊ฒ ์๊ฒผ๋?
C#์ด๋ Java ์ถ์ ์ ๊ฐ๋ฐ์๋ค์ด TS๋ฅผ ์ฒ์ ์ ํ ๋ ๊ฐ์ฅ ํท๊ฐ๋ฆฌ๋ ๋ถ๋ถ์
๋๋ค.
ํ์
์คํฌ๋ฆฝํธ๋ ๊ตฌ์กฐ์ ํ์ดํ(Structural Typing) ์ ์ฑํํ๊ณ ์์ต๋๋ค. ์ฝ๊ฒ ๋งํด "์ค๋ฆฌ์ฒ๋ผ ์๊ฒผ๊ณ , ์ค๋ฆฌ์ฒ๋ผ ๊ฝฅ๊ฝฅ๊ฑฐ๋ฆฌ๋ฉด, ๋ ์ค๋ฆฌ๋ค" ๋ผ๋ ๋
ผ๋ฆฌ์
๋๋ค.
์์๋ค ์ปค๋ฎค๋ํฐ ๊ถํ ๋ถ์ฌ ์์
type BoardAdmin = {
internalId: number;
manageBoard: () => void;
};
type AppSuperUser = {
internalId: number;
manageBoard: () => void;
deleteApp: () => void;
};
// ๊ฒ์ํ ๊ด๋ฆฌ์๋ฅผ ํ์ฉํ๋ ํจ์
function grantBoardAccess(admin: BoardAdmin) {
admin.manageBoard();
}
// ๐ฃ ์์ฒ ์ ์ง๋ฌธ
const superMan: AppSuperUser = {
internalId: 100,
manageBoard: () => console.log("๊ฒ์ํ ๊ถํ ํ๋"),
deleteApp: () => console.log("์ฑ ์ญ์ ์คํ"),
};
// "BoardAdmin ํ์
์ด ์๋๋ฐ ์ด๊ฒ ๋ค์ด๊ฐ์?"
grantBoardAccess(superMan); // โ
ํต๊ณผ! (์๋ฌ ์์)grantBoardAccess ํจ์๋ BoardAdmin์ ์๊ตฌํฉ๋๋ค. ํ์ง๋ง ์ฐ๋ฆฌ๋ AppSuperUser๋ฅผ ๋ฃ์์ต๋๋ค.
๋ค๋ฅธ ์ธ์ด๋ผ๋ฉด ์์(extends) ๊ด๊ณ๊ฐ ๋ช
์๋์ง ์์ ์๋ฌ๋ฅผ ๋ฟ์๊ฒ ์ง๋ง, ํ์
์คํฌ๋ฆฝํธ๋ ํต๊ณผ์ํต๋๋ค.
์์ผ๊น์? superMan์ด ์ต์ํ BoardAdmin์ด ์๊ตฌํ๋ ๋ชจ๋ ์คํ(internalId, manageBoard) ์ ๊ฐ์ถ๊ณ ์๊ธฐ ๋๋ฌธ์
๋๋ค. ์ถ๊ฐ ์์ฑ(deleteApp)์ด ๋ ์์ด๋, ๋ณ์์ ๋ด๊ธด ๊ฐ์ ๋๊ธฐ๋ ์ํฉ์์๋ ํ์ํ ๊ตฌ์กฐ๋ฅผ ๋ง์กฑํ๋ฉด ํธํ๋ฉ๋๋ค.
์ด ์ ์ฐ์ฑ ๋๋ถ์ TS๋ ์๋ฐ์คํฌ๋ฆฝํธ์ ๋์ ์ด๊ณ ์์ ๋ถ๋ฐฉํ ๊ฐ์ฒด ํ ๋น ํจํด์ ๋ฌด๋ฆฌ ์์ด ํ์ด๋ผ ์ ์์ต๋๋ค.
๐ซ 3. any์ as: ์ ์ด๊ถ์ ํฌ๊ธฐํ๋ ํ์
์ํคํ
์ฒ ๊ด์ ์์, ํ์
์คํฌ๋ฆฝํธ์ ๊ฐ์ฅ ๊ฐ๋ ฅํ ๋ฌด๊ธฐ๋ any๋ ์๋๊ณ Interface๋ ์๋๋๋ค. ๋ฐ๋ก ํ์
์ถ๋ก (Type Inference) ์
๋๋ค.
โ ๋์ ์ (์์ฒ ์ด์ ํ์ ๊ฐ์ ์ฝ์ )
// ๐ฃ ์์ฒ : "๋ TS๊ฐ ๋ถ์ํ๋๊น ๋ชจ๋ ๋ณ์์ ํ์
์ ๋ฌ์์ค ๊ฑฐ์ผ!"
const message: string = "์๋
ํ์ธ์!";
const isLoading: boolean = true;
const userIds: number[] = [1, 2, 3];
const result = "๋น๋ฐ ๋ฌธ์" as any; // ๐ฃ ๊ธํ ๋ ์ฐ๋ ๋ง๋ฅ์ด์ โ ์ข์ ์ (์ํธ์ ์ฐ์ํ ์ถ๋ก )
// ๐ฆ ์ํธ: "TS๋ ์๊ฐ๋ณด๋ค ๋๋ํด์. ๋ช
๋ฐฑํ ๊ฑด ๋๋๊ณ , ํ์ํ ๊ณณ์๋ง ํ์ ์ฃผ์ฃ ."
const message = "์๋
ํ์ธ์!"; // TS๊ฐ ์ด๋ฏธ string์ผ๋ก ์
const isLoading = true; // boolean์ผ๋ก ์
const userIds = [1, 2, 3]; // number[]๋ก ์
// ๋ช
์์ ํ์
์ ์ธ์, ๋ฐํ๊ฐ, ๋ณต์กํ ๊ฐ์ฒด ์์ฑ ์์ ์ง์ค!
function createProfile(name: string, age: number): User {
return { id: 1, nickname: name };
}ํนํ as (Type Assertion)๋ "TS๊ฐ ์ถ๋ก ํ ๊ฒ๋ณด๋ค ๋ด๊ฐ ์ด ๊ฐ์ ๋ชจ์์ ๋ ์ ํํ ์๊ณ ์๋ค"๋ผ๊ณ ์ปดํ์ผ๋ฌ์๊ฒ ๊ฒ์ฌ ์ฑ
์์ ๋๊ธฐ๋ ์ ์ธ์
๋๋ค. ์ฌ๋งํ๋ฉด as ์์ด ํ์
์ด ์ ์ฐํ๊ฒ ํ๋ฌ๊ฐ๋๋ก(Flow) ์ฝ๋๋ฅผ ์๊ฒ ์ชผ๊ฐ๋ ๊ฒ์ด ์ง์ง ์ค๋ ฅ์
๋๋ค.
์ธ๋ถ ๋ฐ์ดํฐ๋ unknown์ผ๋ก ๋ฐ์ ์์ ๊ฒ์ฆ ๊ฒฝ๊ณ๋ฅผ ํต๊ณผ์ํค๋ฉด, ํ์
์ ์ธ๊ณผ ๋ฐํ์ ์ฌ์ค์ด ์ด๊ธ๋๋ ์ง์ ์ ์ค์ผ ์ ์์ต๋๋ค.
type User = {
id: number;
nickname: string;
};
function isUser(value: unknown): value is User {
if (typeof value !== "object" || value === null) return false;
const user = value as Record<string, unknown>;
return (
typeof user.id === "number" &&
typeof user.nickname === "string"
);
}
async function fetchUserSafely() {
const response = await fetch("/api/user/1");
const data: unknown = await response.json();
if (!isUser(data)) {
throw new Error("ํ๋กํ API ์๋ต ํ์์ด User์ ๋ค๋ฆ
๋๋ค.");
}
return data;
}์ด ์ฝ๋๋ "๋นจ๊ฐ ์ค์ ์์ ๊ธฐ"๋ณด๋ค "์ธ๋ถ์์ ๋ค์ด์จ ๊ฐ์ ์ธ์ ์ ๋ขฐํ ์ง"๋ฅผ ๋ช ์ํฉ๋๋ค. ์์ฒ ์ด๋ ์ฌ๊ธฐ์๋ถํฐ ํ์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ฌธ๋ฒ์ด ์๋๋ผ ๋ฐ์ดํฐ ๊ฒฝ๊ณ ์ค๊ณ ๋๊ตฌ๋ก ๋ณด๊ธฐ ์์ํฉ๋๋ค.
๐ ๋ง๋ฌด๋ฆฌ ํด์ฆ
Q1. ์ธ๋ถ API์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ฌ ๋ const data: User = await res.json()์ผ๋ก ํ์ดํํ๋ ๊ฒ์ ์ํ์ฑ์ ๋ฌด์์ธ๊ฐ?
โ ์ ๋ต: ๋น๋ํ์ ๊ฒ์ฌ๋ง ํต๊ณผํ ๋ฟ, ์ค์ ๋ฐํ์ ๋ฐ์ดํฐ ๊ตฌ์กฐ๋ฅผ ๋ณด์ฅํ์ง ๋ชปํจ.
๐ก ์์ธ ํด์ค:
res.json()์ ํ์ ์คํฌ๋ฆฝํธ ๊ด์ ์์ ๊ธฐ๋ณธ์ ์ผ๋กany๋ฅผ ๋ฐํํฉ๋๋ค.- ๋ณ์์
: User๋ฅผ ๋จ๋ค๊ณ ํด์ ๊ฐ์ฒด ๋ด์ฉ์ด ๋ณ๊ฒฝ๋๋ ๊ฒ์ด ์๋๋๋ค. ๋ฐํ์(๋ธ๋ผ์ฐ์ )์์ ์ค์ ๋กnicknameํ๋กํผํฐ๊ฐ ์์ผ๋ฉด ๋์ค์ ์ ๊ทผ ์ ์์ธ๊ฐ ๋ฐ์ํฉ๋๋ค.
Q2. ์๋ฐ์คํฌ๋ฆฝํธ๋ ๋ฐํ์ ์ธ์ด์ ๋๋ค. ํ์ ์คํฌ๋ฆฝํธ๋ ๋ฐํ์์ ์๋ฌ๋ฅผ ๋ง์์ฃผ๋ ๋ฐฉํจ ์ญํ ์ ์ํํ๋์?
โ ์ ๋ต: ์๋์. ํ์ ์คํฌ๋ฆฝํธ๋ ๋ธ๋ผ์ฐ์ (๋ฐํ์)์์ ์คํ๋์ง ์์ต๋๋ค.
๐ก ์์ธ ํด์ค:
- ํ์ ์คํฌ๋ฆฝํธ์ ๊ฒ์ฌ๋ ๊ฐ๋ฐ ํ๊ฒฝ(๋น๋ ํ์, VSCode ํธ์ง ์ค)๊น์ง๋ง ์ ํจํฉ๋๋ค.
- ์คํ๋๋ ์์ ์๋ ๋ชจ๋
type๊ณผinterface๊ป๋ฐ๊ธฐ ์ฝ๋๊ฐ ์ฆ๋ฐํ๊ณ ์์ํ ์๋ฐ์คํฌ๋ฆฝํธ๋ง ๋จ์ต๋๋ค. ์ด ํํ ์ธ๊ณ๋ฅผ ์ดํดํ๋ ๊ฒ์ด ๋ฉํ ๋ชจ๋ธ์ ์ฒซ ๋จ์ถ์ ๋๋ค.
Q3. [์์ฒ ์ด์ ํ
์คํธ ํ์: ์ค๋ฌด ๋๋ ๋ง] ์์ฒ ์ด๊ฐ ๋์์ธ ์์คํ
์ปดํฌ๋ํธ์ธ Button์ ๋ง๋ค๊ณ ์์ต๋๋ค. ๊ธฐ์กด HTML <button>์ ๋ชจ๋ ์์ฑ(onClick, disabled ๋ฑ)์ ๋ค ๋ฐ์์ค๋ฉด์ ์ปค์คํ
์์ฑ์ธ variant๋ฅผ ์ถ๊ฐํ๊ณ ์ถ์ด ํฉ๋๋ค. "์ด๊ฑฐ Props๋ฅผ ์ผ์ผ์ด ๋ค ์ ์ด์ค์ผ ํ๋์?"๋ผ๊ณ ๊ณ ๋ฏผํ ๋, ๊ตฌ์กฐ์ ํ์ดํ์ ์ดํดํ ์ํธ ๋ฆฌ๋๋ ์ด๋ค ํด๊ฒฐ์ฑ
(๊ฐ๋
)์ ์ ์ํ ๊น์?
โ
์ ๋ต: ๊ธฐ์กด ๋ฒํผ ์์ฑ ํ์
์ ํ์ฅํ๊ฑฐ๋ ๊ต์ฐจํด์ ์ฌ์ฌ์ฉํ๋ค. ์: React.ButtonHTMLAttributes<HTMLButtonElement>์ variant๋ฅผ ๋ํ๋ค.
๐ก ์์ธ ํด์ค:
- ๊ตฌ์กฐ์ ํ์ดํ ๋๋ถ์
ButtonProps๊ฐ HTML ๋ฒํผ์ด ์๊ตฌํ๋ ์์ฑ ๊ตฌ์กฐ๋ฅผ ํฌํจํ๋ฉด, ๋ณ๋์ ์์ ๊ณ์ธต ์์ด๋ ์์ ํ๊ฒ ํธํ๋ฉ๋๋ค. type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement> & { variant?: "primary" | "secondary" }์ฒ๋ผ ์์ฑํ๋ฉด ๊ธฐ์กด ์ด๋ฒคํธ, ์ ๊ทผ์ฑ ์์ฑ,disabled๊ฐ์ ํ์ค ์์ฑ์ ๋น ๋จ๋ฆด ์ํ์ด ์ค์ด๋ญ๋๋ค.- ํต์ฌ์ "ํ์ ์ ์ ๋ถ ์ง์ ์ฐ๊ธฐ"๊ฐ ์๋๋ผ, ์ด๋ฏธ ๊ฒ์ฆ๋ ํ์ ๋ฉ์ด๋ฆฌ์ ์ฐ๋ฆฌ ์๋น์ค์ ์๋ฏธ ์๋ ์์ฑ๋ง ์น๋ ๊ฒ์ ๋๋ค.
๐ฃ ์์ฒ ์ด์ ํด๊ทผ ์ผ๊ธฐ
์ค๋์ ๋นจ๊ฐ ์ค์ด ์๋ค๋ ์ฌ์ค๊ณผ ๋ฐํ์์ด ์์ ํ๋ค๋ ์ฌ์ค์ด ๋ค๋ฅด๋ค๋ ๊ฑธ ์ ๋๋ก ๋ฐฐ์ ๋ค. const data: User = await res.json()์ ๊ฒ์ฆ์ด ์๋๋ผ ๋ด๊ฐ TS์๊ฒ ๋ณด๋ธ ์ฝ์์ด์๋ค. ๊ทธ ์ฝ์์ด ํ๋ฆฌ๋ฉด ํผํด๋ ์ฌ์ฉ์ ๋ธ๋ผ์ฐ์ ์์ ์์ธ๋ก ๋๋ฌ๋๋ค.
์ํธ ๋์ด "ํ์
์ ์คํ๋์ง ์๋๋ค"๋ผ๊ณ ์ง์ด์ค ๋ค๋ก, any์ as๋ฅผ ์ฐ๋ ์์ด ์กฐ๊ธ ๋ฌด๊ฑฐ์์ก๋ค. ๋นจ๊ฐ ์ค์ ์ง์ฐ๋ ๊ฒ ๋ชฉํ๊ฐ ์๋๋ผ, ๋ฐ์ดํฐ๊ฐ ๋ค์ด์ค๋ ๊ฒฝ๊ณ์์ ๋ฌด์์ ๋ฏฟ๊ณ ๋ฌด์์ ํ์ธํ ์ง ์ ํ๋ ๊ฒ ๋ชฉํ์๋ค.
๐ก "ํ์ ์คํฌ๋ฆฝํธ๋ ๋ฐํ์ ๋ฐ์ดํฐ๋ฅผ ๋์ ๊ฒ์ฆํ์ง ์๋๋ค. ์ธ๋ถ์์ ๋ค์ด์ค๋ ๊ฐ์ ํ์ ์ ์ธ์ด ์๋๋ผ ๊ฒ์ฆ ๊ฒฝ๊ณ๋ก ๋ค๋ค์ผ ํ๋ค."
๋ด์ผ์ ํ๋กํ API ์๋ต์ ๋ค์ ๋ณด๋ฉด์ unknown์ผ๋ก ๋ฐ์ ๋ค ํ์ํ ํ๋๋ง ํ์ธํ๋ ์์ ์ ํธ๋ถํฐ ๋ง๋ค์ด๋ณผ ์๊ฐ์ด๋ค. ๊ตฌ์กฐ์ ํ์ดํ์ ํธํ์ง๋ง, ์ธ๋ถ ๋ฐ์ดํฐ์๋ ์ ๋ขฐ์ ์ถ์ฒ๋ฅผ ๋จ๊ฒจ์ผ ํ๋ค๋ ๊ฑธ ์ฝ๋ ๋ฆฌ๋ทฐ ์ฒดํฌ๋ฆฌ์คํธ์ ์ ์ด๋ฌ์ผ๊ฒ ๋ค.