함수형 프로그래밍(Functional Programming, FP)은 순수 함수와 불변성의 개념을 기반으로 한 프로그래밍 패러다임입니다. 이는 복잡한 시스템을 보다 간결하고 예측 가능한 코드로 만들기 위해 사용됩니다. 자바 8부터 람다 표현식과 스트림 API가 도입되면서 자바에서도 람다 표현식, 메소드 참조, 스트림 API 등을 통해 함수형 프로그래밍을 지원하기 시작했습니다. 함수형 프로그래밍은 불변성, 순수 함수, 고차 함수, 지연 연산 등의 개념을 포함하는데, 이를 통해 코드를 더욱 간결하고 표현력 있게 작성할 수 있습니다. 이 글에서는 자바를 활용한 함수형 프로그래밍의 기본 개념과 이점, 그리고 적용 방법에 대해 살펴보겠습니다.
함수형 프로그래밍이란?
함수형 프로그래밍은 “함수”를 일급 객체로 취급하는 프로그래밍 패러다임입니다. 이는 프로그램의 상태 변경이나 가변 데이터를 피하고, 데이터 처리를 수학적 함수의 계산으로 취급하여 부작용(Side-effect)을 최소화하는 것을 목표로 합니다.
자바에서의 함수형 프로그래밍의 특징
- 람다 표현식(Lambda Expressions): 자바에서는 이름 없는 함수(익명 함수)를 간결하게 표현할 수 있는 람다 표현식을 제공합니다.
- 스트림 API(Stream API): 컬렉션을 선언적으로 처리할 수 있게 해주는 스트림 API를 통해 데이터를 효율적으로 처리할 수 있습니다.
- Optional 클래스: null 값으로 인한 오류를 방지하기 위해 Optional 클래스를 사용하여 값의 존재나 부재를 더 명확하게 표현할 수 있습니다.
- 메소드 참조(Method References): 메소드 참조를 통해 메소드를 더 간결하게 참조할 수 있습니다.
함수형 프로그래밍의 이점
- 가독성의 향상: 람다 표현식과 메소드 참조를 통해 코드의 양을 줄이고, 의도를 명확하게 표현할 수 있습니다.
- 병렬 처리 용이: 스트림 API를 활용하여 데이터의 병렬 처리를 간편하게 구현할 수 있어 성능을 향상시킬 수 있습니다.
- 불변성에 의한 안정성: 데이터의 불변성을 유지함으로써 프로그램의 안정성과 예측 가능성을 높일 수 있습니다.
람다 표현식 예시
람다 표현식은 익명 함수를 단순한 식으로 표현할 수 있게 해줍니다. 이를 통해 코드의 가독성과 유지보수성이 향상됩니다.
1
2
3
4
5
6
7
8
9
10
|
// 기존 방식
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println(“Hello, Lambda!”);
}
};
// 람다 표현식 사용
Runnable runnable = () –> System.out.println(“Hello, Lambda!”);
|
cs |
스트림 API (Stream API)
스트림 API는 컬렉션 데이터를 함수형 스타일로 처리할 수 있게 해줍니다. 필터링, 매핑, 정렬, 그룹화 등의 작업을 간결하게 수행할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 기존 방식
List<Integer> evenNumbers = new ArrayList<>();
for (Integer number : numbers) {
if (number % 2 == 0) {
evenNumbers.add(number);
}
}
// 스트림 API 사용
List<Integer> evenNumbers = numbers.stream()
.filter(n –> n % 2 == 0)
.collect(Collectors.toList());
|
cs |
Optional 클래스 예시
1
2
3
4
5
6
|
public String getUserName(User user) {
return Optional.ofNullable(user)
.map(User::getName)
.orElse(“Default User”);
}
|
cs |
함수형 인터페이스 (Functional Interface)
함수형 인터페이스는 단일 추상 메서드를 가진 인터페이스입니다. 람다 표현식을 사용할 때 대상 타입으로 활용됩니다. 자바에는 Predicate
, Consumer
, Function
, Supplier
등의 표준 함수형 인터페이스가 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
|
// Predicate 예제
List<String> names = Arrays.asList(“John”, “Jane”, “Jack”, “Jill”);
List<String> filteredNames = names.stream()
.filter(name –> name.startsWith(“J”))
.collect(Collectors.toList());
// Consumer 예제
names.forEach(name –> System.out.println(name));
// Function 예제
Function<String, Integer> strLengthFunc = str –> str.length();
int length = strLengthFunc.apply(“Hello”);
|
cs |
함수형 프로그래밍은 불변성, 병렬 처리, 높은 모듈성 등의 장점을 가지고 있습니다. 자바에서 제공하는 람다 표현식, 스트림 API, 함수형 인터페이스를 활용하면 더욱 간결하고 표현력 있는 코드를 작성할 수 있습니다.