IT정보/프로그래밍 가이드

Java Stream 장단점과 사용법 쉽게 이해하기

IdeaBin 2025. 1. 8. 23:42
반응형

Java에서 Stream은 데이터 처리와 컬렉션 조작을 간단하고 효율적으로 할 수 있게 도와주는 도구입니다. 이번 시간에도 쉽게 이해할 수 있도록 Stream의 장단점을 예제와 함께 설명하겠습니다.


Stream이란 무엇인가요?

Stream은 Java 8에서 도입된 기능으로, 데이터 소스를 효율적으로 처리할 수 있는 API입니다. 컬렉션(Collection) 또는 배열(Array)과 같은 데이터를 반복, 필터링, 정렬, 변환 등의 작업을 할 때 사용됩니다.

Stream의 장점

1. 간결한 코드

Stream을 사용하면 데이터 처리 코드를 간결하고 직관적으로 작성할 수 있습니다.

예제

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
List<String> filteredNames = names.stream()
                                  .filter(name -> name.startsWith("A"))
                                  .collect(Collectors.toList());
System.out.println(filteredNames); // 출력: [Alice]

위 코드는 filter를 사용해 이름이 "A"로 시작하는 데이터를 간단히 추출합니다.


2. 병렬 처리 가능

Stream은 데이터 처리 작업을 병렬(Parallel)로 수행할 수 있어 성능을 높일 수 있습니다.

예제

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int sum = numbers.parallelStream()
                 .mapToInt(Integer::intValue)
                 .sum();
System.out.println("합계: " + sum); // 출력: 합계: 55

parallelStream은 데이터를 여러 스레드에서 동시에 처리하여 더 빠르게 결과를 얻습니다.

3. 중간 연산과 최종 연산 분리

Stream은 데이터를 처리하는 단계(중간 연산)와 결과를 반환하는 단계(최종 연산)가 분리되어 있어 작업을 더 효율적으로 구성할 수 있습니다.

예제

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
names.stream()
     .filter(name -> name.length() > 3) // 중간 연산
     .map(String::toUpperCase)          // 중간 연산
     .forEach(System.out::println);     // 최종 연산
// 출력: ALICE, CHARLIE, DAVID

 


Stream의 단점

1. 디버깅이 어려움

Stream의 메서드 체인은 가독성을 높이지만, 디버깅이 어려울 수 있습니다. 각 단계의 중간 결과를 확인하려면 추가적인 작업이 필요합니다.

예제 - 디버깅 보완

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
       .peek(n -> System.out.println("처리 전: " + n))
       .map(n -> n * 2)
       .peek(n -> System.out.println("처리 후: " + n))
       .collect(Collectors.toList());

 


2. 초기 학습 비용

Stream은 함수형 프로그래밍 개념이 포함되어 있어 초보자가 처음 배우기에 다소 어렵게 느껴질 수 있습니다.

3. 모든 상황에 적합하지 않음

Stream은 컬렉션의 데이터를 한 번만 처리하도록 설계되었기 때문에, 데이터를 반복해서 사용해야 하는 경우 적합하지 않을 수 있습니다.

예제

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = numbers.stream();
stream.forEach(System.out::println); // 첫 번째 사용: 정상 실행
stream.forEach(System.out::println); // 두 번째 사용: 예외 발생

Stream은 한 번 소비되면 다시 사용할 수 없습니다.

Stream을 사용해야 할 때와 사용하지 말아야 할 때

Stream을 사용해야 할 때

  • 데이터를 한 번만 처리하거나 필터링할 때.
  • 간결하고 읽기 쉬운 코드를 작성하고 싶을 때.
  • 병렬 처리를 통해 성능을 높이고 싶을 때.

Stream을 사용하지 말아야 할 때

  • 데이터를 여러 번 반복해서 사용해야 할 때.
  • 디버깅이 중요한 작업일 때.


Stream 활용 팁과 주의사항

Stream 활용 팁

  1. 메서드 체인을 활용하라
    • 여러 작업을 간단히 연결하여 코드를 깔끔하게 작성할 수 있습니다.
  2. 병렬 스트림은 신중히 사용하라
    • 병렬 스트림은 처리 속도를 높일 수 있지만, 환경에 따라 오히려 성능이 저하될 수 있습니다.

Stream 사용 시 주의사항

  • 컬렉션의 데이터가 변경되면 Stream 결과가 예상치 못할 수 있으므로 데이터 변경 작업은 피하세요.
  • 대규모 데이터 세트에서는 Stream 성능을 모니터링하세요.

Stream의 흐름

 

데이터 소스 → 중간 연산 → 중간 연산 → 최종 연산 → 결과
[컬렉션]     [필터링]   [매핑]     [수집/출력]   [리스트, 출력 등]

 

Java의 Stream은 데이터를 간결하고 효율적으로 처리할 수 있는 강력한 도구입니다. 장점과 단점을 이해하고 적절한 상황에서 사용하면 더 생산적인 개발을 할 수 있습니다. 예제 코드를 직접 실행해 보면서 Stream의 강점을 확인해 보세요.

추가로 자세한 내용을 알고 싶다면 Java Stream 공식 문서를 참고하세요.

반응형