함수형 프로그래밍이라는 개념은 프로그래밍보다 먼저 등장했다.
정수를 제곱하기
자바 언어에서 25까지 정수 제곱을 출력하려면 아래처럼 코드를 작성하면 된다.
public class Squint {
public static void main(String args[]) {
for (int i = 0; i < 25; i++) {
System.out.println(i*i);
}
}
}
함수형 언어인 클로저는 아래와 같다.
(println (take 25 (map (fn [x] (* x x)) (range))))
위의 코드를 쪼개보면
(println
(take 25
(map (fn [x] (* x x))
(range))))
자바에서는 가변 변수인 i를 사용하지만 클로저에서는 가변 변수가 전혀 없다. 가변 변수처럼 보이는 x 는 한 번 초기화되면 절대 변하지 않는 변수다.
불변성과 아키텍처
경합 조건, 교착상태 조건, 동시 업데이트 문제는 모두 가변 변수로 인해 발생한다. 따라서 가변 변수가 없다면 이러한 문제들이 모두 해결된다. 소프트웨어 아키텍트라면 동시성에 대한 문제를 생각해야 하지만 깊게 생각하지 않는 경우가 대부분이다. 대부분 문제가 일어나지 않을 것이라고 긍정적으로 생각한다.
가변성의 분리
애플리케이션 구조화는 내부 서비스를 가변 컴포넌트와 불변 컴포넌트로 분리하는 것으로부터 시작한다. 변수를 변경하는 컴포넌트와 변경하지 않는 컴포넌트를 분리하고 가변 변수를 보호하는 수단을 찾아야 한다.
현명한 아키텍트라면 가능한 한 많은 처리를 불변 컴포넌트로 옮겨야 하고, 가변 컴포넌트에서는 가능한 한 많은 코드를 빼내야 한다.
이벤트 소싱
고객의 계좌 잔고를 관리하는 은행 애플리케이션에서 계좌 잔고를 변경하는 대신 트랜잭션 자체를 저장한다고 하면 이 과정에서 가변 변수는 하나도 필요 없다. 항상 트랜잭션을 저장한다고 하면 저장 용량이 무한히 커지겠지만 한 시간 또는 하루 단위로 생명주기를 가져간다면 현재 컴퓨팅 자원으로 충분할 것이다.
이벤트 소싱을 사용하게 되면 CRUD 중 CR만 사용하게 된다. 잔고를 업데이트하지 않고 트랜잭션을 저장만 하므로 동시성 업데이트로부터 자유롭다.