JavaScript 이벤트 완벽 가이드 - 이벤트 핸들링 마스터하기

JavaScript 이벤트 완벽 가이드 - 이벤트 핸들링 마스터하기 안녕하세요! 오늘은 웹 개발의 핵심인 JavaScript 이벤트에 대해 자세히 알아보겠습니다. 사용자의 클릭, 키보드 입력, 마우스 움직임 등 모든 상호작용은 이벤트를 통해 처리됩니다. 이 포스팅에서는 이벤트의 기본 개념부터 고급 활용까지 체계적으로 정리해보겠습니다! 이벤트란? 기본 개념 **이벤트(Event)**는 웹 페이지에서 발생하는 모든 상호작용을 의미합니다. 사용자의 마우스 클릭, 키보드 입력, 페이지 로드 등이 모두 이벤트입니다. 이벤트의 구성 요소 이벤트 타입: 어떤 종류의 이벤트인지 (click, keydown, load 등) 이벤트 타겟: 이벤트가 발생한 요소 이벤트 핸들러: 이벤트 발생 시 실행될 함수 주요 이벤트 타입들 1. 마우스 이벤트 이벤트 타입 설명 특징 click 마우스 클릭 가장 일반적인 클릭 이벤트 dblclick 더블 클릭 빠르게 두 번 클릭 mousedown 마우스 버튼 누름 버튼을 누르는 순간 mouseup 마우스 버튼 해제 버튼을 떼는 순간 mousemove 마우스 이동 커서가 움직일 때 mouseenter 요소 진입 요소 안으로 들어올 때 (버블링 없음) mouseover 요소 진입 요소 안으로 들어올 때 (버블링 있음) mouseleave 요소 이탈 요소 밖으로 나갈 때 (버블링 없음) mouseout 요소 이탈 요소 밖으로 나갈 때 (버블링 있음) 2. 키보드 이벤트 이벤트 타입 설명 특징 keydown 키 누름 키를 누르는 순간 keyup 키 해제 키를 떼는 순간 keypress 키 입력 문자 키 입력 시 (폐지됨) 3. 폼 이벤트 이벤트 타입 설명 submit 폼 제출 reset 폼 초기화 input 입력값 변경 change 값 변경 완료 focus 포커스 획득 blur 포커스 상실 4. 문서/윈도우 이벤트 이벤트 타입 설명 load 페이지 로드 완료 DOMContentLoaded DOM 로드 완료 resize 윈도우 크기 변경 scroll 스크롤 beforeunload 페이지 이탈 전 이벤트 핸들러 등록 방법 1. 인라인 이벤트 핸들러 (비권장) <button onclick="handleClick()">클릭하세요</button> <script> function handleClick() { console.log('버튼이 클릭되었습니다!'); } </script> 단점: ...

July 14, 2025 · 7 min · Haeun

JSON 완벽 가이드 - 웹 개발 필수 데이터 포맷 정복하기

JSON 완벽 가이드 - 웹 개발의 핵심 데이터 포맷 웹 개발을 하다 보면 정말 자주 마주치는 게 JSON이다. API 통신할 때도, 설정 파일 만들 때도, 데이터 저장할 때도 JSON을 쓴다. 하지만 정작 JSON이 뭔지, 어떻게 제대로 활용하는지 모르는 경우가 많다. 오늘은 JSON의 기본부터 실제 활용까지 한번에 정리해보겠다. JSON이 뭔가? **JSON(JavaScript Object Notation)**은 클라이언트와 서버 간 데이터 교환을 위한 텍스트 기반 포맷이다. 이름에 JavaScript가 들어가지만 대부분의 프로그래밍 언어에서 사용할 수 있다. ...

July 11, 2025 · 3 min · Haeun

JavaScript 비동기 프로그래밍 완벽 가이드 - 동기 vs 비동기 이해하기

JavaScript 비동기 프로그래밍 완벽 가이드 - 동기 vs 비동기 이해하기 JavaScript 개발에서 가장 중요한 개념 중 하나인 비동기 프로그래밍에 대해 써보려합니다. 웹 개발을 하다 보면 “동기"와 “비동기"라는 용어를 자주 접하게 되는데, 이 두 개념을 제대로 이해하는 것이 현대 JavaScript 개발의 핵심입니다. 동기 vs 비동기란? 기본 개념 JavaScript는 싱글 스레드(Single Thread) 언어입니다. 이는 한 번에 하나의 작업만 처리할 수 있다는 의미입니다. 하지만 실제로는 여러 작업이 동시에 처리되는 것처럼 보이는데, 이는 동기와 비동기 처리 방식의 차이 때문입니다. ...

July 9, 2025 · 10 min · Haeun

디바운스 vs 쓰로틀 완벽 비교 가이드 - 언제 어떤 것을 사용할까?

디바운스 vs 쓰로틀 완벽 비교 가이드 - 언제 어떤 것을 사용할까? 이번에는 **디바운스(Debounce)**와 **쓰로틀(Throttle)**의 차이점을 명확히 이해하고, 실전에서 언제 어떤 것을 사용해야 하는지 알아보겠습니다. 핵심 차이점 특징 디바운스 쓰로틀 실행 시점 마지막 이벤트 후 일정 시간 지난 후 일정 시간마다 한 번씩 실행 횟수 그룹의 마지막에 1번만 주기적으로 여러 번 적합한 상황 입력 완료 후 실행 실시간 반응 필요 시각적 비교 디바운스 (Debounce) 이벤트: |--|--|--|--|--|--|--|--|--|--| 실행: | 연속된 이벤트를 그룹화하여 마지막에 한 번만 실행 쓰로틀 (Throttle) 이벤트: |--|--|--|--|--|--|--|--|--|--| 실행: | | | | | | 일정 주기마다 한 번씩 실행 언제 어떤 것을 사용할까? 디바운스 사용 시기 검색창 자동완성: 사용자가 타이핑을 멈춘 후 검색 폼 자동 저장: 입력 완료 후 저장 윈도우 리사이즈: 크기 조정 완료 후 레이아웃 재계산 쓰로틀 사용 시기 스크롤 이벤트: 무한 스크롤, 고정 헤더 게임 캐릭터 이동: 마우스/키보드 입력 처리 실시간 차트 업데이트: 주기적인 데이터 갱신 실전 예제: 검색 vs 스크롤 // 디바운스: 검색창 (입력 완료 후 실행) const searchInput = document.getElementById('search'); searchInput.addEventListener('input', debounce((e) => { fetchSearchResults(e.target.value); }, 300)); // 쓰로틀: 스크롤 (주기적 실행) window.addEventListener('scroll', throttle(() => { updateHeaderPosition(); }, 100)); 고급 활용: React Hook // 커스텀 디바운스 Hook function useDebounce(value, delay) { const [debouncedValue, setDebouncedValue] = useState(value); useEffect(() => { const handler = setTimeout(() => { setDebouncedValue(value); }, delay); return () => { clearTimeout(handler); }; }, [value, delay]); return debouncedValue; } // 커스텀 쓰로틀 Hook function useThrottle(callback, delay) { const lastRun = useRef(Date.now()); return useCallback((...args) => { if (Date.now() - lastRun.current >= delay) { callback(...args); lastRun.current = Date.now(); } }, [callback, delay]); } // 사용 예시 function SearchComponent() { const [query, setQuery] = useState(''); const debouncedQuery = useDebounce(query, 300); useEffect(() => { if (debouncedQuery) { fetchSearchResults(debouncedQuery); } }, [debouncedQuery]); return ( <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="검색어를 입력하세요" /> ); } 성능 최적화 팁 1. 적절한 딜레이 설정 // 검색: 300ms (사용자가 타이핑을 멈출 시간) const searchDebounce = debounce(searchFunction, 300); // 스크롤: 100ms (부드러운 반응) const scrollThrottle = throttle(scrollFunction, 100); // 리사이즈: 500ms (레이아웃 재계산 비용 고려) const resizeDebounce = debounce(resizeFunction, 500); 2. 메모리 누수 방지 // 컴포넌트 언마운트 시 정리 useEffect(() => { const debouncedHandler = debounce(handleInput, 300); input.addEventListener('input', debouncedHandler); return () => { input.removeEventListener('input', debouncedHandler); }; }, []); 3. 조건부 적용 // 네트워크 상태에 따른 동적 조정 function adaptiveDebounce(callback, baseDelay = 300) { const isSlowConnection = navigator.connection?.effectiveType === 'slow-2g'; const delay = isSlowConnection ? baseDelay * 2 : baseDelay; return debounce(callback, delay); } 실제 프로젝트 적용 사례 1. 쇼핑몰 검색 기능 class SearchManager { constructor() { this.searchInput = document.getElementById('search'); this.resultsContainer = document.getElementById('results'); this.setupEventListeners(); } setupEventListeners() { // 디바운스: 검색 요청 최적화 this.searchInput.addEventListener('input', debounce((e) => { this.performSearch(e.target.value); }, 300)); // 쓰로틀: 검색 결과 스크롤 this.resultsContainer.addEventListener('scroll', throttle(() => { this.handleInfiniteScroll(); }, 200)); } async performSearch(query) { if (query.length < 2) return; try { const results = await fetch(`/api/search?q=${query}`); this.displayResults(await results.json()); } catch (error) { console.error('검색 실패:', error); } } handleInfiniteScroll() { const { scrollTop, scrollHeight, clientHeight } = this.resultsContainer; if (scrollTop + clientHeight >= scrollHeight - 100) { this.loadMoreResults(); } } } 2. 대시보드 실시간 업데이트 class DashboardManager { constructor() { this.charts = document.querySelectorAll('.chart'); this.setupRealTimeUpdates(); } setupRealTimeUpdates() { // 쓰로틀: 차트 업데이트 (실시간성 유지) window.addEventListener('resize', throttle(() => { this.resizeCharts(); }, 100)); // 디바운스: 설정 저장 (입력 완료 후) this.setupAutoSave(); } setupAutoSave() { const settingsForm = document.getElementById('settings'); settingsForm.addEventListener('change', debounce(() => { this.saveSettings(); }, 1000)); } async saveSettings() { const formData = new FormData(settingsForm); try { await fetch('/api/settings', { method: 'POST', body: formData }); console.log('설정 저장 완료'); } catch (error) { console.error('설정 저장 실패:', error); } } } 디버깅 팁 1. 실행 횟수 모니터링 function createMonitoredDebounce(callback, delay) { let callCount = 0; const debouncedFunction = debounce((...args) => { callCount++; console.log(`디바운스 실행 횟수: ${callCount}`); callback(...args); }, delay); return debouncedFunction; } function createMonitoredThrottle(callback, delay) { let callCount = 0; const throttledFunction = throttle((...args) => { callCount++; console.log(`쓰로틀 실행 횟수: ${callCount}`); callback(...args); }, delay); return throttledFunction; } 2. 성능 측정 function measurePerformance(func, name) { return function (...args) { const start = performance.now(); const result = func.apply(this, args); const end = performance.now(); console.log(`${name} 실행 시간: ${end - start}ms`); return result; }; } // 사용 예시 const optimizedSearch = measurePerformance( debounce(searchFunction, 300), '디바운스 검색' ); 핵심 포인트: 디바운스: 입력 완료 후 실행 (검색, 저장) 쓰로틀: 주기적 실행 (스크롤, 실시간 업데이트) 성능 최적화: 적절한 딜레이 설정과 메모리 관리 실전 적용: 프로젝트 특성에 맞는 패턴 선택

July 9, 2025 · 4 min · Haeun

쓰로틀(Throttle) 완벽 가이드 - 스크롤/이벤트 최적화의 핵심

쓰로틀(Throttle) 완벽 가이드 - 스크롤/이벤트 최적화의 핵심 안녕하세요! 개발에서 자주 쓰이는 쓰로틀(Throttle) 패턴에 대해 알아보겠습니다. 쓰로틀이란? 쓰로틀은 짧은 시간 간격으로 연속해서 발생하는 이벤트를 일정 시간마다 한 번씩만 실행되도록 제한하는 기법입니다. 언제 사용할까? 스크롤 이벤트 최적화 (무한 스크롤, 고정 헤더 등) 윈도우 리사이즈 이벤트 최적화 마우스 이동, 드래그 등 고빈도 이벤트 처리 동작 원리 이벤트가 발생하면, 지정한 시간(delay) 동안 추가 이벤트를 무시합니다. delay가 지난 후 다시 이벤트가 발생하면 콜백이 실행됩니다. 이 과정을 반복하여, 최대 1초에 한 번 등으로 호출 빈도를 제한할 수 있습니다. 실전 예제: 스크롤 이벤트 최적화 <div class="container" style="width:300px;height:300px;overflow:scroll;background:#eee;"> <div style="height:1000px;"></div> </div> <div>일반 이벤트 핸들러 호출 횟수: <span id="normal-count">0</span></div> <div>쓰로틀 이벤트 핸들러 호출 횟수: <span id="throttle-count">0</span></div> <script> const container = document.querySelector('.container'); const normalCount = document.getElementById('normal-count'); const throttleCount = document.getElementById('throttle-count'); // 쓰로틀 함수 구현 function throttle(callback, delay) { let waiting = false; return function (...args) { if (!waiting) { callback.apply(this, args); waiting = true; setTimeout(() => { waiting = false; }, delay); } }; } let normal = 0; let throttled = 0; // 일반 이벤트 (매번 실행) container.addEventListener('scroll', () => { normalCount.textContent = ++normal; }); // 쓰로틀 적용 (최대 1초에 한 번만 실행) container.addEventListener('scroll', throttle(() => { throttleCount.textContent = ++throttled; }, 1000)); </script> 설명: ...

July 6, 2025 · 2 min · Haeun

JavaScript 타이머 완벽 가이드 - setTimeout, setInterval 마스터하기

JavaScript 타이머 완벽 가이드 - setTimeout, setInterval 마스터하기 안녕하세요! JavaScript의 핵심 기능 중 하나인 타이머 함수들에 대해 자세히 알아보겠습니다. 웹 개발에서 타이머는 애니메이션, 자동 저장, 폴링, 지연 실행 등 다양한 용도로 사용되는 필수적인 기능입니다. 이 포스팅에서는 setTimeout, setInterval의 기본 개념부터 실전 활용까지 체계적으로 정리해보겠습니다! 호출 스케줄링이란? 기본 개념 **호출 스케줄링(Call Scheduling)**은 함수를 명시적으로 호출하지 않고, 일정 시간이 경과된 후에 자동으로 실행되도록 예약하는 것을 말합니다. 일반적인 함수 호출 vs 스케줄링 // 일반적인 함수 호출 (즉시 실행) function add(a, b) { return a + b; } console.log(add(2, 5)); // 즉시 실행: 7 // 스케줄링된 함수 호출 (지연 실행) setTimeout(() => { console.log(add(2, 5)); // 1초 후 실행: 7 }, 1000); 만약 함수를 명시적으로 호출하지 않고 일정 시간이 경과된 이후에 호출되도록 함수 호출을 예약하려면, 타이머 함수를 사용해야 합니다. ...

December 19, 2024 · 8 min · Haeun