이미지 로딩 중...
CodeDeck AI
2025. 11. 8. · 2 Views
Optimization 기초부터 심화까지 완벽 가이드
코드 최적화의 기본 원리부터 고급 기법까지 다룹니다. 성능 측정, 알고리즘 최적화, 메모리 관리, 캐싱 전략 등 실무에서 바로 적용 가능한 최적화 기법을 학습합니다.
들어가며
이 글에서는 Optimization 기초부터 심화까지 완벽 가이드에 대해 상세히 알아보겠습니다. 총 12가지 주요 개념을 다루며, 각각의 개념에 대한 설명과 실제 코드 예제를 함께 제공합니다.
목차
- 성능_측정_기초
- 메모이제이션_패턴
- 디바운싱_구현
- 쓰로틀링_구현
- 배열_최적화_기법
- 객체_풀링_패턴
- 지연_로딩_구현
- WeakMap_캐싱
- 가상_스크롤링
- 비트_연산_최적화
- 문자열_최적화
- 이벤트_위임_패턴
1. 성능_측정_기초
개요
최적화의 첫 걸음은 정확한 성능 측정입니다. performance API를 사용하여 코드 실행 시간을 측정하는 방법을 배웁니다.
코드 예제
const start = performance.now();
// 측정할 코드
const result = heavyCalculation();
const end = performance.now();
console.log(`실행 시간: ${end - start}ms`);
설명
performance.now()로 시작과 끝 시간을 측정하여 코드 실행 시간을 밀리초 단위로 계산합니다. 최적화 전후 비교의 기준이 됩니다.
2. 메모이제이션_패턴
개요
동일한 계산을 반복하지 않도록 결과를 캐싱하는 메모이제이션 기법입니다. 재귀 함수나 복잡한 연산에 효과적입니다.
코드 예제
function memoize(fn) {
const cache = {};
return (...args) => {
const key = JSON.stringify(args);
if (key in cache) return cache[key];
return cache[key] = fn(...args);
};
}
설명
함수 실행 결과를 캐시 객체에 저장하고, 같은 인자로 호출 시 캐시된 값을 반환하여 불필요한 재계산을 방지합니다.
3. 디바운싱_구현
개요
연속된 이벤트 호출을 제어하여 마지막 호출만 실행하는 디바운싱 기법입니다. 검색창 입력이나 리사이즈 이벤트에 유용합니다.
코드 예제
function debounce(fn, delay) {
let timer;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);
};
}
설명
이벤트가 발생할 때마다 타이머를 초기화하고, 지정된 지연 시간 후에만 함수를 실행하여 불필요한 호출을 줄입니다.
4. 쓰로틀링_구현
개요
일정 시간 간격으로 함수 실행을 제한하는 쓰로틀링 기법입니다. 스크롤 이벤트 최적화에 효과적입니다.
코드 예제
function throttle(fn, limit) {
let waiting = false;
return (...args) => {
if (!waiting) {
fn(...args);
waiting = true;
setTimeout(() => waiting = false, limit);
}
};
}
설명
함수가 실행되면 대기 상태로 전환하고, 지정된 시간이 지나야 다시 실행 가능하도록 하여 호출 빈도를 제어합니다.
5. 배열_최적화_기법
개요
대용량 배열 처리 시 성능을 높이는 기법입니다. for 루프가 map/filter보다 빠르며, 조기 종료로 불필요한 반복을 줄입니다.
코드 예제
// 최적화: for + break
for (let i = 0; i < arr.length; i++) {
if (arr[i] === target) {
result = arr[i];
break; // 찾으면 즉시 종료
}
}
설명
for 루프는 함수 호출 오버헤드가 없고, break로 조기 종료가 가능하여 대용량 데이터 처리에 효율적입니다.
6. 객체_풀링_패턴
개요
객체 생성/삭제 비용을 줄이기 위해 재사용 가능한 객체 풀을 관리하는 기법입니다. 게임이나 애니메이션에 유용합니다.
코드 예제
class ObjectPool {
constructor(factory) {
this.factory = factory;
this.pool = [];
}
acquire() {
return this.pool.pop() || this.factory();
}
release(obj) { this.pool.push(obj); }
}
설명
사용 완료된 객체를 풀에 반환하고, 필요 시 풀에서 꺼내 재사용하여 가비지 컬렉션 부담을 줄입니다.
7. 지연_로딩_구현
개요
필요한 시점에만 리소스를 로드하는 지연 로딩 기법입니다. 초기 로딩 시간을 단축하고 메모리를 절약합니다.
코드 예제
class LazyLoader {
constructor(loader) {
this.loader = loader;
this.value = null;
}
get() {
if (!this.value) this.value = this.loader();
return this.value;
}
}
설명
첫 접근 시에만 loader 함수를 실행하여 값을 생성하고, 이후에는 캐시된 값을 반환합니다.
8. WeakMap_캐싱
개요
WeakMap을 사용한 메모리 효율적인 캐싱입니다. 객체가 가비지 컬렉션되면 자동으로 캐시도 제거됩니다.
코드 예제
const cache = new WeakMap();
function processData(obj) {
if (cache.has(obj)) return cache.get(obj);
const result = expensiveOperation(obj);
cache.set(obj, result);
return result;
}
설명
WeakMap은 키로 사용된 객체가 더 이상 참조되지 않으면 자동으로 엔트리를 삭제하여 메모리 누수를 방지합니다.
9. 가상_스크롤링
개요
대량의 리스트 항목 중 화면에 보이는 부분만 렌더링하는 기법입니다. DOM 노드 수를 최소화하여 성능을 향상시킵니다.
코드 예제
function getVisibleItems(items, scrollTop, itemHeight, viewportHeight) {
const start = Math.floor(scrollTop / itemHeight);
const end = Math.ceil((scrollTop + viewportHeight) / itemHeight);
return items.slice(start, end + 1);
}
설명
스크롤 위치를 기반으로 현재 화면에 보이는 항목의 인덱스 범위를 계산하여 필요한 항목만 렌더링합니다.
10. 비트_연산_최적화
개요
비트 연산자를 사용하여 산술 연산을 최적화하는 기법입니다. 정수 연산에서 매우 빠른 성능을 제공합니다.
코드 예제
// 2로 나누기: n / 2 → n >> 1
const half = num >> 1;
// 2배 곱하기: n * 2 → n << 1
const double = num << 1;
// 짝수 판별: n % 2 === 0 → (n & 1) === 0
const isEven = (num & 1) === 0;
설명
비트 시프트와 AND 연산은 CPU 레벨에서 직접 수행되어 산술 연산자보다 훨씬 빠르게 실행됩니다.
11. 문자열_최적화
개요
문자열 연결 시 성능을 높이는 기법입니다. 배열 join이 반복적인 + 연산보다 효율적입니다.
코드 예제
// 최적화 전: 느림
let str = '';
for (let i = 0; i < 1000; i++) str += i;
// 최적화 후: 빠름
const parts = [];
for (let i = 0; i < 1000; i++) parts.push(i);
const result = parts.join('');
설명
문자열은 불변이므로 + 연산마다 새 문자열이 생성됩니다. 배열에 모아서 한 번에 join하면 메모리 할당이 최소화됩니다.
12. 이벤트_위임_패턴
개요
여러 자식 요소 대신 부모 요소에 하나의 이벤트 리스너를 등록하는 기법입니다. 메모리와 성능을 크게 개선합니다.
코드 예제
// 최적화: 부모에 하나만 등록
parent.addEventListener('click', (e) => {
if (e.target.matches('.item')) {
handleClick(e.target);
}
});
설명
이벤트 버블링을 활용하여 부모에서 이벤트를 처리하므로, 자식 요소가 동적으로 추가/삭제되어도 별도 리스너 관리가 불필요합니다.
마치며
이번 글에서는 Optimization 기초부터 심화까지 완벽 가이드에 대해 알아보았습니다. 총 12가지 개념을 다루었으며, 각각의 사용법과 예제를 살펴보았습니다.
관련 태그
#JavaScript #Performance #Optimization #Memoization #Caching