함수 체인과 지연 실행
JavaScript 라이브러리 중에 거의 jQuery 다음으로 많이 사용하지 않을까 싶은 라이브러리 중에 underscore 또는 lodash 라는 것이 있다. (두 라이러리는 차후 합치는 것이 논의되고 있다.)
이 라이브러리들은 다양한 데이터들을 체인 형태로 실행 할 수 있게 해 주는 라이브러리로써 로직을 깔끔하게 유지시키는데 좋은 역할을 해 준다. JavaScript 기본 함수에도 배열을 처리하는 map, reduce 같은 것이 있지만, lodash와 underscore가 조금 더 편하게 사용 할 수 있고, 추가로 다양한 유틸리티들이 포함되어 있어서 우리 회사에서도 기본 라이브러리로 사용하고 있다.
그 중 lodash에는 지연 실행(Lazy Evaluation) 기법이 포함되었는데, 이에 대해서 간단하게 설명해보고자 한다.
배열을 처리하는 일반적인 방법은 바로 다음과 같이 for 문 같은 루프문을 사용하는 것이다.
이를 lodash의 map과 filter를 이용해서 함수형 툴체인 기법으로 변경하면 다음과 같이 된다.
이 기법이 익숙하지 않다면 처음엔 약간 이해하기 쉽지 않을 수 있지만, for 루프에 비해 각각의 로직이 명확하게 분리가 되어 있으므로, 차후 디버깅을 하거나 로직을 추가/수정할 때 훨씬 쉽고 편하게 할 수 있다.
다만, 각각의 map/filter 함수마다 루프를 한 번씩 돌고, 또 각각 루프를 돌 때 마다 배열을 새로 생성하므로, 상황에 따라 실행속도가 급격히 느려지거나 메모리를 과도하게 잡아먹는 문제가 생길 수 있다.
이를 해결하기 위해 지연 실행이라는 기법이 생겼는데, lodash의 경우 다음과 같이 사용할 수 있다.
사용법은 간단한데, 첫 함수 사용시 lodash 의 _.map(numbers, function) 대신에 _(numbers).map(function) 이와 같이 lodash의 생성자를 이용해 객체를 만든 뒤 함수 체인을 사용하고, 함수체인의 마지막에 .value() 를 붙여주면 된다.
이렇게 하면 함수체인으로 연결되어 있는 각각의 함수들이 배열의 모든 요소들을 처리한 뒤에 다음 체인으로 넘어가는 것이 아니라, 요소 하나를 처리하고 다음 체인으로 넘기는 방식으로 실행 방식이 변한다.
즉, map에서 첫번째 요소에 1을 더하고 filter 에서 2보다 큰 값인 경우만 다음 map 에서 자승을 리턴. 그 다음 두번째 요소를 같은 방식으로 처리, 그리고 또 그 다음 세번째 요소를 같은 방식으로 처리. 이런 방식으로 for 문과 같은 형태로 루프를 돌게 된다.
따라서 요소 3개가 있는 3개의 함수 체인은 최대 9번(여기서는 8번)의 루프를 도는 반면, 지연 실행으로 실행한 함수 체인은 요소의 갯수만큼인 3번의 루프만 돌게 되어 실행 속도를 획기적으로 줄일 수 있게 된다.
참고로, 맨 마지막 체인에 reduce 등을 넣으면 value를 사용하지 않아도 된다.
또한 다음처럼 함수 체인에 들어가는 함수들을 모두 독립 함수로 빼서 조금 더 함수형 프로그래밍에 가까운 형식으로 만들면, 로직이 복잡한 경우라도 훨씬 더 이해하기 쉽고 유지보수가 쉬운 코드로 만들 수 있다.
글을 쓰고 난 뒤에 구글링을 해 봤더니 Lazy Evaluation에 대한 훨씬 더 쉬운 설명이 있었다. -_-a 다음 글을 보면 훨씬 더 명확하게 이해가 될듯. Introducing Lazy Evaluation