TypeScript 5.6의 Iterator Helper 실전 적용기

배경

대용량 로그 데이터를 처리하는 API에서 메모리 사용량이 문제였다. 수십만 건의 레코드를 필터링하고 변환하는 과정에서 중간 배열들이 계속 생성되었고, 이를 개선할 방법을 찾다가 TypeScript 5.6의 Iterator Helper를 알게 되었다.

기존 코드

const result = logs
  .filter(log => log.level === 'ERROR')
  .map(log => parseLog(log))
  .slice(0, 100);

이 코드는 동작은 하지만, 각 단계마다 새 배열을 생성한다. 100개만 필요한데 전체를 처리하는 것도 비효율적이었다.

Iterator Helper 적용

const result = logs.values()
  .filter(log => log.level === 'ERROR')
  .map(log => parseLog(log))
  .take(100)
  .toArray();

Iterator Helper는 lazy evaluation을 지원한다. toArray()를 호출하기 전까지 실제 연산이 일어나지 않으며, take(100) 덕분에 필요한 만큼만 처리한다.

성능 비교

100만 건 데이터 기준:

  • 기존: ~850ms, 메모리 spike 발생
  • 개선: ~120ms, 메모리 사용량 안정적

특히 early termination이 가능한 경우 차이가 극명했다.

주의점

Iterator Helper는 아직 모든 환경에서 지원되지 않는다. lib 설정에 esnext를 추가하고, 런타임 polyfill이 필요할 수 있다. 우리 프로젝트는 Node 22를 사용해서 네이티브 지원을 받을 수 있었다.

배열이 작거나 전체를 순회해야 하는 경우엔 기존 방식이 더 나을 수 있다. 성능 프로파일링 후 적용하는게 맞다.

결론

Iterator Helper는 함수형 스타일을 유지하면서도 성능을 개선할 수 있는 좋은 도구다. 대용량 데이터 처리나 early termination이 필요한 경우 고려해볼 만하다.