함수형 프로그래밍에는 액션, 계산, 데이터 계층이 존재합니다. 함수형 프로그래밍을 잘하기 위해서는 현재 작성하고 있는 코드가 어느 계층인지 판단하면서 작성해야 합니다.
이러한 사고방식은 꼭 코드를 작성할 때만 적용되는 것은 아닙니다. 요구사항을 각 계층에 맞게 정리할 수도 있고, 이미 작성된 코드를 각 계층으로 분리하여 리팩터링을 할 수도 있습니다.
앞으로, 액션, 계산, 데이터 계층에서 계층을 생략하고 설명하겠습니다.
첫 번째로 데이터입니다.
데이터의 사전적인 의미는 “이벤트에 대한 사실”입니다. 흠.. 잘 와닿지가 않네요. 저는 책을 읽으면서 “이벤트에 대한 결과”가 더 적합한 의미인 것 같다고 생각했습니다.
예를 들어, 사용자가 구글에 회원가입을 했습니다. 이때 회원가입은 이벤트이고, 사용자가 정한 아이디 및 비밀번호는 데이터입니다. 즉, 아이디와 비밀번호가 회원가입 이벤트에 의해 생성된 결과입니다.
데이터는 수동적인 개체입니다. 데이터는 혼자서 어떠한 행위를 하지 못합니다. 아래에서 설명할 계산 또는 액션에 의해 데이터가 사용됩니다.
추가로, 계산과 액션도 하나의 이벤트입니다. 계산과 액션을 통해 생성된 결과도 하나의 데이터라고 말할 수 있습니다.
두 번째로 계산입니다.
계산은 항상 동일한 입력에 대해 동일한 값을 산출하는 주체입니다. 함수형 프로그래밍을 공부하다 보면, 그토록 강조하는 순수 함수가 계산에 해당합니다. 다른 말로는 수학 함수라고도 불린다고 합니다.
계산은 입력 이외에 환경에는 영향을 받지 않습니다. 그래서 테스트가 쉽고 자유롭습니다. 사실 자바스크립트로 프로그래밍을 하다 보면 계산을 자주 사용하게 됩니다.
예를 들어, map
, filter
와 같은 고차 함수가 계산에 해당합니다.
// data
const nums = [1,2,3,4,5;]
// data from calculation
const add3 = nums.map(num => num + 3);
마지막으로 액션입니다.
액션은 데이터, 계산과 달리 외부 세계와 영향을 주고받는 주체입니다. 다른 말로는 순수하지 않는 함수 또는 부수 효과가 있는 함수라고도 불립니다.
액션은 호출 시점과 횟수에 영향을 받습니다. 1초 전에 호출한 액션과 1초 후에 호출할 액션의 결과가 다를 수 있다는 의미입니다. 그래서 다루기가 어렵고 테스트하기가 어렵습니다.
책에서는 액션을 가능한 적게 사용하고, 가능한 작게 만들라고 말합니다. 하지만 유일하게 외부 세계와 통신할 수 있기에, 가장 많은 고민이 필요할 것 같습니다.
특징 | 예시 | |
---|---|---|
액션 | 실행 시점과 횟수에 의존한다. (= 순수하지 않는 함수, 부수효과) | 이메일 보내기 |
계산 | 항상 동일한 입력에 동일한 출력을 출력한다. (= 순수 함수) | 최대값 찾기, 이메일 유효성 검사 |
데이터 | 이벤트에 대한 사실 (= 일어난 이벤트의 결과 값) | 이메일 주소, 은행 계좌 금액 |
하나의 액션은 여러 액션 또는 데이터로 분리할 수 있습니다. 더불어 계산은 여러 계산 또는 데이터로 분리할 수 있습니다.
함수의 역할이 분명해야 하는 것처럼, 액션과 계산도 서브 액션, 계산, 데이터로 분리하여 역할을 분명하게 나타내야 합니다.
만약 함수에 액션이 포함된다면, 해당 함수도 액션입니다. 액션은 가능한 작고 적을수록 좋습니다. 항상 액션을 작성할 때는 영향을 미치는 범위를 고려하면서 작성해야 합니다.
만약 처리해야 할 데이터의 크기가 10억이라고 가정해봅시다. 매번 10억 개의 데이터를 계산 또는 액션에 사용해버리면 성능에 큰 영향을 미치게 됩니다. 책에서는 최적화를 위해 페이지 네이션을 제시하고 있습니다.
제가 생각하기에는, 실제로 10억 개의 데이터를 연산하지 않을 것 같습니다. 예를 들어, 지연 평가(lazy evaluation)를 통해 필요할 때 연산을 취할 것 같습니다. 자바스크립트에는 이터레이터를 만들어 지연 평가를 구현해볼 수 있습니다.