함수형 프로그래밍 #2 - 메서드를 함수형으로 전환하기

2020. 8. 6. 15:24컴퓨터언어/Vanilla JS

728x90
반응형

 

이 포스팅은 아래 강의를 수강하며 정리한 글입니다.

 

https://www.inflearn.com/course/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D

 

자바스크립트로 알아보는 함수형 프로그래밍 (ES5) - 인프런

마플(http://www.marpple.com)의 CTO 유인동님이 알려주는 함수형 프로그래밍에 대한 강좌 입니다. 함수형 프로그래밍으로 라이브러리를 직접 만들어가며 함수형 프로그래밍의 패러다임과 코딩의 즐거

www.inflearn.com

 

굳이 함수형 프로그래밍을 하지 않아도 상관은 없다.

하지만 사람이라면 누구나 실수하기 마련이고, 또 코딩은 나 혼자만 하는 것이 아니기 때문에,

유지보수와 사후관리를 위해서는 효율적인 방안이 필요하다.

 

바로 함수형 프로그래밍이 이를 도와준다.

 

1. 객체지향 프로그래밍은 데이터가 갖춰야 하는 틀(Class)을 미리 만들어놓고 이에 맞게 메서드를 끼워맞추는 반면, 함수형 프로그래밍은 행해야 하는 동작을 먼저 설계한 후에 데이터를 끼워맞추기 때문에 오류가 적다.

2. 데이터에 접근할 때 외부적인 부수효과 1도 없이 특정 문맥에서만 치고 빠지도록 한다.

3. 하나의 함수는 하나의 핵심동작만을 담기 때문에, 표현이 훨씬 깔끔하고 재사용성이 뛰어나다.

4. 커스터마이징이 쉽다.

 


아래와 같이 사용자 정보가 있다고 하자.

 

const users = [
    {
        name: "bban",
        age: "26",
        country: "KR"
    },
    {
        name: "john",
        age: "34",
        country: "CA"
    },
    {
        name: "kelly",
        age: "29",
        country: "US"
    },
    {
        name: "ray",
        age: "38",
        country: "UK"
    },
]

 

그리고 여기서 30세 이상인 회원의 이름을 구한다면 어떻게 해야 할까?


1. 함수형 프로그래밍을 사용하지 않고 일반적인 수준으로 구하기

function over30(users) {
    const tempUsers = [];

    for (let i = 0; i < users.length; i++) {
        if (users[i].age >= 30) tempUsers.push(users[i])
    }

    return tempUsers;
}

function theirNames(arr) {
    const names = [];

    for (let i = 0; i < arr.length; i++) {
        names.push(arr[i].name);
    }

    return names;
}

console.log(theirNames(over30(users))); // [ 'john', 'ray' ]

 

위와 같이 간단히 구할 수 있다.

먼저 30세 이상인 회원들을 추려낸 후, 그들의 이름 속성에 접근하면 되는 것이다.

 

이는 자바스크립트를 만진 적 있다면 누구나 작성할 수 있는 코드이다.

하지만 다음과 같은 문제점이 있다.

 

  • 함수 내부의 의미가 직관적이지 못하다.
  • 비슷한 문법이 중복되어 있다.
  • 각 함수의 선언부 밖에서 또는 로직 사이에서 ".pop()" 등 데이터에 조작을 가할 수 있는 여지가 있으므로 버그의 우려가 있다.

 


2. 함수형 프로그래밍으로 구하기

 

function _filter(list, predi) {
    const new_list = [];
    _each(list, function (val) {
        if (predi(val)) new_list.push(val);
    })
    return new_list;
}

function _map(list, mapper) {
    const new_list = [];
    _each(list, function (val) {
        new_list.push(mapper(val));
    })
    return new_list;
}

function _each(list, iter) {
    for (let i = 0; i < list.length; i++) {
        iter(list[i]);
    }
    return list;
}

console.log(
    _map(
        _filter(users, function (user) {
            return user.age >= 30
        }),
        function (user) {
            return user.name
        })
);

 

앞서 함수형이 아닌 경우에도 각 함수가 해야할 일이 명확하게 나눠졌음은 마찬가지였다(30세 이상인 회원 먼저 골라내기 -> 이름 추출).

하지만 지금처럼 함수형 프로그래밍을 하게 되면,

각 함수가

  • 골라내는 역할을 하고(filter)
  • 골라낸 각 값에 대응하는 속성을 추출하는 역할을 한다는 것(map)

을 더 명확히 알 수 있을 뿐 아니라,

함수의 이름에서 알 수 있듯이 더 상위 개념으로 일반화시켰기 때문에(over30 -> _filter, theirNames -> _map)

꼭 지금의 예처럼 "30세 이상의 회원들의 이름"이 아닌 경우에도 이 함수들을 재사용할 수 있게 된다.

즉, 어떤 상황이든 쿼리를 다양하게 줄 수 있게 되는 것이다!

 

그리고 _each 함수를 통해 기존에 "for 반복문"마저 반복해서 써야했던 중복의 고달픔을 해결하였다.

 

이렇게 만들어진 3개의 함수는 각각 하나의 동작만 전문적으로 하도록 세팅되어 있기 때문에, 오류의 확률이 확연히 낮아졌다.

 

이처럼 함수형 프로그래밍은 로직의 흐름을 읽기에 훨씬 직관적이고 간결하다!

728x90
반응형