Java 8 버전부터 자바의 Stream을 지원하기 시작하였습니다. Stream이란 컬렉션에 저장되어 있는 원소들을 하나씩 돌아가면서 처리할 수 있는 패턴입니다. Stream은 람다식과 함께 다양한 편의 메서드들을 제공하여 조금 더 코드를 간결하고 아름답게 작성할 수 있게 많은 도움을 주고 있습니다. 그래서 가독성이 좋다는 이유로 for문을 대신하여 stream을 많이 사용하기도 합니다. 그러면 stream과 for문은 어떤 차이가 있을까요?
For문 이란?
이미 알고 계시겠지만 노파심에 정리하자면, for문은 안에 for( 초기화; 조건; 후처리 )의 내용을 적어서, 반복문을 만들기 위해서 사용하고 있습니다. 예시로 위의 이미지는 1부터 5까지의 숫자를 가지고 있는 리스트를 차례대로 출력을 하고 있습니다.
Java 5 버전부터는 가독성이 더 좋아진 향상된 for문을 사용할 수 있게 됩니다. 전통적인 for문은 정해진 index를 넘어가버리면 IndexOutOfBoundsException 에러가 발생하게 되지만, 향상된 for문은 Index를 직접 입력해 주는 방식이 아니기 때문에 이런 예외로부터 보다 안정적일 수 있게 됩니다.
Stream 이란?
위는 간단한 스트림을 작성한 예시입니다. 우선 (1) stream을 생성한 후에, (2) 중간 연산을 거치고(3 미만 필터링, int로 변환), (3) 최종 연산 (합 구하기)을 진행하게 됩니다.
for문으로 같은 연산을 처리했을 경우입니다. 한 눈에 봐도 stream이 더 가독성이 좋아 보입니다. 더 복잡한 연산이 들어갈 수록 그 차이는 더 심해질 것입니다.
For문 vs Stream
그럼 이제 본격적으로 두 개의 차이점을 알아보겠습니다. 우선 첫 번째로 가독성이 있는데요. 다시 한 번 위의 예시를 보겠습니다.
물론 가독성 이라는 것은 개인의 취향이 많이 반영되기 때문에 객관적인 판단은 어려울 수 있겠으나, 저 같은 경우에는 stream이 for문보다 가독성이 좋다고 여기고 있습니다. For문은 여러 연산들을 진행하다 보면, if문의 depth가 깊어져서 궁극적으로 어떤 것을 목적으로 하는 코드인지 알아보기가 어렵습니다. 그러나 Stream의 경우, 여러 연산들이 중첩된다 하여도 한눈에 알아보기 쉽게 정렬할 수 있어 더 쉽게 이해할 수 있습니다.
두 번째로는 디버깅적인 측면이 있습니다. Stream은 내부에서 연산이 일어나기 때문에 에러가 발생할 경우 어떤 부분에서 문제가 발생했는지 발견하기가 어렵습니다. 그러나 for문은 Stream에 비해서 비교적 뚜렷한 에러 메세지를 발행하기 때문에 for문이 디버깅을 하기에는 더 손쉬운 것 같습니다.
세 번째는 병렬 처리입니다. 병렬 처리를 하기 위해서 For문은 thread를 생성, thread를 관리하는 등의 복잡한 방법을 따라야 하지만 Stream은 parallelStream을 사용하면 내부적으로 처리해 주기 때문에 Stream을 사용하는 것이 비교적 쉽게 병렬 처리를 진행할 수 있습니다.
마지막으로는 빠질 수 없는 성능이 있습니다. 직접 시험해보지는 않았지만(...) 많은 자료에 따르면 의외로 Stream이 For문 보다 성능적인 측면에서는 덜 뛰어나다고 나타나 있습니다. 여러 가지 이유가 있을 수 있겠지만, for문은 Java 초기 버전부터 지원을 해왔기 때문에 성능 최적화가 완료되었고 Stream은 Java 8 버전부터 지원했기 때문에 비교적 최적화가 완료되지 않았다는 분석이 있습니다.
그러면 어떤 것을 선택해야 하는가?
Stream | For문 | |
가독성 | 비교적 좋음 | 보통 |
디버깅 | 어려움 | 비교적 쉬움 |
병렬 처리 | 간단함 | 복잡함 |
성능 | 비교적 안좋음 | 비교적 좋음 |
각각의 장단점이 뚜렷하니 상황마다 원하는 것을 선택하면 될 듯 싶습니다. 저는 평소에는 가독성을 위해 stream을 쓰지만, 성능이 중요한 기능의 경우 for문으로 변환하는 방법을 채택하고 있습니다.
'Java & Spring Boot' 카테고리의 다른 글
실전, MVC 패턴! (1) | 2022.10.01 |
---|---|
DTO와 VO의 차이를 알아보자 (0) | 2022.09.18 |
Java를 버전 별로 비교해보자 (0) | 2022.08.01 |
SOLID 원칙을 이해하기 쉽게 알아보자 (0) | 2022.06.22 |
Gradle의 여러가지 의존성 옵션 (0) | 2022.06.05 |