자바스크립트 검색어 실시간 필터링 목록 렌더링 구현 가이드
자바스크립트 배열 메서드와 DOM 이벤트를 결합하여 사용자가 검색창에 단어를 입력할 때 실시간으로 일치하는 목록만 화면에 다시 그리는 필터링 파이프라인을 단계별로 완성합니다.
목표와 준비 사항: 실시간 검색 필터의 동작 원리
웹 애플리케이션이나 사내 관리 도구에서 대량의 데이터 중 원하는 항목을 빠르게 찾는 기능은 필수적인 인터페이스입니다. 이번 튜토리얼의 목표는 별도의 외부 라이브러리 없이 순수 자바스크립트(Vanilla JS)만을 사용하여 검색창에 키워드를 입력하는 즉시 화면의 목록이 동적으로 변경되는 실시간 필터링 기능을 구현하는 것입니다.
실습을 시작하기 위해 텍스트 편집기와 최신 웹 브라우저를 준비합니다. 본 실습은 자바스크립트 ES6 문법을 기준으로 진행되며, 배열의 `filter` 메서드와 문자열 비교 함수인 `includes`, 그리고 브라우저 텍스트 입력 신호를 포착하는 `input` 이벤트에 대한 기본 개념을 갖추고 있다면 누구나 쉽게 따라 할 수 있습니다.
사용자가 키보드를 누를 때마다 발생하는 이벤트를 가로채 원본 데이터 배열을 순회하고, 입력값과 일치하는 항목만 추출하여 DOM을 새로 갱신하는 전체 데이터 흐름을 명확하게 파악하는 것이 이번 학습의 핵심입니다.

실행 순서: 데이터 관리와 이벤트 바인딩 파이프라인
실시간 필터링을 안정적으로 구현하려면 화면에 표시할 원본 데이터를 변조하지 않고 보존하는 파이프라인을 세워야 합니다. 원본 데이터 배열을 수정해 버리면 검색어를 지웠을 때 이전 목록을 복구할 수 없기 때문에, 원본 배열은 항상 불변 상태로 유지하고 필터링된 새로운 결과 배열만을 화면 렌더링 함수로 넘겨주어야 합니다.
두 번째 단계는 입력 감지 이벤트의 선택입니다. 과거에는 `keyup`이나 `keydown` 이벤트를 주로 사용했으나, 한글 같은 조합형 문자나 마우스 우클릭 붙여넣기 동작에서 이벤트가 누락되는 한계가 있었습니다. 따라서 텍스트가 변경되는 모든 순간을 즉각 감지하는 표준 `input` 이벤트를 입력창 요소에 등록해야 합니다.
마지막으로 사용자가 입력한 검색 문자열과 데이터의 문자열을 소문자로 통일(toLowerCase)하고 불필요한 앞뒤 공백(trim)을 제거한 뒤, 배열 메서드를 통해 일치 항목만 선별하여 렌더링 함수에 전달하는 순서로 코드를 구성합니다.

구체적인 입력 예시: HTML 마크업과 자바스크립트 코드
간단한 상품 목록 필터링을 가정한 예제 코드입니다. 먼저 HTML 영역에 검색 입력창 `<input id="searchInput">`과 결과를 표시할 리스트 `<ul id="itemList">`를 작성합니다. 구조가 준비되면 자바스크립트에서 대상 요소들을 `document.getElementById`로 선택하여 변수에 할당합니다.
자바스크립트 코드에서는 객체 배열 형태로 초기 데이터를 정의합니다. 예를 들어 `const products = [{ id: 1, name: '무선 키보드' }, { id: 2, name: '기계식 키보드' }, { id: 3, name: '게이밍 마우스' }];`와 같이 준비합니다. 이어서 목록을 화면에 그리는 `renderList(data)` 함수를 선언하고, 리스트 요소 내부를 비운 뒤 전달받은 배열을 순회하며 `document.createElement('li')`로 요소를 추가하도록 구성합니다.
이벤트 처리 함수는 다음과 같이 연결합니다. `searchInput.addEventListener('input', (e) => { const query = e.target.value.trim().toLowerCase(); const filtered = products.filter(item => item.name.toLowerCase().includes(query)); renderList(filtered); });` 이렇게 작성하면 키 입력이 발생할 때마다 필터링된 배열이 즉시 렌더링 함수로 전달되어 화면이 동기화됩니다.

기대 결과 확인: 실시간 반응과 빈 결과 처리 검증
작성한 코드를 웹 브라우저에서 실행하고 검색창에 '키보드'를 입력해 봅니다. 입력과 동시에 '게이밍 마우스'는 목록에서 즉시 사라지고 '무선 키보드'와 '기계식 키보드'만 화면에 남아 있어야 합니다. 검색어를 지우면 초기 상태의 세 가지 상품이 모두 정상적으로 다시 나타나는지 확인합니다.
영문 검색어의 경우 대소문자 구분이 없어야 하므로, 'KEYBOARD'처럼 대문자로 입력해도 동일하게 소문자 데이터와 매칭되는지 점검합니다. 또한 한글 입력 시 자음과 모음이 조합되는 과정에서 마지막 글자가 누락되지 않고 온전하게 필터링되는지도 브라우저 콘솔 및 화면을 통해 확인해야 합니다.
데이터와 일치하는 검색어가 없을 때 화면이 단순히 텅 비어 있는 것보다는 '일치하는 항목이 없습니다'와 같은 안내 문구가 노출되도록 `filtered.length === 0` 조건을 분기 처리해 두면 훨씬 사용자 친화적인 결과 화면을 완성할 수 있습니다.

주의점과 최적화: 보안과 잦은 DOM 조작 방지
실시간 필터링을 구현할 때 흔히 저지르는 실수는 검색 결과를 빠르게 반영하기 위해 `innerHTML`을 무분별하게 사용하는 것입니다. 사용자 입력값을 정제하지 않고 `innerHTML`에 직접 문자열로 결합하면 크로스 사이트 스크립팅(XSS) 취약점에 노출될 수 있습니다. 텍스트 노드를 추가할 때는 `textContent`를 사용하거나 `createElement`를 활용하는 것이 안전합니다.
데이터 양이 수백 개 이상으로 늘어나는 환경이라면 매 키 입력마다 DOM을 새로 그리는 작업이 브라우저의 렌더링 부하를 유발할 수 있습니다. 수많은 노드를 개별 추가하면 리플로우와 리페인트가 과도하게 발생하므로, 가상 컨테이너인 `DocumentFragment`에 자식 노드들을 모아 한 번에 DOM 트리에 부착하는 방식을 권장합니다.
또한 타자가 매우 빠른 사용자가 연속으로 키보드를 누를 때 매 순간 필터링 로직이 동작하는 것을 제어하기 위해 200~300ms 간격으로 실행을 지연시키는 디바운스(Debounce) 패턴을 적용하면 브라우저의 연산 자원을 효과적으로 아낄 수 있습니다.