Java 함수형 프로그래밍 패러다임 이해 완벽 정리
Java 8 이후 Java 개발 스타일이 크게 바뀌면서 자주 등장하기 시작한 개념이 바로:
함수형 프로그래밍(Function Programming)
입니다.
특히:
- Lambda
- Stream API
- Optional
- Method Reference
- CompletableFuture
전부 함수형 프로그래밍 철학과 연결됩니다.
많은 개발자가:
“람다 쓰면 함수형 프로그래밍인가?”
정도로 이해하지만,
실제로 함수형 프로그래밍은:
- 상태 변경 최소화
- 불변성(Immutability)
- Side Effect 제거
- Pure Function
- 선언형 프로그래밍
까지 연결되는 매우 큰 패러다임입니다.
이번 글에서는:
- 함수형 프로그래밍이란?
- 왜 등장했는가
- Pure Function
- Side Effect
- 불변성(Immutability)
- 선언형 프로그래밍
- Stream 철학
- Java에서의 현실적 함수형 스타일
까지 깊게 정리해보겠습니다.
1. 함수형 프로그래밍이란?
Functional programming 은:
“함수 중심으로 프로그램을 구성하는 패러다임”
입니다.
2. 핵심 철학
매우 중요.
상태 변경 최소화
+
함수를 조합해서 문제 해결
입니다.
3. 기존 Java 스타일
전통 Java는 기본적으로:
객체지향(OOP)
중심.
즉:
- 객체 상태 변경
- mutable 객체
- setter
- side effect
가 흔함.
4. 예시
user.setName("Kim");
↓
객체 상태 변경
5. 함수형 스타일은 다름
핵심:
기존 상태 변경 최소화
입니다.
6. 예시
User updated =
user.withName("Kim");
즉:
새 객체 생성
선호.
7. 왜 이런 철학이 중요할까?
상태 변경이 많을수록:
- 버그 증가
- 동시성 문제
- 디버깅 어려움
발생 가능.
8. 함수형 프로그래밍 핵심 요소
대표:
| Pure Function | 순수 함수 |
| Immutability | 불변성 |
| Side Effect 최소화 | 부작용 제거 |
| Declarative Style | 선언형 프로그래밍 |
9. Pure Function이란?
매우 중요합니다.
10. 의미
Pure function 은:
같은 입력이면 항상 같은 출력 반환
- 외부 상태 변경 없음
입니다.
11. 예시
int add(int a, int b) {
return a + b;
}
12. 특징
| 입력 동일 → 결과 동일 | O |
| 외부 상태 변경 | X |
즉 순수 함수.
13. 반대로 순수 함수가 아닌 예
int count = 0;
int increase() {
return ++count;
}
14. 왜 문제일까?
결과가:
외부 상태(count)
에 의존.
즉 예측 어려움 증가.
15. Side Effect(부작용)란?
매우 중요.
16. 의미
Side effect 는:
함수 실행이 외부 상태에 영향을 주는 것
입니다.
17. 대표적인 Side Effect
| 전역 변수 수정 | 상태 변경 |
| 파일 저장 | 외부 시스템 변경 |
| DB 저장 | 외부 영향 |
| 로그 출력 | 외부 IO |
18. 함수형 프로그래밍은 왜 Side Effect를 싫어할까?
핵심 이유:
예측 가능성 감소
입니다.
19. 상태 변경이 많으면
대표 문제:
- 디버깅 어려움
- Race Condition
- 동시성 문제
- 테스트 어려움
20. 그래서 등장한 불변성(Immutability)
매우 중요.
21. 의미
Immutable object 는:
생성 후 상태 변경 불가능
입니다.
22. 예시
String s = "Java";
String은 immutable.
23. 변경 시 실제론?
s = s + "8";
↓
새 객체 생성
입니다.
24. 왜 immutable이 중요할까?
장점:
| Thread-safe 유리 | O |
| 예측 가능 | O |
| Side Effect 감소 | O |
| 디버깅 쉬움 | O |
25. 함수형 프로그래밍과 Stream
Java Stream은 사실상:
함수형 프로그래밍 스타일 API
입니다.
26. 예시
list.stream()
.filter(x -> x > 10)
.map(x -> x * 2)
.toList();
27. 특징
핵심:
원본 수정 없이
새 결과 생성
입니다.
28. 선언형 프로그래밍(Declarative Programming)
매우 중요.
29. 기존 방식 (명령형)
for (int i = 0; i < list.size(); i++) {
if (list.get(i) > 10) {
}
}
30. 특징
“어떻게(how)”
중심.
31. Stream 방식 (선언형)
list.stream()
.filter(x -> x > 10)
32. 특징
“무엇을(what)”
중심.
33. 왜 중요할까?
코드가:
- 짧아짐
- 의도 명확
- 조합 쉬움
34. Higher-Order Function
함수형 프로그래밍 핵심 개념.
35. 의미
Higher-order function 는:
함수를 인자로 받거나 반환하는 함수
입니다.
36. Java 예시
list.stream()
.map(x -> x * 2)
여기서:
x -> x * 2
함수를 전달.
37. Lambda가 중요한 이유
람다가 없으면:
함수 전달 자체가 어려움
38. Optional도 함수형 스타일
예:
optional
.map(User::getName)
.orElse("Unknown");
39. 특징
null 체크 제거
+
함수 체이닝
40. CompletableFuture도 동일
future.thenApply(x -> x * 2)
↓
비동기 함수 체이닝
41. Java는 완전 함수형 언어일까?
매우 중요.
정답:
아님
42. Java는 기본적으로 OOP 언어
즉:
- mutable 객체 많음
- side effect 흔함
- 상태 기반 객체 많음
43. Java의 함수형 프로그래밍은
정확히는:
함수형 스타일 지원
에 가까움.
44. 실무에서 현실적인 함수형 스타일
대표:
- Stream 사용
- immutable 객체 선호
- Optional 활용
- side effect 최소화
45. 그런데 함수형 스타일도 과하면 문제
매우 중요.
46. 안 좋은 예
users.stream()
.filter(...)
.map(...)
.flatMap(...)
.collect(...)
너무 길어지면:
가독성 폭망
가능.
47. 실무에서는 균형 중요
즉:
함수형 스타일
+
가독성
+
디버깅 편의성
균형 필요.
48. Side Effect 주의
매우 중요.
49. 안 좋은 예
List<Integer> result =
new ArrayList<>();
list.stream()
.forEach(result::add);
50. 왜 문제일까?
외부 상태 변경 발생.
특히 병렬 Stream에서 위험.
51. 더 함수형스러운 방식
List<Integer> result =
list.stream()
.toList();
52. 함수형 프로그래밍 장점
| 예측 가능성 증가 | O |
| 테스트 쉬움 | O |
| 병렬 처리 유리 | O |
| Side Effect 감소 | O |
53. 단점도 존재
| 디버깅 어려움 | O |
| 과도한 체이닝 | 가독성 저하 |
| 객체 생성 증가 | 성능 비용 가능 |
54. 실무에서 자주 하는 실수
1) 함수형 = Stream 남발
오히려 읽기 어려워짐.
2) side effect 무시
외부 상태 변경 발생.
3) immutable 개념 부족
mutable 객체 그대로 사용.
4) 함수형 스타일을 무조건 정답처럼 사용
상황 따라 imperative가 더 좋을 수 있음.
55. 핵심 흐름 요약
상태 변경 최소화
↓
Pure Function
↓
Immutable 객체
↓
함수 조합
↓
선언형 데이터 처리
56. 가장 중요한 핵심 한 줄
함수형 프로그래밍은
“상태 변경과 부작용을 최소화하며 함수를 조합해 문제를 해결하는 방식”
입니다.
57. 정리
Java의 함수형 프로그래밍은 단순 Lambda 문법이 아닙니다.
실제로는:
- Stream API
- Optional
- Immutable 객체
- Side Effect 제거
- Declarative Programming
전체와 연결되는 Java 8 이후 핵심 패러다임입니다.
특히 실무에서는:
- Pure Function
- 불변성
- side effect 최소화
- Stream 가독성
- 함수형 스타일 균형
을 정확히 이해하는 것이 매우 중요합니다.
다음 글에서는:
Exception 구조
를 Throwable, Error, Exception, RuntimeException 계층 구조와 JVM 예외 처리 메커니즘까지 포함해서 깊게 정리해보겠습니다.
'language > java' 카테고리의 다른 글
| Java Checked vs Unchecked Exception 완벽 이해하기 (0) | 2026.05.28 |
|---|---|
| Java Exception 구조 완벽 이해하기 (0) | 2026.05.28 |
| Java Optional 남용 문제 완벽 이해하기 (0) | 2026.05.28 |
| Java Optional<T> 사용법 완벽 이해하기 (0) | 2026.05.28 |
| Java Collector 활용 완벽 이해하기 (0) | 2026.05.28 |
댓글