개요
객체지향 프로그래밍은 필수적인 패러다임으로서 다루는 책과 글은 많다.
반면, 함수형 프로그래밍은 필수적이지도 않으며,
어떤 부분이 좋다고 콕 집어 말하기 어렵다.
이는 함수형 프로그래밍이 범용 패러다임이기 때문이다.
결국, 어디에서나 잘 어울릴 수 있다는 뜻이기도 하다
이 글은 아래 책을 읽고 난 후 작성되었습니다.
- 쏙쏙 들어오는 함수형 코딩 / 에릭 노먼드
목표
함수형 프로그래밍의 주요 개념과 관점을 이해하고, 함수지향 설계와 아키텍쳐를 학습한다.
여정
함수형 프로그래밍의 어려운 점
함수형 프로그래밍은 부수효과(Side Effect) 없이 순수함수만을 사용한다.
- 부수효과는 리턴 값 전달 이외에 발생하는 행동을 말한다.
- 순수함수는 인자에만 의존하여 같은 인자는 항상 같은 결과를 발생시키는 함수이다.
하지만, 실질적으로 많은 비즈니스 로직에서 이러한 순수함수를 적용할 수는 없다.
바로 이 부분이 함수형 프로그래밍이 실제로 적용되기 어려운 부분이다.
문제가 어렵다면 쪼개서 생각해볼 수 있다.
그래서 함수형 프로그래밍은 코드를 아래 세 가지 형태로 나눠서 생각한다.
- 액션 : 실행 시점, 횟수에 의존하는 코드,
- 계산 : 입력값을 계산해 출력하는 코드, 횟수와 시점에 영향을 받지 않는다.
- 데이터 : 이벤트에 대한 사실을 기록한 코드, 속성을 가지고 있으며, 실행하지 않아도 의미가 있다.
액션보다 계산이 예측하기 쉽고,
계산보다 데이터가 예측하기 쉽다.
함수형 프로그래밍에서는 이 분류작업을 잘하는 것이 핵심이다.
이제 예제를 통해서 한번 이를 분류하는 작업을 해보자.
함수형 사고로 코드를 분류하기
다시 말하지만, 함수형 프로그래밍에서 코드를 분류하는 작업은 중요하다.
아래와 같은 예시는 코드 분류의 어려움을 나타내는 예시이다.
// 수수료를 전송하는 코드
// 시점에 영향을 받는 액션
function figurePayOut(affiliate) {
let owed = affiliate.sales * affiliate.commission;
if(owed > 100) { sendPayOut(affiliate.bank_code, owed); }
}
// figurePayOut에 따라
// 시점에 영향을 받는 액션이 되었다.
function affiliatePayOut(affiliates) {
for(var i=0; a<affiliates.length; i++){ figurePayOut(affiliates[i]); }
}
// affiliatePayOut에 따라
// 시점에 영향을 받는 액션이 되었다.
function main(affiliates) { affiliatePayOut(affiliates); }
분명 실제 액션은 figurePayOut() 뿐이지만 모든 코드가 결국 액션이 되었다.
액션은 코드 전체로 퍼진다.
하지만 무엇을 더 쪼갤 수 있단 말인가?
바로 이 부분이 함수형 사고의 시작이다.
때때로, 액션과 계산은 우리의 사고 과정에 녹아있기 때문에
분리하는 일이 쉽지가 않은 것이다.
다음 예시를 보자.장보기를 4가지 과정으로 나눠서 작성하였다.장보기 : 냉장고 확인 → 운전(출발) → 구입 → 운전(복귀)
어떤가? 모두 액션처럼 보이지 않는가?
하지만 아래와 같이 더욱 세분화할 수 있다.
타임라인 ↓ | 액션 | 계산 | 데이터 |
냉장고 확인 | 냉장고 확인 | - | 현재 재고 목록 |
운전(출발) | - | - | - |
구입 | 장보기 목록에 맞게 구입 |
재고 뺄셈 | 필요한 재고 목록 |
- | 장보기 목록 | ||
운전(복귀) | - | - | - |
이제 실제로 냄새나는 코드를 리팩토링하면서
요구사항에 대응하는 예시를 보도록 하자.
냄새나는 코드
아래와 같은 간단한 쇼핑몰 장바구니 코드가 있다고 해보자.
let shoppingCart = [];
let shoppingCartTotal = 0;
function addToCart(name, price) {
shoppingCart.push({
name: name,
price: price
});
calculateTotal();
}
function calculateTotal() {
shoppingCartTotal = 0;
for (let i = 0; i < shoppingCart.length; i++) {
shoppingCartTotal += shoppingCart[i].price;
}
setCartTotalDom();
}
function setCartTotalDom() {
// DOM manipulation
}
여기에 우리는 아래와 같은 요구사항이 들어왔다고 가정해보자.
- 결제팀
- 무료 배송 정책을 추가해야 합니다.
- 총액 구간마다 세금을 계산해야 합니다.
- QA팀
- 테스트 가능한 코드를 만들어 주세요
- 배송팀
- 운송장에도 출력가능하게 해주세요
벌써부터 머리가 어지럽지만,
문제를 쪼개서 생각하면 쉽다.
다음 포스팅에서 계속 진행해보자.
마무리
이번 시간에는 함수형 프로그래밍의 주요 개념과 관점을 설명하는 시간이었다.
다음 시간에는 실제 코드에 직접 적용해보면서
함수형 설계와 아키텍쳐에 대해 학습해보자.
'Do you know?' 카테고리의 다른 글
아시나요? 함수형 프로그래밍 - (3) 추상화 레벨 (0) | 2023.07.23 |
---|---|
아시나요? 함수형 프로그래밍 - (2) 분류하기 (0) | 2023.07.18 |
아시나요? - 객체지향의 사실과 오해 (0) | 2023.05.14 |
아시나요? 웹서버와 WAS, 그리고 Nginx (0) | 2023.03.09 |
아시나요? 의존성 주입(DI, Dependency Injection) (0) | 2023.01.18 |