๐Ÿ“… TIL #29

์žฌ๊ท€ํ•จ์ˆ˜๋กœ stringify-JSON ๋ฐ tree-UI ๊ตฌํ˜„


๐Ÿ‘‰ JSON ์ด๋ž€?


JSON์ด๋ž€, JSON(JavaScript Object Notation)์˜ ์•ฝ์ž๋กœ Javascript ๊ฐ์ฒด ๋ฌธ๋ฒ•์œผ๋กœ ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๋ฌธ์ž ๊ธฐ๋ฐ˜์˜ ํ‘œ์ค€ ํฌ๋งท์ด๋‹ค.

๊ทธ๋Ÿฌ๋ฉด ์™œ JSON์„ ์•Œ์•„์•ผ ํ• ๊นŒ?

์›น์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†ก์„ ํ•ด์•ผํ•  ๋•Œ ์ผ๋ฐ˜์ ์œผ๋กœ JSON์„ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. (์˜ˆ๋ฅผ๋“ค์–ด, ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ)

JSON์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ• ๊นŒ?

JSON์€ ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ ์กด์žฌํ•œ๋‹ค. Javascript ๊ฐ์ฒด ๋ฌธ๋ฒ•์„ ๋”ฐ๋ฅด๋Š” ๋ฌธ์ž์—ด์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ธฐ๋ณธ ๋ฐ์ดํ„ฐ ํƒ€์ž…์ธ ๋ฌธ์ž์—ด, ์ˆซ์ž, ๋ฐฐ์—ด, ๋ถˆ๋ฆฌ์–ธ ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๊ฐ์ฒด๋“ค๋„ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.

JSON ์‚ฌ์šฉ๋ฒ•์€?

๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋ฅผ ์‚ดํŽด๋ณด๋ฉด์„œ ์ดํ•ด๋ฅผ ํ•ด๋ณด์ž.

const message = {
  sender: "์ด์šฐ์„ฑ",
  receiver: "๋„ค์ด๋ฒ„",
  message: "์ €๋ฅผ ๋ฐ๋ ค๊ฐ€์„ธ์š”!",
  createdAt: "2021-02-15 21:08:10"
};

let transferableMessage = JSON.stringify(message);

console.log(transferableMessage);
// {"sender":"์ด์šฐ์„ฑ","receiver":"๋„ค์ด๋ฒ„","message":"์ €๋ฅผ ๋ฐ๋ ค๊ฐ€์„ธ์š”!","createdAt":"2021-02-15 21:08:10"}


์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉ๋ฒ•์€ ์ •๋ง ๊ฐ„๋‹จํ•˜๋‹ค. ๊ทธ๋ฆฌ๊ณ  stringifyํ•˜๋Š” ์ด ๊ณผ์ •์„ ์ง๋ ฌํ™”(serialize)ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

Other notes

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


๊ทธ๋ ‡๋‹ค๋ฉด ๋‹ค์‹œ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜์€?

์ด์ œ๋Š” ๋ฌธ์ž์—ด ๊ทธ ์ž์ฒด๋กœ ๋ˆ„๊ตฐ๊ฐ€์—๊ฒŒ ๊ฐ์ฒด ๋‚ด์šฉ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ˆ˜์‹ ์ž๋Š” ์ด ๋ฉ”์‹œ์ง€๋ฅผ ์–ด๋–ป๊ฒŒ ๋‹ค์‹œ ๊ฐ์ฒด๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„๊นŒ?

๊ทธ ์—ญํ• ์„ ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋กœ parseํ•˜๋Š” ์ด ๊ณผ์ •์„ ์—ญ์ง๋ ฌํ™”(deserialize)ํ•œ๋‹ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.์ด๋‹ค.

let packet = {sender: "์ด์šฐ์„ฑ", receiver: "๋„ค์ด๋ฒ„", message: "์ €๋ฅผ ๋ฐ๋ ค๊ฐ€์„ธ์š”!", createdAt: "2021-02-15 21:08:10"};

let obj = JSON.parse(packet);

console.log(obj);
/*  
{
  sender: "์ด์šฐ์„ฑ",
  receiver: "๋„ค์ด๋ฒ„",
  message: "์ €๋ฅผ ๋ฐ๋ ค๊ฐ€์„ธ์š”!",
  createdAt: "2021-02-15 21:08:10"
};
*/


parseํ•˜๋Š” ์ด ๊ณผ์ •์€ ์—ญ์ง๋ ฌํ™”(deserialize)ํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

serialize-deserialize-binary-tree

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



๐Ÿ‘‰ stringify-JSON ๊ตฌํ˜„

๊ทธ๋Ÿฌ๋ฉด ์ด์ œ ๋ณธ๊ฒฉ์ ์œผ๋กœ ์žฌ๊ท€๋ฅผ ์‚ฌ์šฉํ•ด์„œ JSON์„ ๊ตฌํ˜„ํ•ด๋ณด์ž! :punch: :punch: :punch:


๋‚˜๋Š” ๋จผ์ € ๋ฐฐ์—ด(Array)๊ณผ ๊ฐ์ฒด(Object) ๊ทธ๋ฆฌ๊ณ  ๋‚˜๋จธ์ง€ ํƒ€์ž…๋“ค, ์ด๋ ‡๊ฒŒ ํฌ๊ฒŒ ์„ธ๊ฐ€์ง€๋กœ ๋ถ„๋ฅ˜๋ฅผ ํ•ด์„œ ์ƒ๊ฐ์„ ํ–ˆ๋‹ค.

์ธ์ž๋ฅผ ๋ฐ›์•˜์„ ๋•Œ ๋จผ์ € number, null, boolean, string ํƒ€์ž…๋“ค์„ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ด์„œ ๋ฐ˜ํ™˜ํ•ด์ฃผ์—ˆ๋‹ค.


function stringifyJSON(obj) {
  //TODO: recursive base
  if (typeof obj === "number" || obj === null || typeof obj === "boolean") {
    return `${obj}`;
  } else if (typeof obj === "string") {
    return `"${obj}"`;       // ๋ฌธ์ž์—ด์€ ์Œ๋”ฐ์˜ดํ‘œ๋ฅผ ํ•œ ๋ฒˆ ๋” ๋ถ™์—ฌ์ค˜์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋”ฐ๋กœ ๋ถ„๋ฅ˜ํ–ˆ๋‹ค.
  }


๊ทธ ๋‹ค์Œ์€ ํƒ€์ž…์ด ๋ฐฐ์—ด(Array)์ด๊ณ  ๊ทธ ์•ˆ์—์„œ ๋นˆ ๋ฐฐ์—ด์ด๋ƒ, ์š”์†Œ๊ฐ€ ์žˆ๋ƒ๋กœ ๋‚˜๋ˆ„์–ด์ฃผ์—ˆ๋‹ค.

์š”์†Œ๊ฐ€ ์žˆ์„ ๊ฒฝ์šฐ๋Š” ๋ชจ๋“  ์š”์†Œ์— ์ ‘๊ทผ์„ ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ชจ๋“  ์š”์†Œ์— ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ์ ์šฉ์‹œ์ผœ์ฃผ์—ˆ๋‹ค. ๊ทธ ํ›„์— ๋ฌธ์ž์—ด๋กœ ๋œ ์š”์†Œ๋“ค์„ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์— push๋ฅผ ํ•ด์ฃผ์—ˆ๋‹ค.

์ด ๋ถ€๋ถ„์ด ์˜ค๋Š˜ ๋ฐฐ์šด ๋‚ด์šฉ์˜ ํ•ต์‹ฌ์ด๋ฉฐ, ๊ทธ๋ฆฌ๊ณ  ์ง€๊ธˆ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•˜๋Š” JSON ํ•จ์ˆ˜์˜ ํ•ต์‹ฌ์ด๋‹ค.


let resultArr = [];

if (Array.isArray(obj)) {
  if (obj.length === 0) {
    // ๋นˆ ๋ฐฐ์—ด์ธ์ง€ ํ™•์ธ
    return "[]";
  } else {
    for (let i = 0; i < obj.length; i++) {
      // ๋ชจ๋“  ์š”์†Œ์— ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. ์š”์†Œ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊พธ๊ธฐ ์œ„ํ•ด ์žฌ๊ท€ base๋กœ ํ–ฅํ•˜๊ฒŒ ํ•œ๋‹ค.
      let result = stringifyJSON(obj[i]);
      resultArr.push(result);
    }
    return `[${resultArr}]`; // ๋ฐฐ์—ด์ž์ฒด๋ฅผ ๋ฌธ์ž์—ด ํ˜•ํƒœ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  }
}


์ด์ œ ๊ฐ์ฒด(Object)์ผ ๋•Œ๋ฅผ ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค. ๊ฐ์ฒด๋„ ๋ฐฐ์—ด๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ, ๋จผ์ € ๋นˆ ๊ฐ์ฒด์ธ์ง€ ํ™•์ธ์„ ํ•ด์ฃผ์—ˆ๋‹ค.

๊ทธ ํ›„์—, ๊ฐ์ฒด์˜ value๊ฐ’์ด function ์ด๊ฑฐ๋‚˜ undefined์ธ ๊ฒฝ์šฐ delete๋ฅผ ํ•ด์ฃผ๊ณ  ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ–ˆ๋‹ค. (JSON ํ•จ์ˆ˜ ๊ตฌํ˜„ ๋ฌธ์ œ์ค‘์˜ ํ•˜๋‚˜ ์˜€์Œ)

๊ทธ๋ฆฌ๊ณ  ๊ฐ์ฒด์˜ ๋ชจ๋“  ํ‚ค์™€ ๊ฐ’์„ ๋ฐ˜๋ณต๋ฌธ์œผ๋กœ ํ™•์ธํ•ด์ฃผ๊ณ  ๊ฐ ํ‚ค์™€ ๊ฐ’์— ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ–ˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด.

  //TODO: Object
  else {
    let recursiveArr = [];
    // ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ณ  ๊ฐ’์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด ํ• ๋‹น

    if (Object.keys(obj).length === 0) {  // ๋นˆ ๊ฐ์ฒด ํ™•์ธ
      return "{}";
    } else {
      for (let key in obj) {
        // ๋ชจ๋“  ํ‚ค์™€ ๊ฐ’์— ์ ‘๊ทผ
        if (typeof obj[key] === "function" || obj[key] === undefined) {
          delete obj[key];
          stringifyJSON(obj);
          // ํ•„์š”์—†๋Š” ๋ถ€๋ถ„์„ ์ œ๊ฑฐํ•˜๊ณ  ๋‹ค์‹œ ์‹คํ–‰(์žฌ๊ท€)
        } else {
          // ๋ชจ๋“  ํ‚ค์™€ ๊ฐ’์„ ํ™•์ธํ•˜๊ณ  ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜
          let vals = stringifyJSON(obj[key]);
          let keys = stringifyJSON(key);
          let resultObj = keys + ":" + vals;
          recursiveArr.push(resultObj);
          // ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.
        }
      }
    }
    return `{${recursiveArr}}`;
    // ๊ฐ์ฒด ์ž์ฒด๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  }
}



stringify-JSON ๊ตฌํ˜„ ์ฝ”๋“œ

function stringifyJSON(obj) {
  //TODO: recursive base
  if (typeof obj === "number" || obj === null || typeof obj === "boolean") {
    return "" + obj;
  } else if (typeof obj === "string") {
    return `"${obj}"`;
  }

  //TODO: Array
  let resultArr = [];

  if (Array.isArray(obj)) {
    if (obj.length === 0) {
      return "[]";
    } else {
      for (let i = 0; i < obj.length; i++) {
        let result = stringifyJSON(obj[i]);
        resultArr.push(result);
      }
      return `[${resultArr}]`;
    }
  }

  //TODO: Object
  else {
    let recursiveArr = [];

    if (Object.keys(obj).length === 0) {
      return "{}";
    } else {
      for (let key in obj) {
        if (typeof obj[key] === "function" || obj[key] === undefined) {
          delete obj[key];
          stringifyJSON(obj);
        } else {
          let vals = stringifyJSON(obj[key]);
          let keys = stringifyJSON(key);
          let resultObj = keys + ":" + vals;
          recursiveArr.push(resultObj);
        }
      }
    }

    return `{${recursiveArr}}`;
  }
}

๐Ÿ‘‰ tree-UI ๊ตฌํ˜„

์˜ค๋Š˜์€ JSON๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ธฐ์—…์šฉ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ํ”ํžˆ ๋ณผ ์ˆ˜ ์žˆ๋Š” tree-UI(ํŠธ๋ฆฌ๊ตฌ์กฐ)์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€๋ฅผ ํ•ด๋ณด์•˜๋‹ค.

์™„์„ฑ๋œ ๊ตฌ์กฐ๋ฅผ ์‚ดํŽด๋ณด๋ฉด

tree-UI

๊ธฐ๋ณธ์ ์ธ menu๋Š” ๋‹ค ์ž‘์„ฑ์ด ๋˜์–ด์žˆ๊ณ , ๋‚˜๋Š” ํŠธ๋ฆฌ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด์ค„ ํ•จ์ˆ˜๋งŒ ๊ตฌํ˜„ํ•˜๋ฉด ๋˜๋Š” ๋ฌธ์ œ์˜€๋‹ค.

ul์š”์†Œ์•ˆ์— ๋ถ€๋ชจ ์—˜๋ฆฌ๋จผํŠธ๋Š” 4๊ฐ€์ง€ (์Œ๋ฃŒ, ์Œ์‹, ๊ตฟ์ฆˆ, ์นด๋“œ)li๊ฐ€ ์žˆ๊ณ , ๊ทธ ์•ˆ์— input ํƒœ๊ทธ์™€ spanํƒœ๊ทธ ๊ทธ๋ฆฌ๊ณ  ์ž์‹ ์—˜๋ฆฌ๋จผํŠธ๋กœ ul์ด ๋˜ ์žˆ๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

์ž์‹ ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์—†์œผ๋ฉด ๊ทธ๋Œ€๋กœ ํ…์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ตฌ์กฐ์ด๋‹ค.


๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์ž์‹ ์š”์†Œ๊ฐ€ ์žˆ๋Š”์ง€, ์—†๋Š”์ง€๋ฅผ ๊ตฌ๋ถ„์ง€์–ด์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ ์ž์‹์š”์†Œ๊ฐ€ ์žˆ๋‹ค๋ฉด ์žฌ๊ท€ํ•จ์ˆ˜๋ฅผ ์จ์ฃผ์–ด์•ผ ํ•˜๊ณ , ์—†๋‹ค๋ฉด ๊ทธ๋Œ€๋กœ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋จผ์ € ์นดํ…Œ๊ณ ๋ฆฌ (์Œ๋ฃŒ, ์Œ์‹, ๊ตฟ์ฆˆ, ์นด๋“œ) 4๊ฐ€์ง€๋ฅผ ๋ Œ๋”๋งํ•  4๊ฐœ์˜ li ์—˜๋ฆฌ๋จผํŠธ๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์ด ๊ฒฝ์šฐ ๋ฐ˜๋ณต๋ฌธ์„ ์‚ฌ์šฉํ•ด๋„ ๋˜์ง€๋งŒ, ๋‚˜๋Š” forEach ๋‚ด์žฅํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

menu.forEach(el => {
    if (el.type === "group") {
      // ๋ชจ๋“  1์ฐจ์› ๊ฐ์ฒด๊ฐ€ type: "group" ์œผ๋กœ ๋ฌถ์—ฌ์žˆ์Œ
      let li = document.createElement("li");
      currentNode.append(li);

      ...


๊ทธ๋ฆฌ๊ณ  ์ž์‹์š”์†Œ๋กœ input, span, ul ์ด๋ ‡๊ฒŒ 3๊ฐ€์ง€๊ฐ€ ์žˆ๋Š”๋ฐ, ์ด๊ฒƒ๋„ ๋‹ค ๋งŒ๋“ค์–ด์ค€๋‹ค.

๊ทธ ํ›„

      let input = document.createElement("input");
      input.type = "checkbox";
      li.append(input);

      let span = document.createElement("span");
      span.textContent = el.name;
      li.append(span);

      let ul = document.createElement("ul");
      li.append(ul);

      createTreeView(el.children, ul);   // ์ž์‹ ์š”์†Œ๊ฐ€ ์žˆ์œผ๋ฉด๋ชจ๋“  ์š”์†Œ๋“ค์„ ์žฌ๊ท€์ ์œผ๋กœ ์ƒ์„ฑํ•œ๋‹ค.
    }


์žฌ๊ท€๋ฅผ ๋Œ๊ณ  ๋งŒ์•ฝ ์ž์‹ ์š”์†Œ๊ฐ€ ๋”์ด์ƒ ์—†๋‹ค๋ฉด? ํ…์ŠคํŠธ๋งŒ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

// ๋”์ด์ƒ ์ž์‹ ์š”์†Œ๊ฐ€ ์—†์„ ๊ฒฝ์šฐ
else {
      const li = document.createElement("li");
      li.textContent = el.name;
      currentNode.append(li);
    }


tree-UI ๊ตฌํ˜„ ์ฝ”๋“œ

const root = document.getElementById("root");
function createTreeView(menu, currentNode) {
  // TODO: createTreeView ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜์„ธ์š”.

  menu.forEach(el => {
    if (el.type === "group") {
      let li = document.createElement("li");
      currentNode.append(li);

      let input = document.createElement("input");
      input.type = "checkbox";
      li.append(input);

      let span = document.createElement("span");
      span.textContent = el.name;
      li.append(span);

      let ul = document.createElement("ul");
      li.append(ul);

      createTreeView(el.children, ul);
    } else {
      const li = document.createElement("li");
      li.textContent = el.name;
      currentNode.append(li);
    }
  });
}

createTreeView(menu, root);



์ด์ œ ๋‚ด์ผ์ด๋ฉด ํ”„๋ฆฌ์ฝ”์Šค ๋งˆ์ง€๋ง‰ ๋‚ ์ด๋‹ค. ๋งˆ์ง€๋ง‰๊นŒ์ง€ ํ™”์ดํŒ…ํ•˜์ž!!

๐Ÿ‘Š ๋‚ด์ผ์˜ TIW(today I Will)

๋‚ ์”จ API