JSON(JavaScript Object Notation)은 서로 다른 프로그램에서 데이터를 교환하기 위한 포맷이다. JSON.stringify 함수를 이용하여 객체를 문자열로 변환하여 객체 내용을 보낼 수 있고, JSON.parse 함수를 이용하여 문자열을 다시 객체로 변환하여 내용을 확인할 수 있다. 이때, 객체를 문자열로 변환하는 과정을 직렬화(serialize), 문자열을 객체로 변환하는 과정을 역직렬화(deserialize)라고 한다.
이번 시간에는 재귀를 이용해 브라우저에서 제공하는 주요 기능 중 하나인 JSON.stringify 함수를 직접 구현해보았다. 앞에서 언급했듯이 JSON.stringify는 객체를 JSON으로 변경하는 메소드였다. 이 기능을 하는 함수를 아래와 같은 방식으로 구현하였다.
function stringifyJSON(obj) { let resultArr = []; for(let key in obj) { if(key === "functions" || key === undefined) { //함수와 undefined는 stringify되지 않는다. return `{${resultArr}}` } } if(typeof obj === 'number' || typeof obj === 'boolean' || obj === null) { return `${obj}`; } else if(typeof obj === 'string') { return `"${obj}"`; } else if(Array.isArray(obj)) { //Array가 input으로 주어졌을 경우 for(let i = 0; i < obj.length; i++) { resultArr.push(stringifyJSON(obj[i])); } return `[${resultArr}]` } else if(typeof obj === 'object') { //Object가 input으로 주어졌을 경우 for(let key in obj) { resultArr.push(stringifyJSON(key) + ":" + stringifyJSON(obj[key])); } return `{${resultArr}}` } };
Array가 input으로 주어졌을 경우 배열의 요소 각각의 타입을 확인해야 하기 때문에 배열의 인덱스를 이용해서 요소 하나씩 전달인자로 보내 stringifyJSON 함수를 다시 호출하고 그 리턴값을 새로운 배열인 resultArr에 담아 결과를 출력하는 재귀함수의 형태로 구현하였다.
Object가 input으로 주어졌을 경우도 마찬가지로 key와 value 각각을 전달인자로 보내 stringifyJSON 함수를 다시 호출하는 방식으로 구현하였다.
stringifyJSON 함수를 직접 구현해보면서 재귀함수의 동작방식을 많이 생각해보게 되었고, JSON.stringify에 대해서도 공부할 수 있는 시간이었다.
우리 일상생활에는 Tree 구조가 많이 사용된다. TreeUI 시간에는 기업용 애플리케이션에서 흔히 볼 수 있는 트리구조를 표현한 UI를 직접 구현해보았다.
다음과 같은 구조를 구현하였다. 데이터에 대한 정보는 const menu = [] 배열에 미리 저장이 되어있다.
트리 구조를 구현하기 위하여 다음과 같은 코드를 작성하였다.
const root = document.getElementById('root'); //부모 엘리먼트 function createTreeView(menu, currentNode) { for(let i = 0; i < menu.length; i++) { const li = document.createElement('li'); if(!menu[i].children) { //더 이상 자식이 없을 경우 li.textContent = menu[i].name; // 정보 출력하고 마무리한다. } else { //자식이 있을 경우 const input = document.createElement('input'); const span = document.createElement('span'); const ul = document.createElement('ul'); input.setAttribute('type',"checkbox"); span.textContent = menu[i].name; li.append(input, span, ul); createTreeView(menu[i].children, ul); //자식을 매개변수로 보내 재귀함수 호출 } currentNode.append(li); } } createTreeView(menu, root);
반복적으로 내용을 출력하는 것이기 때문에 재귀함수를 사용하면 적절할 것이라고 생각했다. 이를 구현하기 위해 저번시간에 학습했던 재귀함수 템플릿에 따라 작성하였다.
1. 문제를 더 이상 쪼갤 수 없는 경우: 더 이상 출력할 것이 없는 경우. 즉, 더 이상 자식이 없을 경우
2. 단순한 문제의 해답: 현재의 정보를 출력하고 마무리한다.
3. 그렇지 않음 경우: 현재의 정보를 출력하고 menu의 자식, currentNode를 매개변수로 하는 createTreeView 함수를 다시 호출한다.
위 과정을 반복문을 이용하여 menu의 길이만큼 반복을 해 주었다.
TreeUI를 구현하면서 재귀함수의 필요성에 대해 많이 느낄 수 있었다. 재귀함수가 없었다면 태그를 생성하고, 속성을 부여하고, 부모 노드에 붙이는 과정을 수없이 해야 했을 것이고, 그 수만큼 변수도 많이 필요했을 것이다. 그러나 재귀함수를 이용하여 코드를 간결화하고 가독성도 높일 수 있었다.
코드를 보고싶다면 여기로!
이번 시간에는 재귀함수를 이용해 stringifyJSON, TreeUI를 직접 구현해보았다.
내일은 API에 대하여 학습하겠다.
오늘은 여기까지.!