프로그래밍 패러다임(Programming Paradigm)
프로그래밍 패러다임이란 코드를 어떻게 구조화 할지 정의하는 방식을 의미한다. 이러한 프로그래밍 패러다임은 그 종류가 매우 다양하나 큰 틀로 나눴을 때는 다음과 같이 두가지로 나뉜다.
1. 명령형(Imperative) 프로그래밍 : 어떻게(How) 처리할지 단계별로 기술하는 방식
- 절차지향 프로그래밍 : 수행되어야 할 순차적인 처리 과정을 포함하는 방식(C, C++)
- 객체지향 프로그래밍 : 객체들의 집합으로 프로그램의 상호작용을 표현(C++, Java, C#)
2. 선언형(Declarative) 프로그래밍 : 무엇을(What) 할지 선언하는 방식
- 함수형 프로그래밍 : 자료 처리를 수학적 함수의 계산으로 취급하는 방식(클로저, 하스켈, 리스프)
함수형 프로그래밍의 등장
전통적인 명령형 프로그래밍 방식은 어떻게 할지를 순서대로 명령문을 작성한다. 이런 방식은 어플리케이션의 구조가 커지면 서로 복잡하게 엉키며 스파게티 코드가 되어버린다. 이를 해결하기 위해 “값을 바꾸기 않고 작은 함수를 조합해서 문제를 풀자” 라는 아이디어가 등장했고 이것이 바로 함수형 프로그래밍이다.
Clean Code의 저자 Robert C.Martin은 함수형 프로그래밍을 대입문(assigment)이 없는 프로그래밍이라고 정의했다.
int x = 5; // 1. 변수 선언과 동시에 할당
x = x + 1; // 2. 대입문: x의 값을 6으로 변경
명령형 코드는 위처럼 x = x + 1 과 같은 대입문을 통해 변수에 값을 할당하고 변수의 상태를 계속 바꿔가며 로직을 전개한다.
명령형 프로그래밍과 함수형 프로그래밍 코드 비교
아래 코드는 리스트에서 짝수만 골라 제곱한 뒤, 리스트로 모으는 Java 코드이다.
[명령형 프로그래밍]
import java.util.*;
public class ImperativeDemo {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 결과를 담을 리스트를 직접 만들고
List<Integer> evensSquared = new ArrayList<>();
// 1) 반복문으로 순회
for (Integer n : numbers) {
// 2) 조건 검사
if (n % 2 == 0) {
// 3) 상태 변경 (리스트에 추가)
evensSquared.add(n * n);
}
}
// 4) 결과 출력
System.out.println(evensSquared); // [4, 16]
}
}
[함수형 프로그래밍]
import java.util.*;
import java.util.stream.*;
public class FunctionalDemo {
public static void main(String[] args) {
List<Integer> numbers = List.of(1, 2, 3, 4, 5);
// 선언형 파이프라인: What만 기술
List<Integer> evensSquared = numbers.stream()
.filter(n -> n % 2 == 0) // 짝수 걸러내기
.map(n -> n * n) // 제곱 변환
.collect(Collectors.toList()); // 새 리스트로 수집
System.out.println(evensSquared); // [4, 16]
}
}
함수형 프로그래밍의 특징
함수형 프로그래밍은 명령형 프로그래밍과 달리 다음과 같은 특징을 가지고 있다.
1. 부수효과(Side-Effect)가 발생하지 않음
부수효과란 다음과 같은 변화 또는 변화가 발생하는 작업을 의미한다.
- 변수의 값이 변경됨
- 자료 구조를 제자리에서 수정함
- 객체의 필드값을 설정함
- 예외나 오류가 발생하며 실행이 중단됨
- 콘솔 또는 파일 I/O가 발생함
함수형 프로그래밍에서는 함수 내부에서 외부 상태를 변경하지 않음
// 순수 함수 (Pure Function)
int pureIncrement(int n) {
return n + 1;
}
// 함수형 프로그래밍에서는 함수를 호출해도 외부 상태는 전혀 바뀌지 않음
명령형 프로그래밍에서는 오히려 부수효과를 당연하게 사용함
int counter = 0;
void incrementCounter() {
counter = counter + 1; // 전역 변수 counter 상태 변경 → 명령형 프로그래밍에서는 부수효과 발생
}
2. 순수 함수(Pure Function)
순수 함수란 위와 같은 부수효과가 발생하지 않는 함수를 의미하며 동일한 입력에 대해 항상 같은 출력을 보장한다. 이러한 특징 덕분에 Thread 안전성을 보장받을 수 있어 병렬 처리를 동기화 없이 진행할 수 있다.
순수 함수는 동일한 입력에 대해 항상 같은 출력을 보장하고, 함수 내부에서 외부 상태를 읽거나 쓰지 않는다.
int add(int a, int b) {
return a+b; // 입력(a, b)이 같으면, 항상 같은 결과를 반환
}
명령형 프로그래밍에서도 순수 함수를 쓸 수는 있지만 순수 함수만을 강제하지는 않음
int total = 0;
int addAndAccumulate(int x, int y) {
total += (x + y); // 외부 상태(total)를 읽고 쓰기 때문에 순수 함수가 아님
return total;
}
3. 불변 값 활용
함수형 프로그래밍에서는 한번 생성된 데이터 구조를 변경하지 않고 변경해야 할 때는 새로운 객체를 만들어서 반환한다.
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
List<Integer> appendImmutable(List<Integer> original, int value) {
List<Integer> temp = original.stream().collect(Collectors.toList());
temp.add(value);
return Collections.unmodifiableList(temp);
}
// 원본 리스트는 변경되지 않음
명령형 프로그래밍에서는 기본적으로 가변 객체를 사용해서 성능과 직관성을 얻음
import java.util.ArrayList;
import java.util.List;
void addMutable(List<Integer> list, int value) {
list.add(value); // 기존 리스트 자체가 변경됨
}
4. 1급 객체(First-Class Object)
1급 객체는 다음과 같은 것들이 가능한 객체를 의미한다.
- 변수나 데이터 구조 안에 담을 수 있다.
- 파라미터로 전달할 수 있다.
- 반환 값으로 사용할 수 있다.
- 할당에 사용된 이름과 무관하게 고유한 구별이 가능하다.
함수형 프로그래밍에서 함수는 1급 객체로 취급하기 때문에 함수를 파라미터로 넘기는 등의 작업이 가능하다.
자바에서는 java 8 부터 함수형 프로그래밍이 도입되었다. 아래에서 처럼 Function 객체를 사용하면 함수를 1급 객체로 취급하는 것이 가능하다.
import java.util.function.Function;
int applyTwice(int x, Function<Integer, Integer> f) {
return f.apply(f.apply(x));
}
Java 8 이전에는 함수형 프로그래밍을 지원하지 않아서 함수를 파라미터나 반환 값으로 사용하는 것이 불가능했다.
int add(int a, int b) {
return a + b;
}
5. 참조 투명성(Referential Transparency)
참조 투명성이란 함수를 실행하여도 어떠한 상태의 변화 없이 항상 동일한 결과를 반환하여 항상 동일하게(투명하게) 실행 결과를 참조(예측)할 수 있다는 것을 의미한다.
다시 말해 참조 투명성이란 동일한 입력(파라미터)에는 항상 같은 출력(값)을 내며 부수효과가 없는 것을 의미한다.
출처 : https://www.youtube.com/watch?v=24tL6-YKz3I https://www.youtube.com/watch?v=ii5hnSCE6No https://mangkyu.tistory.com/111 https://itstory1592.tistory.com/120 |
'Java' 카테고리의 다른 글
람다 표현식 (2) | 2025.06.15 |
---|---|
함수형 인터페이스 (3) | 2025.06.08 |
Java Collection Framework (0) | 2025.05.25 |
Enum (0) | 2025.05.11 |
Singleton 패턴 (0) | 2024.07.16 |