레이지 컬렉션(Lazy Collections)은 스위프트 2에서 도입된 특별한 메커니즘으로, 컬렉션에 대한 계산을 실제 결과에 접근할 때까지 미루는 기능을 제공합니다. 처음에 표준 컬렉션 메서드(예: map, filter)는 새로운 컬렉션의 완전히 계산된 결과를 반환했으며, 이는 대량의 배열이나 변환 체인 작업 시 불필요한 메모리 및 시간 소모로 이어질 수 있습니다.
문제는 중간 컬렉션의 과잉 생성입니다. 각 map 또는 filter 호출은 데이터의 새로운 복사본을 생성하여 여러 변환 시 프로그램의 성능을 감소시킵니다.
해결책은 .lazy 속성을 사용하여 레이지 컬렉션을 활용하는 것입니다. 스위프트는 모든 작업을 하나의 체인으로 결합하고 실제로 접근하는 요소만 계산합니다.
코드 예:
let array = Array(1...1_000_000) let result = array.lazy.filter { $0 % 2 == 0 }.map { $0 * 3 } print(result.prefix(5)) // 가장 처음 5개의 값만 계산됩니다
주요 특징:
질문 1: let b = a.lazy.map { ... }가 계산 결과를 즉시 반환하나요?
아니요, .lazy와 map/filter 메서드를 사용할 경우 데이터에 직접 접근할 때만 계산 결과가 반환됩니다(예: for-in, first, reduce를 통해).
코드 예:
let array = [1, 2, 3] let mapped = array.lazy.map { x in print("처리 중\(x)") return x * 2 } // 이 시점에서는 아무것도 출력되지 않습니다 let first = mapped.first // 여기서부터 계산이 시작되고 출력이 나타납니다
질문 2: .lazy 후에 원본 컬렉션에 새 요소를 추가하면, 이후에 결과에 접근할 때 그 요소도 처리되나요?
아니요, 레이지 컬렉션은 레이지 표현이 생성될 시점의 컬렉션 상태를 반영합니다. 이후에 추가된 요소는 고려되지 않습니다.
질문 3: 작은 컬렉션(<100 요소)에 .lazy를 사용하는 것이 효과적인가요?
아니요, 작은 컬렉션에서는 레이지 계산의 이점이 거의 보이지 않으며, 때때로 추가 오버헤드가 성능에 부정적인 영향을 미칠 수 있습니다.
프로젝트에서 모든 map/filter에 대해 무분별하게 .lazy를 사용했습니다.
장점:
단점:
긴 변환 체인이 실제로 있는 함수에서만 .lazy를 적용하여 대규모 거래 데이터베이스의 보고서를 리팩토링했습니다.
장점:
단점: