Vue.js를 사용한 메뉴 트리 검색 기능 구현

메뉴 트리 검색 기능 개요

다단계 메뉴 트리에서 특정 키워드와 일치하는 항목을 검색하고 강조 표시하는 기능은 프론트엔드 개발에서 자주 요구되는 사항입니다. 본 구현에서는 Vue.js를 활용해 2단계 메뉴 구조에서 동적 렌더링과 실시간 검색 기능을 구현합니다.

프로젝트 설정

기본 프로젝트 구조는 다음과 같습니다:

├── data.json       # 메뉴 계층 구조 데이터
├── index.html      # 메인 페이지
└── js
    ├── axios.min.js # HTTP 클라이언트 라이브러리
    ├── index.js     # 핵심 로직 구현
    └── vue.js       # Vue 2.x 프레임워크

기능 요구사항

  1. 페이지 로드 시 전체 메뉴 트리 렌더링
  2. 검색어 입력 시 계층 구조 유지하며 일치 항목 표시
  3. 일치하는 항목은 노란 배경으로 강조
  4. 검색 결과 표시 규칙:
    • 부모 메뉴가 존재할 경우: 부모 및 형제 메뉴 표시
    • 자식 메뉴가 존재할 경우: 현재 메뉴 및 모든 자식 표시
    • 독립 메뉴일 경우: 해당 항목만 표시

HTML 구현 (index.html)

<div id="app">
  <input 
    type="text" 
    v-model="searchQuery" 
    placeholder="메뉴 검색"
  >
  <ul>
    <li v-for="parent in menuHierarchy" :key="parent.id">
      <span :class="{ highlight: parent.isMatched }">
        {{ parent.label }}
      </span>
      <ul v-if="parent.subItems">
        <li v-for="child in parent.subItems" :key="child.id">
          <span :class="{ highlight: child.isMatched }">
            {{ child.label }}
          </span>
        </li>
      </ul>
    </li>
  </ul>
</div>

Vue 로직 구현 (index.js)

new Vue({
  el: '#app',
  data: {
    originalMenu: [],
    menuHierarchy: [],
    searchQuery: ''
  },
  mounted() {
    this.fetchMenuData();
  },
  methods: {
    fetchMenuData() {
      axios.get('./data.json')
        .then(response => {
          this.originalMenu = response.data;
          this.menuHierarchy = [...this.originalMenu];
        });
    },
    resetHighlight() {
      this.originalMenu.forEach(parent => {
        parent.isMatched = false;
        if (parent.subItems) {
          parent.subItems.forEach(child => {
            child.isMatched = false;
          });
        }
      });
    }
  },
  watch: {
    searchQuery() {
      if (!this.searchQuery) {
        this.menuHierarchy = [...this.originalMenu];
        return;
      }

      this.resetHighlight();
      const filteredResults = [];

      this.originalMenu.forEach(parent => {
        let parentMatch = false;
        
        if (parent.label.includes(this.searchQuery)) {
          parent.isMatched = true;
          parentMatch = true;
          filteredResults.push(parent);
        }

        if (parent.subItems) {
          parent.subItems.forEach(child => {
            if (child.label.includes(this.searchQuery)) {
              child.isMatched = true;
              if (!parentMatch) {
                parent.isMatched = false;
                parentMatch = true;
                filteredResults.push(parent);
              }
            }
          });
        }
      });

      this.menuHierarchy = filteredResults;
    }
  }
});

핵심 구현 전략

  • 계층적 데이터 처리: 상위/하위 메뉴 관계 유지하며 탐색
  • 반응형 검색: v-model과 watch를 이용한 실시간 필터링
  • 상태 관리: isMatched 플래그로 강조 표시 제어
  • 데이터 무결성: 검색 전 항상 강조 상태 초기화

태그: Vue.js JavaScript 메뉴 트리 검색 기능 axios

7월 10일 02:04에 게시됨