메뉴 트리 검색 기능 개요
다단계 메뉴 트리에서 특정 키워드와 일치하는 항목을 검색하고 강조 표시하는 기능은 프론트엔드 개발에서 자주 요구되는 사항입니다. 본 구현에서는 Vue.js를 활용해 2단계 메뉴 구조에서 동적 렌더링과 실시간 검색 기능을 구현합니다.
프로젝트 설정
기본 프로젝트 구조는 다음과 같습니다:
├── data.json # 메뉴 계층 구조 데이터
├── index.html # 메인 페이지
└── js
├── axios.min.js # HTTP 클라이언트 라이브러리
├── index.js # 핵심 로직 구현
└── vue.js # Vue 2.x 프레임워크
기능 요구사항
- 페이지 로드 시 전체 메뉴 트리 렌더링
- 검색어 입력 시 계층 구조 유지하며 일치 항목 표시
- 일치하는 항목은 노란 배경으로 강조
- 검색 결과 표시 규칙:
- 부모 메뉴가 존재할 경우: 부모 및 형제 메뉴 표시
- 자식 메뉴가 존재할 경우: 현재 메뉴 및 모든 자식 표시
- 독립 메뉴일 경우: 해당 항목만 표시
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 플래그로 강조 표시 제어
- 데이터 무결성: 검색 전 항상 강조 상태 초기화