개요
- 기존 객체 지향 프로그래밍에서 가지는 문제를 해결하는 대안으로 함수형 프로그래밍이 주목받고 있다.
- 함수의 비일관성: 객체의 멤버 변수가 변경될 경우 함수(메소드)가 다른 결과를 반환할 수 있다.
- 객체간 의존성 문제: 객체 간 상호작용을 위해서 다른 객체의 함수들을 호출하게 되고, 이는 자연스럽게 프로그램 복잡도를 증가시킨다.
- 객체 내 상태 제어의 어려움: 외부에서 객체의 상태를 변경하는 메소드들이 호출되면, 언제 어디서 객체의 상태를 변경했는지 추적이 어렵다.
- 함수형(Functional) 프로그래밍은 외부 상태를 갖지 않는 함수들의 연속으로 프로그래밍을 하는 패러다임이다.
- 외부 상태를 갖지 않는다는 의미는, 같은 입력을 넣었을 때 언제나 같은 출력을 내보낸다는 것이다.
- 즉 함수의 입/출력에 영향을 주는 외부 요인이 없다.
- 함수형 프로그래밍 코드에서는 한 번 초기화한 변수는 변하지 않는다.
- 이런 특성을 불변성이라고 하는데, 이 불변성을 통해 안정성을 얻을 수 있다.
기본 개념
- 함수형 프로그래밍에서는 함수가 외부 상태를 갖지 않는다는 것이 중요하다.
- 예를 들면 다음은 함수형 프로그래밍에서 이야기하는 순수 함수가 아니다.
1 |
|
- 반면 다음은 순수 함수라고 볼 수 있다.
1 |
|
- 수학에서
f(x) = y
라는 함수f
가 있을 때,f
에x
를 입력으로 주면 항상y
라는 출력을 얻는다. - 이처럼 함수형 프로그래밍은 같은 입력을 주었을 때 항상 같은 값을 출력하도록 상태를 갖지 않는 것이다.
- 그렇다면 왜 외부 상태를 가지지 않으려고 할까?
- 일반적으로 통제하지 못하는 외부 상태를 사용한다면 예측하지 못한 결과를 가질 수 있기 때문이다.
- 예를 들어 다음과 같이 상태를 가지는
Calculator
클래스가 있다.
1 |
|
- 위 코드에서
run()
메서드 실행 시 매번 같은 값이 나오리라는 보장은 없다.
1 |
|
- 이렇게 매번 상태를 가지면, 같은 함수를 실행하더라도 실제로 내가 의도하는 결과가 나오는 지 완전히 단언하기 어렵다.
- 위 코드처럼 상태는 어디서든 바뀔 가능성이 있기 때문이다.
- 보통 이런 현상을 “사이트 이펙트”라고 한다.
- 객체 지향 언어들도 이런 상태가 존재함으로써 생기는 문제를 알고 있어 접근 제어자(private, protected)와 같은 기능들을 제공하지만, 완벽한 해법은 아니다.
예시
- 함수형 프로그래밍은 보통 다음과 같은 순서로 문제를 해결하게 된다.
- 문제를 잘개 쪼갠다.
- 쪼개진 문제들 중 하나를 해결하는 순수 함수를 만든다.
- 순수 함수들을 결합하여 문제들을 해결해 나간다.
- 보통 함수형 프로그래밍에서는 함수를 조합하는 방식으로
Pipelining
,Partial Application
,Currying
등이 있다.
1 |
|
- 프로그래밍 언어 중에서는 대표적으로 ‘스칼라(Scala)’가 이런 함수형 프로그래밍을 따르는 언어이며 다른 프로그래밍 언어에서도 특정 API를 사용하면 함수형 프로그래밍이 가능하다.
장단점
- 함수형 프로그래밍은 상태로 인한 사이드 이펙트가 없기 때문에 안정적이다.
- 따라서 동시성을 가지는 프로그램에 사용하기 적합하다.
- 특히 대용량 데이터를 병렬적으로 처리할 때 이렇게 사이드 이펙트가 없도록 로직을 설계하는 것은 매우 중요한데, 최근 데이터 처리기술의 발전으로 함수형 프로그래밍이 부상되었다.
- 하지만 실제로 함수형 프로그래밍을 하기 위해선, 상태를 허용하지 않기에 기존 객체 지향과 같은 기능의 코드를 구현하려면 다양한 함수들을 조합해서 사용해야 한다.
- 그리고 친숙하지 않은 설계 방식으로 인해 러닝 커브가 높다.
정리
- 프로그래밍 패러다임이란 프로그래밍을 어떤 기준으로 바라보고 작성할 것인지에 대한 관점이다.
- 절차지향 프로그래밍은 순차적인 함수 호출을 중심의 관점이다.
주로 구조가 TOP-DOWN이다. 따라서 이해하기 쉽다.
하지만 코드를 확장하거나 자주 실행에 따라 로직이 바뀌어야 하는 경우에 수정하기 어렵다. - 객체 지향 프로그래밍은 객체들의 책임과 협력 중심의 관점이다.
다형성과 의존성 주입으로 코드를 확장하기 쉬우며, 실행환경의 다양한 입력에 대응하기 좋다.
하지만 런타임이 되기 전에 실제로 코드가 어떤 방향으로 흐르는 지 알기 어려우며, 디버깅도 어렵다. - 함수형 프로그래밍은 상태를 갖지 않는 함수들의 활용 중심의 관점이다.
상태를 가지지 않기 때문에 예측에서 벗어나는 결과(사이드 이펙트)가 없다.
하지만 실제로 상태를 가지지 않는 함수를 작성하고 활용하는 코드를 작성하는 것은 어렵다.