코딩쌀롱

함수형 프로그래밍 키워드 정리 본문

개발공부

함수형 프로그래밍 키워드 정리

이브✱ 2021. 1. 21. 05:27

 

프로그래밍 패러다임

•패러다임 : 세계를 이해하는 방식, 어떤 한 시대 사람들의 견해나 사고를 근본적으로 규정하고 있는 인식의 체계

•프로그래밍 패러다임 : 프로그래밍을 어떤 관점으로 보고 이해하는가, 프로그램을 작성할 때의 관점

 

프로그래밍 패러다임은 여러 가지가 있고, 대표적으로는 아래와 같다.

•명령형 프로그래밍 : 절차지향, 객체지향

•선언형 프로그래밍 : 함수형, 반응형  

 

 최근 대부분의 프로그래밍 언어는 여러 개의 패러다임을 갖는데 이런 언어를 멀티 패러다임 언어라고 한다. 대표적으로 자바스크립트가 그러하다. 어떤 언어는 하나의 패러다임을 갖기도 하지만 최근에는 여러 패러다임들이 관대하게 지원되고 있다. 예로 자바는 람다가 생기면서 함수형 프로그래밍도 가능해졌다.

 

 누구나 세계관을 가지고 있듯, 각각의 프로그래머들도 선호하는 프로그래밍 패러다임이 있다. 다양한 프로그래밍 패러다임을 이해하고, 활용할 수 있으면 개발에 대한 이해와 수준이 달라질 것 같다.

 

함수형 프로그래밍 (functional programming)

✱ 일급 함수 (First-class function) 

프로그래밍 언어에서 함수를 값으로 다룰 수 있는 것 (함수 스스로 객체 취급)

자바스크립트의 함수는 일급 객체이자 일급 함수이다.

•변수에 담을 수 있다.

•함수나 메서드의 인자로 넘길 수 있다.

•함수나 메서드에서 반환할 수 있다.

 

일급 함수를 만족하기 위해서는 조건들이 필요하다.

•아무 때나(런타임에서도) 선언이 가능하다.

•익명으로 선언할 수 있다.

•익명함수도 함수, 메서드의 인자로 넘길 수 있다.

생성한 함수 자체를 반환하거나 다른 함수에 전달하는 기능은 코드 재사용성과 추상화 측면에서 매우 유용하다.

 

순수 함수 (Pure function) 

 부수 효과(side effects)가 없는 함수,  부수 효과는 함수 본연의 기능 이외의 행위를 말하며, 외부 함수 또는 외부 변수값의 변경이 해당한다. 함수에 인자로 넘긴 변수를 함수 내부에서 바꾸는 것도 부수 효과이다.

 

 쉽게 말하면, 함수가 input만 받아, input만을 사용해 output을 반환! output에 영향을 주는 건 오직 input만이다. 그렇기 때문에 함수 밖에 있는 변수를 가져다 쓰면 안 된다. 그 변수의 값이 바뀜에 따라 output에 영향을 줄 가능성이 있기 때문. 사이드 이펙트를 발생할 가능성이 있다는 것. 결국 순수 함수는 input을 가지고 output을 내놓는 것 이외에는 추가적인 작업을 수행하지 않는다. 이를 통해 같은 input에는 항상 같은 output을 출력(참조 투명성)한다는 것을 알 수 있다.  그리고 순수함수는 함수의 역할이 명확하고 예측이 가능하고, 디버깅이 쉬우며 테스트하는데 용이함을 의미한다.

 

✱ 불변성 (Immutablility)

 모든 데이터는 불변형으로. 배열, 객체와 같은 참조 데이터 타입은 참조를 따라 값이 변할 수 있다. 이러한 가능성을 아예 없애기 위해 배열, 객체들은 한 번 만들어지면 수정하지 않는다. 수정하고 싶다면, 원본은 그대로 두고 복제해서 사용한다. 

// mutable
const fruits = ['cherry', 'blueberry'];
fruits.push('banana');

// immutable
const somePets = ['dog', 'cat'];
const pets = [...somePets, 'raccoon'];

const func = arr => [...arr].filter(e => e > 3);

 

반복문은 피하고, 고차 함수 (Higher-order function)로 작성하자

 함수를 인자로 받는 함수, 또는 함수를 반환하는 함수를 고차 함수라고 한다. 함수를 인자로 받는 Array의 많은 메소드들(map, filter, reduce, forEach, every, some, sort...)도 고차함수다. 이러한 메서드들을 사용하면 코드가 훨씬 간결해진다.

// 반복문
const double = arr => {
   let results = [];
   for(let i = 0; i < arr.length; i++){
      results.push(arr[i] * 2)
   }
   return results
};

// 고차함수 map 사용
const double = arr => arr.map(e => e*2);

선언형 프로그래밍의 중요한 첫 번째 단계는 명령형 코드를 추상화 하는 것.

상태를 변경하는 지점들은 map 메서드 안으로 추상화되어 나는 직접 상태를 변경하지 않는다. 

 

 

✱ 선언적 패턴(Declarative patterns)

명령형 프로그래밍 : '어떻게'에 대한 단계들을 하나하나 나열

선언형 프로그래밍: '무엇을' 원하는지에 집중

 

명령형 방식 (HOW) : 주차장 북쪽 출구를 나와 왼쪽으로 가세요. 12번가 출구에 도착할 때까지 15번 북쪽 도로를 타세요. 이케아를 끼고 우회전하세요. 직진하여 첫 번째 신호등에서 우회전 하세요. 다음 신호등을 지나 좌회전을 하세요. 우리 집은 #298입니다.

선언형 방식 (WHAT) : 내 주소는 98 West Immutable Alley, Eden, Utah 84310입니다.

 

출처: https://boxfoxs.tistory.com/430 [박스여우 - BoxFox]

 

 

또한 명령형은 현재 상태의 컨텍스트에 의존하기 때문에 재사용하기 어려운 경우가 많으나, 선언형 코드는 해당 코드가 달성하고자 하는 것이 무엇인지만을 나열하기 때문에 다른 프로그램에서 재사용하기 쉽다.

 

지연 평가 (느긋한 계산법, Lazy evaluation)

 컴퓨터 프로그래밍에서 느긋한 계산법은 계산의 결과값이 필요할 때까지 계산을 늦추는 기법이다. - 위키피디아

 

지연 평가는 필요할 때까지 계산을 늦추면서 불필요한 계산을 줄일 수 있다.

 •불필요한 계산을 하지 않으므로 빠른 계산 가능

 •무한 자료 구조를 사용할 수 있다.

 •복잡한 수식에서 오류 상태를 피할 수 있다.

 

 느긋한 계산법의 반대 개념은 조급한 계산법(엄격한 계산법, Strict evaluation)은 실행되는 즉시 계산의 결과를 도출하는 동작 방식이다. 

// strict evaluation
const arr = [0, 1, 2, 3, 4, 5]
const result = arr.map(n => n + 10).filter(n => n % 2).slice(0, 2);
console.log(result) // [11, 13]

조급한 계산법은 흐름이 왼쪽에서 오른쪽으로 흐른다. map, filter, slice 각각의 메서드가 실행이 종료되어야 다음 메서드를 실행할 수 있다. result값([11, 13])을 보면 처음 arr의 4, 5 원소에 대한 계산은 불필요함을 알 수 있다.

 

 지연 평가는 흐름이 위에서 아래로 흐른다. 배열의 각 원소들이 map, filter, take 함수들을 차례대로 수행한다. 원하는 결과가 나오면 그 뒤 원소에 대한 계산은 하지 않는다. 지연 평가는 연산 횟수 자체를 줄여 좋은 성능을 보여준다. 참고한 블로그의 예시 코드는 generator를 사용했는데 generator를 몰라서 공부가 필요하다.

 

 

 


참조

블로그 - 프로그래밍 패러다임

블로그 - 프로그래밍 패러다임이란

블로그 - 자바스크립트 일급함수

블로그 - JavaScript 함수형 프로그래밍 3단계로 설명하기

블로그 - 명령형 프로그래밍 VS 선언형 프로그래밍

위키피디아 - 느긋한 계산법

블로그 - 지연 평가를 이용한 성능 개선

 

 

학습 단계로 잘못된 정보가 있을 수 있습니다. 잘못된 부분에 대해 알려주시면 곧바로 정정하도록 하겠습니다🙂

 

 

Comments