kotlin

Kotlin의 Sequence는 무엇이고, 왜 써야 할까요?

curiousKidd 2025. 5. 28. 14:16
반응형

코틀린으로 개발을 하다 보면 Sequence라는 타입을 종종 만나게 됩니다.

처음에는 익숙한 List나 Stream만 써도 충분한데, 갑자기 등장한 이 친구는 도대체 어떤 역할을 할까요? 그리고 왜 사용하는 걸까요?

이 글에서는 Sequence의 개념부터, Stream과의 차이점, 실제로 왜 속도가 빨라지는지도 함께 정리해보겠습니다.

Sequence란?

간단히 말하면 Sequence는 "지연 계산(Lazy Evaluation)을 지원하는 컬렉션 처리 방식"입니다. 일반적인 리스트 연산은 **즉시 계산(Eager Evaluation)**을 하는 반면, Sequence는 계산을 나중으로 미루는 특성이 있습니다.

val list = listOf(1, 2, 3, 4, 5)
val result = list
    .map { it * 2 }     // 즉시 처리
    .filter { it > 5 }  // 즉시 처리
    .toList()

이 코드는 리스트를 순회하면서 map, filter가 각각 한 번씩 수행됩니다. 즉, 중간 리스트가 만들어지는 것이죠.

val result = sequenceOf(1, 2, 3, 4, 5)
    .map { it * 2 }      // 아직 실행 안 됨
    .filter { it > 5 }   // 아직 실행 안 됨
    .toList()            // 여기서 한 번에 실행됨

위 코드는 toList()를 호출할 때까지 실제로 아무 연산도 수행하지 않습니다. 필요할 때만 계산이 일어나는 것이 Sequence의 가장 큰 특징입니다.


Stream과 Sequence의 차이점

항목 Kotlin Sequence Java Stream

언어 지원 Kotlin 표준 Java 8 이상
중간 연산 처리 Lazy (지연 처리) Lazy (지연 처리)
병렬 처리 ❌ 기본 미지원 ✅ 병렬 스트림 지원
단방향/재사용 재사용 가능 일회용 (한 번만 순회)
사용 용도 간단한 성능 최적화 시 활용 대용량 데이터 처리에 적합

Sequence는 Java의 Stream과 유사하지만, 더 간단하게 재사용이 가능하고, Kotlin의 문법과 더 잘 어울립니다.


왜 Sequence가 더 빠르다고 느껴질까요?

Sequence는 중간에 생성되는 임시 리스트를 만들지 않기 때문에 메모리 효율이 좋고, 연산 수가 줄어들 수 있습니다. 특히 연산 순서가 중요한 경우, 효율 차이는 확실히 벌어집니다.

예제를 하나 보시죠.

val result = (1..1000000)
    .asSequence()
    .map { it * 2 }
    .filter { it % 3 == 0 }
    .take(5)
    .toList()

이 경우, 일반 리스트 연산이면 100만 개를 모두 순회하고 나서야 결과가 나옵니다. 하지만 Sequence는 take(5)로 인해 필요한 값만 앞에서부터 계산하고 바로 종료되죠. 성능이 빨라지는 건 당연합니다.


언제 Sequence를 써야 할까요?

  • 데이터 크기가 크고, 중간 리스트가 많이 생길 때
  • map, filter, take, find 등 체이닝이 많은 경우
  • 최종 결과가 부분 데이터만 필요할 때 (take, first 등)

반대로 데이터가 적고, 간단한 처리만 할 때는 굳이 Sequence를 쓰지 않아도 됩니다. 오히려 코드가 복잡해질 수 있어요.


마무리하며

Sequence는 성능 최적화를 위해 제공되는 Kotlin만의 강력한 기능입니다. 무조건 사용하는 게 아니라, 언제 쓰면 좋은지를 알고 잘 활용하는 것이 중요하다고 생각합니다. 리스트 연산이 많고 성능 이슈가 생겼을 때, 한 번쯤 Sequence를 고민해보셔도 좋습니다.

혹시 Java Stream에 익숙하셨다면 Kotlin의 Sequence도 큰 거부감 없이 사용할 수 있으실 거예요. 작은 코드가 큰 차이를 만들기도 하니까요!

반응형