Section3 Unit1 [์๋ฃ๊ตฌ์กฐ/์๊ณ ๋ฆฌ์ฆ] ์ฌ๊ท - ๊ณผ์ JSON.stringify, Tree UI
โญ๏ธ ๊ณผ์ 1. JSON.stringify
โ๏ธ ์ด๋ฒ ๊ณผ์ ๋ ์ฌ๊ท๋ฅผ ์ด์ฉํด ๋ฉ์๋ JSON.stringify
๋ฅผ ํจ์์ ํํ๋ก ์ง์ ๊ตฌํํ๋ ๊ณผ์ ์๋ค.
์ฌ๊ทํจ์๋ฅผ ๊ตฌํํ๋๊ฒ์ ์ด๋ ค์์ ๋๊ปด์ ๊ทธ๋ฐ์ง ์ด๋ฒ ๊ณผ์ ๋ ์ฝ์ง ์์๋ค.
ํ
์คํธ์ ๊ทธ๋ฅ ํตํํ๊ณ ์ถ๋ค๋ฉด const stringifyJSON = JSON.stringify;
์ด๋ ๊ฒ ๊ตฌํํ๋ฉด ๋๋ค. (๋๋ฌด๋ ์์ฝ๊ฒ ํด๊ฒฐ~)
ํ์ง๋ง ์ด ๊ณผ์ ๋ ์ฌ๊ท๋ฅผ ๊ณต๋ถํ๊ธฐ ์ํ ๊ฒ์ด๋, ํ๋์ฉ ๊ตฌํํด๋ณด์.
โจ ๊ตฌํ๊ณผ์ & ์ฝ๋
1. ์ฒ์์๋ ๊ฐ์ด ์กํ์ง ์์์ ํ์ฐธ์ ํค๋งค๊ณ , ์์์ ๋ชปํ๊ณ ์์๋ค... ๐ญ
2. ๋ฐฐ์ด๊ณผ ๊ฐ์ฒด๋ฅผ ์ ์ธํ๊ณ ๋, ๋จ์ํ "" ์ด๋ ๊ฒ ๋ฐ์ดํ๊ฐ ์ถ๊ฐ๋๋ ๊ฒ์ ์์์ฐจ๋ฆฌ๊ณ ๋ ์กฐ๊ฑด๋ฌธ์ผ๋ก number, string, boolean, null ์ผ ๊ฒฝ์ฐ ๋ถ๊ธฐ์ฒ๋ฆฌ๋ฅผ ํด์ฃผ์๋ค.
3. ํจ์์ undefined์ธ ๊ฒฝ์ฐ๋ stringify ๋์ง ์๋๋ค.
4. ๋ฐฐ์ด๊ณผ ๊ฐ์ฒด๋ฅผ ๋ณํ์ํค๋ ๊ฒ์ ๋๋๊ฑฐ๋ฆฌ๋ค ๋ ํผ๋ฐ์ค๋ฅผ ์ฐธ๊ณ ํด์ ์์ฑ์ ์๋ฃํ์๋ค. (๊ทธ๋๋ ์ ๊ทผ์ ๋น์ทํ๊ฒ ํ๊ณ ์์์ด...๐ฅฒ)
function stringifyJSON(obj) {
// Number ๋๋ Boolean์ผ ๊ฒฝ์ฐ
if (typeof obj === "number" || typeof obj === "boolean" || obj === null) {
return `${obj}`
}
// String์ผ ๊ฒฝ์ฐ
if (typeof obj === "string") {
return `"${obj}"`
}
// Array์ผ ๊ฒฝ์ฐ
if (Array.isArray(obj)) {
const result = [];
// Reference ์์๋ forEach๋ก ์์ฑ
for (let el of obj) {
result.push(stringifyJSON(el))
}
return `[${result}]`
}
// Object์ผ ๊ฒฝ์ฐ
if (typeof obj === "object") {
let result = "";
for (let key in obj) {
// console.log(el, obj[el])
let objKey = stringifyJSON(key);
let objValue = stringifyJSON(obj[key])
// ํจ์์ undefined๋ stringify๋์ง ์๋๋ค.
if (typeof objValue === "function" || objValue === undefined) {
continue;
} else {
result += `${objKey}:${objValue},`
}
}
return `{${result.slice(0, result.length - 1)}}`
}
};
โญ๏ธ ๊ณผ์ 2. Tree UI
โ๏ธ Tree UI ๊ณผ์ ๋ ํ๋ฉด์ ๊ตฌ์ฑํ ๋ ์ฌ๊ท๋ฅผ ์ฌ์ฉํ๋ ๊ณผ์ ์ด๋ค.
Tree UI๋ฅผ ๊ตฌํํ๋๋ฐ ์ฌ๊ท๋ฅผ ์ฌ์ฉํ ์๊ฐ์ ํด๋ณธ ์ ์ด ์์ง๋ง(์ฌ๊ทํจ์ ์ฌ์ฉ์ ์ ๋ชปํ๋..), Tree UI๋ฅผ ์ฌ๊ท๋ก ๊ตฌํํ ์ ์๋ค๋ ์ ๊ธฐํ๊ณ ์ฌ๋ฐ๋ ์ฌ์ค์ ์๊ฒ ๋ ๊ณผ์ ์๋ค. ๊ฐ์ธ์ ์ผ๋ก ์ ๊ณผ์ ๋ณด๋ค ์ฌ๋ฐ์๋ค.
์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๋ฌผ์ด ๋์ค๋ฉด ๋๊ณ , menu ๋ฐฐ์ด๋ ์๋์ ๊ฐ์ด ๊ตฌ์ฑ๋์ด ์๋ค.
const menu = [
{
type: 'group',
name: '์๋ฃ',
children: [
{
type: 'group',
name: '์ฝ๋ ๋ธ๋ฃจ',
children: [
{ type: 'item', name: '๋์ดํธ๋ก ์ฝ๋ ๋ธ๋ฃจ' },
{ type: 'item', name: '๋์ฒด ์ฝ๋ ๋ธ๋ฃจ' },
{ type: 'item', name: '์ ์ฃผ ๋น์๋ฆผ ์ฝ๋ ๋ธ๋ฃจ' },
{ type: 'item', name: '์ฝ๋ ๋ธ๋ฃจ' },
],
},
{
type: 'group',
name: 'ํ๋ผํธ์น๋
ธ',
children: [
{ type: 'item', name: '์ ํ ์ฟ ํค ํฌ๋ฆผ ํ๋ผํธ์น๋
ธ' },
{ type: 'item', name: '๋๋ธ ์์คํ๋ ์ ์นฉ ํ๋ผํธ์น๋
ธ' },
{ type: 'item', name: '๋ชจ์นด ํ๋ผํธ์น๋
ธ' },
{ type: 'item', name: 'ํผ์คํ์น์ค ํฌ๋ฆผ ํ๋ผํธ์น๋
ธ' },
],
},
{ ... } // ์์ ๊ฐ์ children์ด ์ฌ๋ฌ ๊ฐ ๋ ์๋ ๊ตฌ์กฐ
]
}
// ์์ ๊ฐ์ group์ด ์ฌ๋ฌ ๊ฐ ๋ ์๋ ๊ตฌ์กฐ
]
โจ ๊ตฌํ๊ณผ์ & ์ฝ๋
๊ตฌํ๊ณผ์ ์ ์ฃผ์์ผ๋ก ์ ๋ฆฌํด๋์๋ค.
์๋ ์ฝ๋๋ ๋ช ๋ นํ(imperitive) ๋ฐฉ์์ผ๋ก ๊ตฌํํ์๊ณ , ๋ ํผ๋ฐ์ค ์ฝ๋๋ฅผ ๋ณด๋ ์ ์ธํ ๋ฐฉ์์ผ๋ก ๊ตฌํํ ์ฝ๋๋ ์์๋ค! ์ ์ธํ ์ฝ๋๋ณด๋ค๋ ๋ช ๋ นํ์ผ๋ก ์์ฑ๋ ์ฝ๋๊ฐ ๋๋ ๋ณด๊ธฐ์ ๋ ํธํ๋ค.
function createTreeView(menu, currentNode) {
// menu์ ๊ฐ์ฒด ๊ฒ์ฌ
menu.map((el) => {
console.log(el)
/*
{type: 'group', name: '์๋ฃ', children: Array(5)}
{type: 'group', name: '์์', children: Array(6)}
{type: 'group', name: '๊ตฟ์ฆ', children: Array(3)}
{type: 'group', name: '์นด๋', children: Array(4)}
*/
/** result ํํ : ul#root > li > input, span, ul > li > input, span, ul > li ...
* ul#root ๋ ์ด๋ฏธ ์์ฑ๋์ด ์์
* li ์์ฑ
*/
const li = document.createElement("li");
/** ๊ฐ์ฒด ์์ children์ด ์์ ๊ฒฝ์ฐ input, span, ul ์์ฑ
* input type="checkbox"
* span textContent : name (ex.์๋ฃ)
*/
// ์๋ if ๋ฌธ์ด ๋ฐ๋ณต๋์ด์ผ ํจ. (children์ด ์์ ๋๊น์ง)
if (el.hasOwnProperty("children")) {
const input = document.createElement("input");
const span = document.createElement("span");
const ul = document.createElement("ul");
input.setAttribute("type", "checkbox");
// input.type = "checkbox"
span.textContent = el.name;
li.append(input, span, ul);
currentNode.append(li);
/* ์ต์ด ๋ ๋๋ง
<ul id="root">
<li>
<input type="checkbox" />
<span>${el.name}</span>
<ul></ul>
</li>
</ul>
*/
// ์ฌ๊ทํจ์ ํธ์ถ
// createTreeView(menu, currentNode)
// menu๋ ์ถ๊ฐํ ๊ฒ, currentNode๋ ์ถ๊ฐํ ๊ณณ
createTreeView(el.children, ul);
} else {
// console.log(`${el.name}์๋ ๋์ด์ children ์์`);
// ๊ฐ์ฒด ์์ children์ด ์๋ ๊ฒฝ์ฐ li๋ง append
currentNode.append(li);
li.textContent = el.name;
}
})
}
๐ ์ค๋์ ํ๊ณ
์ค๋ ์ ๊ท ์์ ์๊ฐ์๋ ์กฐ๊ธ ๋๋ํ๊ฒ ๊ณต๋ถํ๊ฒ ์๋๊น, ๋ผ๋ ์๊ฐ์ด ๋ค์ด์ ์ ์ง ์์ฌ์์ด ์ข ๋จ์๋ค. ์ฌ๊ทํจ์, ๋๋ฌด ์ด๋ ค์ ์ง๋ง ์ด์ ๊ณผ์ ๋ฅผ ๋ฏธ๋ฆฌ ์กฐ๊ธ ํ์ด๋ดค๋๋(๋ค ํผ๊ฑด ์๋๊ณ , ์ผ๋ถ๋ง ํ์์ง๋ง...) ์ค๋ ์์ ์๊ฐ์ ์ฌ์ ๊ฐ ์๊ฒผ๋ค. ์์ ์๊ฐ์ ์กฐ๊ธ ์ฌ์ ๋ก์ฐ๋ ค๊ณ , ๊ณผ์ ๋ฅผ ๋ฏธ๋ฆฌ ํ์ด๋ณธ๊ฑด ์๋๋ฐ ๐ฅฒ ์ข ๋ ์ดํด๋๋ฅผ ๋์ด๊ธฐ ์ํด ๋ฏธ๋ฆฌ ๊ณต๋ถ๋ฅผ ํ๋ ๊ฑด๋ฐ ์ด์ ๋ฏธ๋ฆฌ ํ ๊ณผ์ ๊ฐ ์ค๋์ ํ์ต ์ง์ค๋์ ๋์ ํ๋์ ์กฐ๊ธ ๋ฐฉํดํ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ๋ ๋ค์๋ค. ๊ณต๋ถ ๊ณํ๊ณผ ๋ฐฉํฅ์ ๋ค์ ์๊ฐํด๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๋ค.
์ ๊ท ์์ ํ์ ์คํฐ๋๋ญ ์ด๋ฒคํธ(?)์ ๋ง์ง๋ง ์คํฐ๋๋ก “๋๋ง์ ๋ณด์ผ๋ฌ ํ๋ ์ดํธ ๋ง๋ค๊ธฐ”๊ฐ ์งํ๋์๋๋ฐ, ๋ฆฌ์กํธ ํ๋ก์ ํธ๋ฅผ ์ฒ์ ๊ตฌ์ถํ๋ฉฐ ์์์ผ ํ ๋ด์ฉ๋ค์ ๋ํ ์์ ์ด ์งํ๋์ด์ ๊ฝค ์ ์ตํ๊ณ , ์ฌ๋ฏธ์์๋ค. npm์ผ๋ก ๋ฐฐํฌ๋ฅผ ํ๋ ๊ฒ๋ ๋๋ฌด ์ ๊ธฐํ๊ณ ์ ์ ํ๋ค. ๋ด๊ฐ ์์ฃผ ์ฌ์ฉํ๋ ์ผ์ข ์ ํ ํ๋ฆฟ์ ๋ฐฐํฌํด์, npm์ผ๋ก ๋ฐ์์ ์ฌ์ฉํ ์ ์๋ค๋?! ๋๋ฌด ์ฌ๋ฐ์ ๊ฒ ๊ฐ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ์์ ์ ๋ฃ๋ค๊ฐ ๊ถ๊ธํ ์ ์ด ๋ ์๊ฒผ๋๋ฐ, ๊ทธ๊ฒ๋ ์ข ๋ ์ฐพ์๋ณด๋ฉฐ ๊ณต๋ถํด์ผ ๊ฒ ๋ค๋ ์๊ฐ์ด ๋ค์๋ค. ๊ถ๊ธํ ๊ฒ ์๊ธด๋ค๋ ๊ฑด ์ฆ๊ฑฐ์ด ์ผ์ด๋ค.
์ต๊ทผ๋ค์ด ๊ฑฐ์ ์ฌ๋๋ ์์ด ๊ณต๋ถ๋ฅผ ํ๋ค๋ณด๋ ํผ๋ก๊ฐ ํ ์์ฌ๊ฐ์ด ๋ชธ์ผ๋ก ๋๊ปด์ง๋ค. ํ๋ณต์ ํด์์ด๋ , ๋ง์ ๋ฆฌํ๋ ์๋ ๋ญ๊ฐ ํ์ํ ๊ฒ ๊ฐ๋ค… ๊ทธ๋ฌ๋ ์ค๋์ ์ด๋์ ์ ์ ์ ์๋ฆฌ์ ๋ค์ด์ผ๊ฒ ๋ค.
๋ด์ผ์ ์ข ๋ ํจ์จ์ ์ด๊ณ , ์ด์ฌํ ๊ณต๋ถํด์ผ์ง.