함수형 프로그래밍은 프로그래밍 패러다임중 하나로, 순수 함수와 불변성을 강조하며, 프로그램의 상태 변경을 최소화하는 것을 목표로 합니다. 함수형 프로그래밍은 수학적 함수의 개념에 기반을 두고 있으며, 이를 통해 코드의 간결성, 모듈성 및 예측 가능성을 높일 수 있습니다.
- 명령형 프로그래밍: 무엇(What)을 할 것인지 나타내기보다 어떻게(How) 할 건지를 설명하는 방식
- 절차지향 프로그래밍: 수행되어야 할 순차적인 처리 과정을 포함하는 방식 (C, C++)
- 객체지향 프로그래밍: 객체들의 집합으로 프로그램의 상호작용을 표현 (C++, Java, C#)
- 선언형 프로그래밍: 어떻게 할건지(How)를 나타내기보다 무엇(What)을 할 건지를 설명하는 방식
- 함수형 프로그래밍: 순수 함수를 조합하고 소프트웨어를 만드는 방식 (클로저, 하스켈, 리스프)
함수형 프로그래밍을 배워야 하는 이유
잠시 당신이 나무꾼이라고 가정해보자. 당신은 숲에서 가장 좋은 도끼를 가지고 있고, 그래서 가장 일 잘하는 나무꾼이다. 그런데 어느 날 누가 나타나서 나무를 자르는 새로운 패러다임인 전기톱을 알리고 다닌다. 이 사람이 무척 설득력이 있어서 당신은 사용하는 방법도 모르면서 전기톱을 사게 된다. 당신은 여태껏 했던 방식대로 시동을 걸지도 않고 전기톱으로 나무를 마구 두들겨댄다. 곧 당신은 이 새로운 전기톱은 일시적인 유행일 뿐이라고 단정하고 다시 도끼를 쓰기 시작한다. 그때 누군가 나타나서 전기톱의 시동 거는 법을 가르쳐 준다.
— 닐포드 , “함수형 사고”
함수형 프로그래밍은 프로그래밍 언어나 방식을 배우는것이 아니라 함수로 프로그래밍하는 사고를 배우는 것이다.
새로운 계산방법을 배우는 것 처럼 사고의 전환을 필요로 하며 다양한 사고방식으로 프로그래밍을 바라보면 유연한 문제해결이 가능하다.
명령형이나 객체지향 코드보다 간결하고 예측하기 쉬우며, 테스트하기가 더 쉬워진다.
유명한 책인 클린 코드(Clean Code)의 저자 Robert C.Martin은 함수형 프로그래밍을 대입문이 없는 프로그래밍이라고 정의하였다.
함수형 프로그래밍(Functional Programming)의 특징
함수형 프로그래밍(Functional Programming)은 계산을 수학적 함수의 평가로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임입니다. 부수 효과(Side Effect)를 제거할 경우 프로그램의 동작을 이해하고 예측하기 쉬워지기 때문에 부수 효과가 없는 순수 함수(Pure Function)들로만 작성됩니다.
- 부수 효과(Side Effect)란?
- 콘솔에 출력하거나 사용자의 입력을 읽는 것
- 변수를 수정하거나, 객체의 필드를 저장하는 것
- 예외를 던지거나 오류를 발생시키며 실행을 중단하는 것
- 파일에 읽고 쓰는 작업
순수 함수(Pure Function)
그리고 이러한 부수 효과(Side Effect)들을 제거한 함수들을 순수 함수(Pure Function)이라고 부르며, 함수형 프로그래밍에서 사용하는 함수는 이러한 순수 함수들이다.
- Memory or I/O의 관점에서 Side Effect가 없는 함수
- 함수의 실행이 외부에 영향을 끼치지 않는 함수
순수 함수(Pure Function)의 장점
순수 함수(Pure Function)을 이용하면 얻을 수 있는 효과는 다음과 같다.
- 함수 자체가 독립적이며 Side-Effect가 없기 때문에 Thread에 안전성을 보장받을 수 있다.
- Thread에 안정성을 보장받아 병렬 처리를 동기화 없이 진행할 수 있다.
1급 객체(First-Class Object)
그리고 1급 객체란 다음과 같은 것들이 가능한 객체를 의미한다.
- 변수나 데이터 구조 안에 담을 수 있다.
- 파라미터로 전달 할 수 있다.
- 반환값으로 사용할 수 있다.
- 할당에 사용된 이름과 무관하게 고유한 구별이 가능하다.
함수형 프로그래밍에서 함수는 1급 객체로 취급받기 때문에 위의 예제에서 본 것 처럼 함수를 파라미터로 넘기는 등의 작업이 가능한 것이다. 또한 우리가 일반적으로 알고 개발했던 함수들은 함수형 프로그래밍에서 정의하는 순수 함수들과는 다르다는 것을 인지해야 한다.
불변성(Immutable)
- 함수 외부에서 데이터를 수정하지 않음
- 함수의 계산을 수행하는 동안 변수에 할당된 값들이 절대로 변하지 않음
참조 투명성(Referential Transparency)
- 동일한 인자에 대해 항상 동일한 결과를 반환해야 한다.
- 참조 투명성을 통해 기존의 값은 변경되지 않고 유지된다.(Immutable Data)
고차 함수(High order function)
- 함수를 다루는 함수
- 함수의 인자로 함수 전달 가능
- 함수의 리턴 값으로 함수 사용 가능
익명 함수(Anonymous function)
- 이름이 없는 함수
- 람다식으로 표현되는 함수 구현
게으른 평가(Lazy evaluation)
- 코드 실행 즉시 값을 평가하는 것이 아닌 필요한 시점에 평가
명령형 프로그래밍과 함수형 프로그래밍에서 사용하는 함수는 부수효과의 유/무에 따라 차이가 있다. 그에 따라 함수가 참조에 투명한지 안한지 나뉘어 지는데, 참조에 투명하다는 것은 말 그대로 함수를 실행하여도 어떠한 상태의 변화 없이 항상 동일한 결과를 반환하여 항상 동일하게(투명하게) 실행 결과를 참조(예측)할 수 있다는 것을 의미한다.
즉, 어떤 함수 f에 어떠한 인자 x를 넣고 f를 실행하게 되면, f는 입력된 인자에만 의존하므로 항상 f(x)라는 동일한 결과를 얻는다는 것을 의미한다. 부작용을 제거하여 프로그램의 동작을 이해하고 예측을 용이하게 하는 것은 함수형 프로그래밍으로 개발하려는 핵심 동기 중 하나이다. 그리고 이러한 부분인 병렬 처리 환경에서 개발할 때 Race Condition에 대한 비용을 줄여준다. 왜냐하면 함수형 프로그래밍에서는 값의 대입이 없이 항상 동일한 실행에 대해 동일한 결과를 반환하기 때문이다.
함수형 프로그래밍의 장단점
장점
- 깔끔하고 유지보수가 용이함
- 함수 단위의 코드 재사용이 수월하다
- (코드 재사용성이 높음)
- 불변성을 지향하기 때문에 프로그램의 동작을 예측하기 쉬워진다
- 함수는 입력과 그에 대한 출력만을 책임지기 때문에 테스트가 쉽고 가독성이 좋
- 사용하는 모든 데이터가 변경 불가능(immutable)하고 함수는 부수 효과를 가지고 있지 않기 때문에 동시성과 관련된 문제를 원천적으로 차단
- 고차 함수로 인해 함수들 간의 결합, 조합이 간결해지며, 익명 함수를 사용할 수 있음
단점
- 학습 곡선: 함수형 프로그래밍은 명령형 프로그래밍과 상당히 다른 개념과 접근 방식을 사용
- 새로운 개념들, 예를 들어 순수 함수, 불변성, 고차 함수 등을 학습하는 데 시간이 걸릴 수 있음
- 추사상화 수준: 함수형 프로그래밍은 높은 수준의 추상화를 제공함 이로 인해 코드가 간결하고 모듈화되긴 하지만, 때로는 이해하기 어렵고 복잡해질 수도 있음
- 함수형 프로그래밍에 익숙하지 않은 개발자들에게는 코드 해석이 어려울 수 있음
- 성능: 함수형 프로그래밍에서는 불변성과 순수 함수를 사용하여 상태 변경을 최소화합니다. 그러나 이로 인해 메모리 사용량이 증가하거나, 가비지 컬렉션 비용이 높아질 수 있습니다. 또한, 재귀를 사용한 경우 스택 오버플로우가 발생할 수도 있음
- 함수형 프로그래밍에서는 반복이 for문이 아닌 재귀를 통해 이루어지는데 (deep copy), 재귀적 코드 스타일은 무한 루프에 빠질 수 있다
- 최적화 제한: 몇몇 최적화 기법들이 함수형 프로그래밍에서는 적용하기 어려울 수 있음
- 예를 들어, 상태 변경이 없다는 가정으로 최적화를 수행하는 것은 일부 경우에 제한적일 수 있음
- 표현력: 일부 애플리케이션에서는 명령형 프로그래밍이 더 직관적이고 표현력이 높을 수 있음
- 특히 상태 변경이 빈번하게 발생하는 경우, 함수형 프로그래밍으로 표현하기 어려운 경우가 있을 수 있음
- 순수함수를 사용하는 것은 쉬울 수 있지만 조합하는 것은 쉽지 않다
- 순수함수를 구현하기 위해서는 코드의 가독성이 좋지 않을 수 있다
참고자료
https://mangkyu.tistory.com/111