코드스테이츠 프론트엔드 부트캠프-Section3 카테고리(Tree UI)를 재귀함수로?

그래도 아무튼 개발자·2023년 4월 12일
0

Front_End

목록 보기
11/12
post-thumbnail

재귀함수가 자주 쓰일 법한 카테고리, Tree UI에 관해서 구현을 시도해보자

위와 같이 평소에도 흔히 볼 수 있는 구조이다. 당장 윈도우 탐색기만 키더라도 왼편에 바로 보인다😂😂

생각해보면 루트 폴더가 있고, 루트 폴더를 펼치면 다양한 파일들도 있겠지만, 디렉토리들도 있을 것이다. 만일 특정 디렉토리를 여는 순간 그 디렉토리가 사실상 루트의 개념을 받게 되고, 그 루트의 개념을 이어받은 디렉토리 안에는 또 다른 다양한 파일들과 더불어 또 다른 하위 디렉토리들이 있는.. 이러한 방식일 것이다. 아주 보편적이다.

재귀함수로 구현하기에 매우 적합하다는 뜻이다 👍


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: '피스타치오 크림 프라푸치노' },
        ],
      },
      {
        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: '아이스 캐모마일 블렌드 티' },
        ],
      },
      {
        type: 'group',
        name: '주스',
        children: [
          { type: 'item', name: '한방에 쭉 감당' },
          { type: 'item', name: '파이팅 청귤' },
          { type: 'item', name: '딸기주스' },
          { type: 'item', name: '도와주 흑흑' },
        ],
      },
    ],
  },
  {
    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: '부드러운 생크림 카스텔라' },
        ],
      },
      {
        type: 'group',
        name: '샌드위치',
        children: [
          { type: 'item', name: '애플 까망베르 샌드위치' },
          { type: 'item', name: '트리플 머쉬룸 치즈 샌드위치' },
          { type: 'item', name: '로스트 치킨 샐러드 밀 박스' },
          { type: 'item', name: 'B.E.L.T 샌드위치' },
        ],
      },
      {
        type: 'group',
        name: '과일',
        children: [
          { type: 'item', name: '하루 한 컵 RED' },
          { type: 'item', name: '한라봉 가득 핸디 젤리' },
        ],
      },
      {
        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: 'group',
    name: '굿즈',
    children: [
      {
        type: 'group',
        name: '머그',
        children: [
          { type: 'item', name: '우리 한글 블랙 머그 473ml' },
          { type: 'item', name: '서울 투어 머그 355ml' },
          { type: 'item', name: '스타벅스 1호점 머그 400ml' },
          { type: 'item', name: '서울 제주 데이머그 세트' },
        ],
      },
      {
        type: 'group',
        name: '텀블러',
        children: [
          { type: 'item', name: 'SS 부산 투어 텀블러 355ml' },
          { type: 'item', name: 'SS 블랙 헤리티지 오드리 텀블러 355ml' },
          { type: 'item', name: 'SS 에치드 실버 텀블러 473ml' },
        ],
      },
      {
        type: 'group',
        name: '악세사리',
        children: [
          { type: 'item', name: '리저브 오렌지 카드 홀더' },
          { type: 'item', name: '스타벅스 1호점 에코백' },
          { type: 'item', name: '스타벅스 1호점 랩탑 파우치' },
        ],
      },
    ],
  },
  {
    type: 'group',
    name: '카드',
    children: [
      { type: 'item', name: '10000원권' },
      { type: 'item', name: '30000원권' },
      { type: 'item', name: '50000원권' },
      { type: 'item', name: '100000원권' },
    ],
  },
];

이러한 방식으로 세팅이 되어있는 메뉴가 있다고 가정해보자. 메뉴를 들어가면 음료, 음식, 굿즈, 카드 이렇게 4개의 디렉토리가 있는 것이고, 음료에 진입하면 콜드브루, 블렌디드, 주스 등 또 다른 다양한 디렉토리들이 존재하는 것이다.

function createTreeView(menu, currentNode) {
  for(let i=0; i<menu.length; i++) {
    const li = document.createElement('li');  //li 요소 일단 생성
    if(menu[i].children !== undefined) {    //children 요소가 있을 경우
      const input = document.createElement('input');
      input.type = 'checkbox';
      const span = document.createElement('span');
      span.textContent = menu[i].name;    //name을 span 태그로 감싸야 함.
      const ul = document.createElement('ul');

      li.append(input);   //생성해놓은 li에 input span ul append
      li.append(span);
      li.append(ul);
      
      createTreeView(menu[i].children, ul);   //ul 안에서 다시 children들로 재귀 시작
    }
    else li.textContent = menu[i].name;   //마지막엔 li 태그로 name을 감싸야 함.
    currentNode.append(li);   //만든 리스트를 부모(root거나 ul이거나)에 append
  }
}

이를 재귀함수로 표현하면 위와 같이 간단하게 표현이 가능하다!
menu와 currentNode가 들어가는데, currentNode가 위에서 말한 루트 혹은 루트 개념을 이어받은 하위 디렉토리를 의미하고, 메뉴는 그 안에 있는 요소들을 의미한다!

css파일까지 살짝 처리하고 나면 위와 같이 체크박스 형태의 Tree UI가 만들어지게 된다 🫡🫡

0개의 댓글