💡 함수형 프로그래밍의 개념과 장점을 이해하고 다른 프로그래밍 방식과 차이를 이해하였습니다 !
함수형 프로그래밍
- 함수형 프로그래밍은 대부분의 문제를 순수 함수로 나누어 해결하는 기법입니다.
- 작은 문제를 해결하기 위한 함수를 작성하여 가독성을 높이고 유지보수를 용이하게 해줍니다.
- 클린 코드의 저자 Robert C.Martin은 함수형 프로그래밍을 대입문이 없는 프로그래밍으로 정의하였습니다.
- 명령형 프로그래밍 기반으로 개발할 때 소프트웨어의 크기가 커짐에 따라 발생하는 스파게티 코드의 유지보수 어려움을 해결하기 위해 사용되었습니다.
- 선언형 프로그래밍의 방식입니다.
명령형 프로그래밍
- 무엇(What)을 할 것인지 나타내기보다 어떻게(How)를 할 것인지 설명하는 방식입니다.
- 아래 두 가지로 구분 됩니다.
- 절차지향 프로그래밍: 수행되어야 할 순차적인 처리 과정을 포함하는 방식으로 C, C++이 있습니다.
- 객체지향 프로그래밍: 객체들의 집합으로 프로그램의 상호작용을 표현하며 대표적으로 Java가 있습니다.
선언형 프로그래밍
- 어떻게 할 것인지(How)를 나타내기보다 무엇(What)을 할 것인지를 설명하는 방식입니다.
- 대표적으로 함수형 프로그래밍이 있으며, 원하는 결과를 묘사하는 방식으로 코드를 작성합니다.
동시성 문제 해결
- 안정적인 소프트웨어를 개발하기 위해서 다양한 동시성 문제를 해결해야 합니다.
- 데이터의 상태를 변경하는 객체지향 프로그래밍 방식으로는 동시성 문제를 해결하는 데 한계가 있으며, 함수형 프로그래밍으로 이를 해결할 수 있습니다.
- 이는 불변성과 동시성과 관련이 있습니다.
- 여러 스레드가 동일한 데이터에 접근해도 데이터가 변하지 않기 때문에 레이스 컨디션이나 데드락 같은 동시성 문제를 줄일 수 있습니다.
- 비동기 작업에서 콜백이나 프로미스 같은 패턴을 자연스럽게 구현하여 작업이 완료되면 특정 함수를 호출하도록 코딩할 수 있습니다.
불변성
- 데이터는 변경되지 않으며, 상태 변화를 피할 수 있습니다.
동시성
- 여러 작업을 동시에 처리할 수 있습니다.
레이스 컨디션
- 공유 자원에 대해 여러개의 스레드, 프로세스가 동시에 접근하는 경쟁 상태를 뜻합니다.
데드락
- 두 개 이상의 작업이 서로 상대방의 작업이 끝나기 만을 기다리는 상태를 뜻합니다.
변경 불가능한 값을 활용
- 값이 번경되는 것을 허용하면 멀티 스레드 프로그래밍이 어렵습니다.
- 값을 변경할 수 없도록 하여 프로그램의 정확성을 높여 버그의 발생 가능성을 줄입니다.
참조 투명성
- 동일한 인자에 대해 항상 동일한 결과를 반환하며, 기존의 값은 변경되지 않고 유지 됩니다.
- 부작용을 제거하여 프로그램의 동작을 이해하고 예측이 가능한 프로그래밍을 할 수 있습니다 !
일급 객체로서의 함수
- 함수가 일급 객체의 역할을 합니다.
- 함수를 함수의 인자로 받거나 함수의 반환 값으로 활용하는 것이 가능해집니다.
- 변수나 데이터 구조 안에 담을 수 있으며, 할당에 사용된 이름과 무관하게 고유한 구별이 가능합니다.
일급 객체?
- 다른 객체들이 일반적으로 적용 가능한 연산을 모두 지원하는 객체이며 아래와 같은 특징을 가집니다.
- 변수에 할당이 가능하다
- 다른 함수의 인자로 전달 받는다
- 다른 함수의 결과로서 리턴될 수 있다
fun applyOperation(x: Int, operation: (Int) -> Int): Int {
return operation(x)
}
fun main() {
val result = applyOperation(5, ::square) // square 함수를 인자로 전달
println(result) // 출력: 25
}
순수 함수(Pure Function)
- 부수효과를 제거한 함수들을 순수 함수라고 부릅니다.
- Memory, I/O 관점에서 Side Effect가 없으며, 함수의 실행이 외부에 영향을 끼치지 않습니다.
- 이는 Thread에 안전성을 보장하며 병렬 처리를 동기화 없이 진행할 수 있습니다.
fun square(x: Int): Int {
return x * x
}
fun main() {
println(square(4)) // 출력: 16
println(square(4)) // 출력: 16
}
부수효과(Side Effect)
- 부수효과란 아래와 같은 변화 혹은 변화가 발생하는 작업을 의미합니다.
- 변수의 값이 변경
- 자료 구조를 제자리에서 수정
- 객체의 필드값 설정
- 예외나 오류로 실행이 중단
- 콘솔 또는 파일 I/O 발생
함수형 메서드를 활용한 데이터 처리
- map, filter, reduce 등의 함수형 메서드를 활용하여 데이터를 처리할 수 있습니다.
fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
// 각 요소를 제곱한 새로운 리스트 생성 (map 사용)
val squares = numbers.map { it * it }
// 짝수만 필터링 (filter 사용)
val evenSquares = squares.filter { it % 2 == 0 }
// 리스트의 모든 요소의 합 계산 (reduce 사용)
val sumOfSquares = evenSquares.reduce { acc, i -> acc + i }
println(squares) // 출력: [1, 4, 9, 16, 25]
println(evenSquares) // 출력: [4, 16]
println(sumOfSquares) // 출력: 20
}
참고
https://arc.net/l/quote/uakbmzuu
https://futurecreator.github.io/2018/10/05/why-functional-programming/