JavaScript/함수형 프로그래밍과 JavaScript ES6+

장바구니 예제(총 수량, 총 가격)

느리지만 꾸준하게 2021. 8. 19. 20:49

장바구니에 담긴 총 수량을 뽑아보는 코드를 작성해보자.

모든 quantity를 더해야 하기 때문에 products를 출발해서 quantity만 남겨놓으면 reduce를 통해서 축약하기 쉬울 것이다.

    <script>
        const products = [
            { name: '반팔티', price: 15000, quantity: 1, is_selected: true },
            { name: '긴팔티', price: 20000, quantity: 2, is_selected: false },
            { name: '핸드폰케이스', price: 15000, quantity: 3, is_selected: true },
            { name: '후드티', price: 30000, quantity: 4, is_selected: false },
            { name: '바지', price: 25000, quantity: 5, is_selected: false }
        ];

products 통해서 map을 해서 출력을 하게되면 아래와 같이 나오게 된다.

    <script>
        const products = [
            { name: '반팔티', price: 15000, quantity: 1, is_selected: true },
            { name: '긴팔티', price: 20000, quantity: 2, is_selected: false },
            { name: '핸드폰케이스', price: 15000, quantity: 3, is_selected: true },
            { name: '후드티', price: 30000, quantity: 4, is_selected: false },
            { name: '바지', price: 25000, quantity: 5, is_selected: false }
        ];

        go(products,
            map(p => p.quantity),
            log);
    </script>

 

그 다음에 go를 통해 map을 하고 reduce를 하면 a와 b를 받은 다음 a + b를 해주면 총 수량이 나타나게 된다.

        go(products,
            map(p => p.quantity),
            reduce((a, b) => a + b),
            log);

함수로 만들어보자.  total_quantity라고 변수를 지정해주고 products가 들어오면 수량을 리턴해주는 함수를 만들어 볼 수 있다. 

        const total_quantity = products => go(products,
            map(p => p.quantity),
            reduce((a, b) => a + b));

        log(total_quantity(products));

products를 받아서 products를 그대로 go에 넣는다는 것은 pipe로 되어도 된다는 것이다.

        const total_quantity = pipe(
            map(p => p.quantity),
            reduce((a, b) => a + b));

        log(total_quantity(products));

이번에는 price와 quantity가 연결되어서 합산되어지는 총 가격을 구하는 코드를 작성하자. 이 코드 또한 위와 거의 비슷할 것이다. total_price라는 함수가 있다고 하고 p.price * p.quantity를 한 값을 똑같이 reduce해준다.

        const total_price = pipe(
            map(p => p.price * p.quantity),
            reduce((a, b) => a + b));

        log(total_price(products));

그리고 reduce의 a+b 부분을 add라는 함수를 만들어서 간단하게 할 수 있다.

        const add = (a, b) => a + b;

        const total_quantity = pipe(
            map(p => p.quantity),
            reduce(add));

        log(total_quantity(products));


        const total_price = pipe(
            map(p => p.price * p.quantity),
            reduce(add));

        log(total_price(products));

그리고 map이 전달하는 부분을 제외하고는 두 개의 코드가 동일한 코드이다. 추상화를 시켜보자. sum이라는 함수를 만들어본다. 함수와 f 이터레이터 iter을 받아서 go를 하면서 비슷한 일을 한다. map에 있는 부분을 위임을 한다.( map(f) )

그래서 sum을 이용해서 두 함수를 간략하게 나타낼 수 있다.

        const sum = (f, iter) => go(
            iter,
            map(f),
            reduce(add));

 

log를 출력하는데 sum을 하면서 products를 주고 p를 받아서 p의 quantity를 하면 같은 결과가 나온다.

        log(sum(p => p.quantity, products));

혹은 아래와 같이 코드를 작성해도 값을 합한 결과가 출력된다.

        log(sum(p => p.price * p.quantity, products));

sum이라는 함수를 이용해서 두 코드의 중복을 줄일 수 있다. products를 하면서 sum을 하면서 products를 전달하는 식으로 작성한다.

        const total_quantity = products => sum(p => p.quantity, products);

        log(total_quantity(products));

        const total_price = products => sum(p => p.price * p.quantity, products);

        log(total_price(products));

curry를 이용해서도 작성할 수 있다. 먼저 curry함수로 감싸준다.

        const sum = curry((f, iter) => go(
            iter,
            map(f),
            reduce(add)));

sum같은 경우에는 아래와 같이 실행할 수 있다. products를 받아서 product를 받는 함수가 sum이 return한 함수에 products를 전달하고만 있기 때문에 아래 코드를 간단하게 나타낼 수 있다. 훨씬 코드가 줄어든 것을 볼 수 있다.

 

sum이라는 함수에 currying을 이용해서 보조함수를 사용하겠다는 것만으로( map(f) ) 간결하게 코드를 작성했다.

const total_quantity = products => sum(p => p.quantity)(products);

const total_price = products => sum(p => p.price * p.quantity)(products);
const total_quantity = sum(p => p.quantity);

const total_price = sum(p => p.price * p.quantity)

sum은 products만을 위해서 사용되는 함수가 아니다. 아래와 같이 유저가 있고 유저의 나이를 다 더하는 코드를 작성하면 합해진 결과를 볼수 있다. 즉 sum은 추상화 레벨이 매우 높은 것이다.

        log(sum(u => u.age, [
            { age: 30 },
            { age: 20 },
            { age: 10 },
        ]))

지금까지 sum을 이용해서 total_quantity와 total_price를 만들어 보았다.

 

 

 

 

 

<출처 : 유인동 함수형 프로그래밍과 JavaScript ES6+>

https://www.inflearn.com/course/functional-es6/dashboard

 

함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의

ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍,

www.inflearn.com