함수형 프로그래밍(FP)은 순수 함수(Pure Function)와 불변성(Immutability)을 기반으로 하는 선언형(Declarative) 프로그래밍 패러다임입니다.
순수 함수(Pure Function)란 입력(Input)이 같으면 항상 같은 출력(Output)을 반환하며, 부작용(Side Effect)이 없는 함수입니다.
📌 순수 함수 조건
1️⃣ 같은 입력 → 항상 같은 출력
2️⃣ 함수 외부의 상태를 변경하지 않음 (Side Effect 없음)
📌 순수 함수 예제 (Java/Kotlin)
// Java - 순수 함수
public int add(int a, int b) {
return a + b; // 같은 입력이면 항상 같은 결과 반환
}
// Kotlin - 순수 함수
fun add(a: Int, b: Int): Int = a + b
📌 같은 입력값이 들어오면 항상 동일한 결과가 나오며, 외부 변수 값을 변경하지 않음.
함수형 프로그래밍에서는 데이터를 변경하지 않고 새로운 데이터를 생성합니다.
📌 불변 데이터 예제 (Kotlin)
val numbers = listOf(1, 2, 3)
val newNumbers = numbers.map { it * 2 } // 원본 리스트는 변경되지 않음
println(newNumbers) // [2, 4, 6]
println(numbers) // [1, 2, 3] (불변)
📌 원본 리스트(numbers
)는 변경되지 않으며, 새로운 리스트(newNumbers
)가 생성됨.
고차 함수(Higher-Order Function)란 다른 함수를 매개변수로 받거나 반환하는 함수입니다.
📌 고차 함수 예제 (Kotlin)
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b) // operation 함수 실행
}
fun main() {
val sum = operate(3, 5) { x, y -> x + y }
println(sum) // 8
}
📌 함수를 인자로 전달하여 다양한 연산을 수행할 수 있음.
함수형 프로그래밍에서는 함수를 변수처럼 다룰 수 있음. 즉, 함수를 변수에 저장하거나 다른 함수의 인자로 전달 가능.
📌 일급 객체 예제 (Kotlin)
val square: (Int) -> Int = { it * it }
println(square(5)) // 25
📌 square
변수에 함수를 할당하여 실행 가능.
람다 함수(Lambda)는 익명 함수(Anonymous Function)로, 간결한 함수 표현을 제공합니다.
📌 람다 표현식 예제 (Kotlin)
val multiply = { a: Int, b: Int -> a * b }
println(multiply(4, 5)) // 20
📌 람다를 활용하면 코드가 간결해지고 가독성이 높아짐.
함수형 프로그래밍에서는 작은 함수를 조합하여 새로운 함수를 생성할 수 있습니다.
📌 함수 조합 예제 (Kotlin)
val addFive = { x: Int -> x + 5 }
val multiplyByTwo = { x: Int -> x * 2 }
val combined = addFive.andThen(multiplyByTwo)
println(combined(10)) // (10 + 5) * 2 = 30
📌 여러 개의 함수를 조합하여 새로운 기능을 쉽게 만들 수 있음.
함수형 프로그래밍은 컬렉션 데이터를 다룰 때 강력한 기능을 제공합니다.
val numbers = listOf(1, 2, 3, 4, 5)
// map: 변환
val squared = numbers.map { it * it }
println(squared) // [1, 4, 9, 16, 25]
// filter: 조건에 맞는 요소만 선택
val evens = numbers.filter { it % 2 == 0 }
println(evens) // [2, 4]
// reduce: 누적 연산
val sum = numbers.reduce { acc, num -> acc + num }
println(sum) // 15
함수형 프로그래밍은 비동기(Asynchronous) 프로그래밍에도 적합합니다.
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(1000L)
println("World!")
}
println("Hello,")
}
📌 코루틴을 사용하여 비동기 코드 실행을 간결하게 구현 가능.
✔ 코드가 간결하고 가독성이 높음
✔ 디버깅 & 유지보수가 쉬움
✔ 병렬 처리 및 멀티스레딩에 강함 (Immutable 데이터)
✔ 예측 가능성 증가 (부작용 없는 순수 함수)
❌ 학습 곡선이 있음 → OOP에 익숙한 개발자는 FP 개념이 어렵게 느껴질 수 있음
❌ 실행 속도가 OOP보다 느릴 수 있음 → Java의 mutable 방식보다 성능이 떨어질 수도 있음
❌ 메모리 사용 증가 → Immutable 데이터 사용으로 인해 새로운 객체가 계속 생성됨
비교 항목 | 객체 지향 프로그래밍(OOP) | 함수형 프로그래밍(FP) |
---|---|---|
중심 개념 | 객체(Object), 클래스(Class) | 함수(Function), 표현식(Expression) |
상태 변경 | 변경 가능 (Mutable State) | 불변성 유지 (Immutable State) |
패러다임 | 클래스, 객체, 상속 | 함수, 불변성, 순수 함수 |
코드 스타일 | 명령형 (Imperative) | 선언형 (Declarative) |
부작용 | 있음 (Side Effect 발생) | 없음 (순수 함수 사용) |
데이터 변경 | 가능 (Mutable) | 불가능 (Immutable) |
병렬 처리 | 어려움 | 쉬움 (Immutable 상태) |
가독성 | 코드 길어질 가능성 있음 | 간결하고 직관적 |
📌 OOP는 상태 중심, FP는 데이터 변환 중심!
📌 최근에는 "함수형 스타일 + 객체지향" 혼합 방식 사용이 많아짐!
📌 객체 지향 프로그래밍(OOP) → 클래스 & 객체 중심, 상태(State) 변경 발생
📌 함수형 프로그래밍(FP) → 함수 & 데이터 변환 중심, 상태 변경 최소화
✅ 함수형 프로그래밍(FP)은 "순수 함수 + 불변성"을 기반으로 선언형 코드 스타일을 제공
✅ Side Effect(부작용) 없이 안전하고 유지보수가 쉬운 코드 작성 가능
✅ 멀티스레딩, 병렬 처리, 데이터 변환에 강력한 기능 제공
✅ Java, Kotlin, Scala 등에서 활용 가능하며, 최근에는 OOP와 혼합하여 많이 사용
🚀 FP를 활용하면 더 간결하고 안정적인 코드를 작성할 수 있습니다! 🚀
추가 학습 자료