프로그래밍에서 지연 평가(Lazy Evaluation)는 계산을 미루는 기법으로, 데이터가 실제로 필요할 때 계산을 수행하는 방식을 의미합니다. 함수형 프로그래밍에서 자주 사용되는 이 개념은 메모리 사용을 최적화하고, 불필요한 계산을 줄이는 데 매우 유용합니다.
이번 글에서는 자바스크립트에서 지연 평가를 구현하는 방법에 대해 알아보겠습니다.
1. 지연 평가란?
지연 평가는 값이 필요할 때까지 계산을 미루는 전략입니다.
즉, 어떤 표현식이나 함수 호출의 결과를 바로 계산하지 않고, 실제로 사용될 때 계산을 수행합니다.
동작 방식
- 즉시 평가(Eager Evaluation): 표현식을 만나면 바로 계산합니다.
- 지연 평가(Lazy Evaluation): 표현식을 만나도 계산을 미루고, 필요할 때 계산합니다.
// 즉시 평가
const eagerValue = 2 + 3; // 바로 계산되어 5가 할당됩니다.
// 지연 평가
const lazyValue = () => 2 + 3; // 계산을 함수로 감싸서 필요할 때 실행됩니다.
console.log(lazyValue()); // 실제로 호출할 때 계산됩니다.
장점
- 성능 최적화: 필요한 데이터만 계산하므로 불필요한 작업을 줄임. 대규모 데이터 처리나 무한 시퀀스와 같은 경우에 효과적.
- 무한 데이터 처리: 무한 시퀀스와 같은 데이터 구조를 처리 가능.
- 메모리 효율성: 데이터 전체를 메모리에 로드하지 않고 필요한 만큼만 계산.
단점
- 디버깅의 어려움: 계산이 미뤄지기 때문에 디버깅이 복잡해질 수 있음.
- 복잡한 구현: 즉시 평가보다 구현이 복잡할 수 있음.
- 의도하지 않은 계산 지연: 지연 평가를 잘못 사용하면 오히려 성능 문제가 발생할 수 있음.
2. 자바스크립트에서의 지연 평가
자바스크립트는 기본적으로 즉시 평가를 사용하지만, 지연 평가를 구현할 수 있는 몇 가지 방법을 제공합니다.
2.1 함수로 지연 평가 구현
가장 간단한 방법은 계산을 함수로 감싸는 것입니다.
const lazyValue = () => {
console.log('계산 중...');
return 2 + 3;
};
console.log('계산 전');
console.log(lazyValue()); // 실제로 호출할 때 계산
console.log('계산 완료');
출력
계산 전
계산 중...
5
계산 완료
2.2 제너레이터를 활용한 지연 평가
자바스크립트의 제너레이터(Generator)는 지연 평가를 구현하는 강력한 도구입니다.
제너레이터는 값을 필요할 때마다 생성하므로, 계산을 미룰 수 있습니다.
예제: 제너레이터로 무한 시퀀스 생성
function* infiniteSequence() {
let i = 0;
while (true) {
yield i++; // 값을 반환하고, 다음 호출까지 계산을 멈춤
}
}
const sequence = infiniteSequence();
console.log(sequence.next().value); // 0
console.log(sequence.next().value); // 1
console.log(sequence.next().value); // 2
위 코드에서 infiniteSequence는 무한한 숫자 시퀀스를 생성하지만, 실제로 사용된 값만 계산합니다.
2.3 Iterable과 Lazy Mapping
지연 평가를 활용하여 배열과 같은 데이터 구조를 효율적으로 처리할 수도 있습니다.
예제: 제너레이터로 Lazy Mapping 구현
function* lazyMap(arr, fn) {
for (const item of arr) {
yield fn(item); // 각 아이템에 함수를 적용하고 결과를 반환
}
}
const numbers = [1, 2, 3, 4, 5];
const lazyMapped = lazyMap(numbers, x => x * 2);
console.log([...lazyMapped]); // [2, 4, 6, 8, 10]
2.4 Lodash의 Lazy Evaluation
Lodash 라이브러리는 지연 평가를 기본적으로 지원합니다.
특히, _.chain을 사용하면 지연 평가를 통해 효율적인 데이터 처리가 가능합니다.
예제: Lodash로 Lazy Evaluation
const _ = require('lodash');
const result = _.chain([1, 2, 3, 4])
.map(x => x * 2) // 모든 요소에 2를 곱함
.filter(x => x > 4) // 4보다 큰 값만 필터링
.value(); // 최종 계산 실행
console.log(result); // [6, 8]
3. 예제
무한 피보나치 수열 생성
지연 평가를 사용하면 무한 피보나치 수열을 쉽게 생성할 수 있습니다.
function* fibonacci() {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
const fib = fibonacci();
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
console.log(fib.next().value); // 3
console.log(fib.next().value); // 5
대규모 데이터 처리
지연 평가를 사용하여 대규모 데이터를 효율적으로 처리할 수 있습니다.
function* largeDataProcessor(data) {
for (const item of data) {
if (item % 2 === 0) {
yield item * 2; // 짝수만 두 배로 변환
}
}
}
const largeData = Array.from({ length: 1_000_000 }, (_, i) => i);
const processed = largeDataProcessor(largeData);
console.log([...processed].slice(0, 10)); // 첫 10개의 결과만 확인
'JavaScript' 카테고리의 다른 글
[JavaScript] Jest로 유닛 테스트 작성하기 (1) | 2025.01.19 |
---|---|
[JavaScript] 모나드(Monad) (0) | 2025.01.09 |
[JavaScript] 순수 함수(Pure Function) (0) | 2025.01.03 |
[JavaScript] 커링(Currying) (2) | 2024.12.28 |
[JavaScript] 프로토타입으로 상속하기 (0) | 2024.12.25 |