코드스테이츠 SEB FE 41기/Section 별 내용 정리

section3/Unit1/ [자료구조/알고리즘] 재귀(10/20)

bbeyak 2022. 10. 21. 15:49
반응형

블로깅 주제

  • JSON.stringify

1. 지금 현재, 당신의 기분이나 느낌을 표현해 주세요.

  • 드디어 금요일이다. 역시 재귀 코플릿은 까다로웠다....데일리코딩도 역시 어려웠다. 얼른 알고리즘 푸는 실력이 늘었으면 좋겠다. 복잡하게 생각하지말자. 규칙찾자. 문제를 잘 읽자!

2. 오늘 무엇을 학습한 내용 중 지금 떠올릴 수 있는 단어를 모두 나열해 주세요.

  • JSON.stringify, tree UI만들기

3. 2에서 작성한 단어를 가지고, 오늘의 학습 내용을 설명해 보세요.

- JSON.stringify

 

▶ JSON이란?

 

JSON은 JavaScript Object Notation의 줄임말로, 데이터 교환을 위해 만들어진 객체 형태의 포맷이다. 네트워크를 통해, 어떤 객체 내용을 다른 프로그램에게 전송한다고 가정해보자. 이 객체 내용을 일종의 메신저 혹은 채팅 프로그램에서 쓰는 하나의 메시지라고 한다면, 다음 객체를 어떻게 전송할 수 있을까?

const message = {
  sender: "김코딩",
  receiver: "박해커",
  message: "해커야 오늘 저녁 같이 먹을래?",
  createdAt: "2021-01-12 10:10:10"
}

 

메시지 객체가 전송 가능하려면, 메시지를 보내는 발신자와 메시지를 받는 수신자가 같은 프로그램을 사용하거나, 문자열처럼 범용적으로 읽을 수 있는 형태여야 한다.

 

전송 가능한 조건 (transferable condition)

  • 수신자(reciever)와 발신자(sender)가 같은 프로그램을 사용한다.
  • 또는, 문자열처럼 범용적으로 읽을 수 있어야 한다.

 

객체는 타입 변환을 이용해 String으로 변환할 경우 객체 내용을 포함하지 않는다. JavaScript에서 객체를 문자열로 변환하기위해 메서드(message.toString())나 형변환(String(message))을 시도하면, [object Object] 라는 결과를 리턴한다.

 

이 문제를 해결하는 방법은 객체를 JSON의 형태로 변환하거나 JSON을 객체의 형태로 변환하는 방법이다. 

  • JSON.stringify : 객체를 JSON으로 변환합니다.
  • JSON.parse : JSON을 객체로 변환합니다.

 

stringify하는 이 과정을 직렬화(serialize)한다고 한다.

let transferableMessage = JSON.stringify(message)

console.log(transferableMessage) 
// `{"sender":"김코딩","receiver":"박해커","message":"해커야 오늘 저녁 같이 먹을래?",
//    "createdAt":"2021-01-12 10:10:10"}`

console.log(typeof(transferableMessage))
// `string`

 

JSON으로 변환된 객체의 타입은 문자열이다. 발신자는 객체를 직렬화한 문자열을 누군가에게 객체의 내용을 보낼 수 있다. 그렇다면 수신자는 이 문자열 메시지를 어떻게 다시 객체의 형태로 만들 수 있을까? JSON.stringify와 정반대의 작업을 수행을 하는 메서드 JSON.parse 를 사용할 수 있다.

JSON.parse를 적용하는 이 과정을 역직렬화(deserialize)한다고 합니다.

let packet = `{"sender":"김코딩","receiver":"박해커","message":"해커야 오늘 저녁 같이 먹을래?","createdAt":"2021-01-12 10:10:10"}`
let obj = JSON.parse(packet)

console.log(obj)
/*
 * {
 * sender: "김코딩",
 * receiver: "박해커",
 * message: "해커야 오늘 저녁 같이 먹을래?",
 * createdAt: "2021-01-12 10:10:10"
 * }
 */

 console.log(typeof(obj))
 // `object`

 

직렬화와 역직렬화 모식도

이처럼, JSON은 서로 다른 프로그램 사이에서 데이터를 교환하기 위한 포맷이다. 그리고 JSON 포맷은 자바스크립트를 포함한 많은 언어에서 범용적으로 사용하는 유명한 포맷이다.

 

JSON 사용 규칙

 

  자바스크립트 객체 JSON
키는 따옴표 없이 쓸 수 있음
{ key : "property" }
반드시 쌍따옴표를 붙여야 함
'{"key":"property"}'
문자열 값 작은따옴표도 사용 가능
{ "key" : 'property' }
반드시 큰따옴표로 감싸야 함
'{"key":"property"}'
키와 값 사이 공백 사용 가능
{"key" : 'property'}
사용 불가능
'{"key":"property"}'
키-값 쌍 사이 공백 사용 가능
{ "key":'property', num:1 }
사용 불가능
'{"key":"property","num":1}'

 

- 과제 1 : JSON.stringfy 함수 만들기

 

stringifyJSON.js

function stringifyJSON(obj) {
  // your code goes here
  // 불린, 스트링, 널, 넘버, 배열, 객체
  if(typeof obj === 'boolean' || obj === null || typeof obj === 'number'){
    return `${obj}`;
  }
  if(typeof obj === 'string'){
    return `"${obj}"`;
  }

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

  if(typeof obj === 'object' && !Array.isArray(obj)){
    let strObj = '';
      for (let key in obj) {
          if (obj[key] === undefined || typeof obj[key] === 'function') {
              continue;
          } 
          strObj += `${stringifyJSON(key)}:${stringifyJSON(obj[key])},`;
      }
      strObj = strObj.slice(0,-1); // 마지막 ',' 빼주기
      return `{${strObj}}`;
    }
  
};

// 다음 코드는 결과 제출을 위한 코드입니다. 신경 쓰지 않아도 좋습니다.
if (typeof window === "undefined") {
  module.exports = stringifyJSON;
}

 

이번 과제의 포인트!

 

※ template literal

예시) let obj = [1,2,3]

obj가 배열인 경우, `${obj}`처럼 템플릿 리터럴을 사용해도 원하는대로  '[1,2,3]' 이런 결과가 나오지 않는다.

템플릿 리터럴이 붙는 순간,

배열([,]) 까지고, 요소 중 문자열이 있으면 그 요소의 따옴표(" 또는 ') 가 한겹 까진 상태로 만들고,

그 상태에서 겉에 ""를 씌워줌으로써 문자열로 만들어준다.

let obj = ["1",2,3];
`${obj}` = "1,2,3" ; //중첩이 몇번이 되어도 다 벗겨지고 스트링화됨.

 

객체에 템플릿 리터럴이 붙으면, 

const description = 'App opened';
const properties = { key1: 'val1', blah: 123 };
const logString = `Description: ${description}. Properties: ${properties}`;
console.log(logString);

그림처럼 [object Object]가 출력된다.

그래서 객체를 스트링형태로 만들어주고 싶으면 JSON.stringify를 사용하는 것이다. 

 

https://stackoverflow.com/questions/57238871/why-is-an-array-inside-a-template-string-displayed-as-a-normal-string

 

Why is an array inside a template string displayed as a normal string?

Let's assume we have an object: var pet = { "name": "Barky", "species" : "dog", "foods": { "likes": ["bones", "carrots"], "dislikes": ["tuna"] } }; co...

stackoverflow.com

https://stackoverflow.com/questions/46146860/javascript-template-strings-dont-pretty-print-objects

 

Javascript - Template Strings Don't Pretty Print Objects

Can I use ES6 template strings to pretty print javascript objects? This is from a React Native project, with console.log() outputting to Chrome debugging tools. What I Want const description = 'App

stackoverflow.com

 

null, undefined의 type

typeof null // "object"
typeof undefined // "undefined"
let value = null;
String(null) // "null"
value.toString() //typeError!

 

- 과제 2: tree UI

 

fix_me.js

// TODO: createTreeView 함수를 재귀(자기 자신을 계속 부르게 함)호출하여 테스트케이스를 통과하세요.
// GOAL: 최종 결과가 resut.html와 같은 모습으로 나와야 합니다.

// 데이터 구조)
// menu[0]은 음료 메뉴판. menu[0].children = [ 콜드브루, 프라푸치노, 블렌디드, 티, 주스] ;
// menu[1]은 음식. menu[1].children = [빵, 케이크, 샌드위치, 과일, 스낵, 아이스크림] ;
// menu[2]는 굿즈. menu[2].children = [머그, 텀블러, 악세사리]
// menu[3]은 카드. menu[3].children  = [10000원권, 30000원권, 50000원권, 100000원권]

// menu[i].children = [ {type: "item", name: 음식이름 }, {type: "item", name: 음식이름 }  ]

// type이 "group" 이면 li에 checkbox,span 및 ul 태그 append 후 재귀 호출(그 ul태그에 또 li태그 append하게!)
// type이 "item" 이면 li 태그로 currentNode(ul태그)에 append

const root = document.getElementById("root");
function createTreeView(menu, currentNode) {
  // TODO: createTreeView 함수를 작성하세요.

  for (let i = 0; i < menu.length; i++) {
    const makeUl = document.createElement("ul");
    const makeLi = document.createElement("li");
    // 자식요소가 없을때
    if (menu[i].type === "item") {
      // ↓ li 태그 안에 'name' 값 넣어주기
      makeLi.textContent = menu[i].name;
      currentNode.append(makeLi);
    }
    //자식요소가 있을 때
    else {
      const makeInput = document.createElement("input");
      makeInput.setAttribute("type", "checkbox");
      const makeSpan = document.createElement("span");
      makeSpan.textContent = menu[i].name;
      // ↓ li 안에 input, span, ul 한꺼번에 넣어주기
      makeLi.append(makeInput, makeSpan, makeUl);
      currentNode.append(makeLi);
      // 재귀호출(만든 ul에 자식요소 붙히기 위해)
      createTreeView(menu[i].children, makeUl);
    }
  }
}

// 트리 상->하 순으로 만들어주는 구조
// createTreeView(menu, currentNode) = currentNode 태그 안에 append로 ul or li 를 append해주는 함수 
// 만약 자식이 있으면 (체크박스,span,ul append된)li의 ul에 자식요소들을 append 하기 위해 재귀함수 호출, 
// 없으면 li만 currenNode에 append

// 처음에 createTreeview(menu, root) 선언하기 때문에 첫번째 currentNode는 root 가 됨
// 그 다음에는 createTreeview(menu[i].children, makeUl)로 재귀함수 호출하여, ul에 li append되게 만듦

createTreeView(menu, root);

반응형