함수형 프로그래밍이란

함수형프로그래밍 개념

*"I anticipate that the adoption of pure functional languages will improve the quality and robustness of the whole software industry while greatly reducing time wasted on bugs that are simply impossible to generate with functional programming. It’s not magic, but sometimes it feels like that, and I’m reminded of how good I have it every time I’m forced to work with a non-functional codebase."*

왜 배워야 할까

많은 사람들은 어떠한 소프트웨어를 개발할때 초기 설계와 개발하는 과정이 가장 비용이 많이 사용된다고 생각할 수 있다. 하지만 실상은 그렇지 않다 그 소프트웨어를 유지 보수하는데 훨씬 많은 비용이 소모된다고 한다.

개발을 할 때 유지 보수를 생각하지 않고 개발을 착수하고 사용자들이 사용할수 있는 단계까지 가면 그제서야 결함들이 보이고, 그제서야 결함들을 고치려고 하면, 시간에 쫓겨 더 많은 버그들을 낳기 마련이다

따라서 유지보수를 하는데에 있어서 좋은 방법이 있는데 그 중 하나가 함수형 프로그래밍이다

**높은 추상화**로 코드가 단순해지고, **가독성이 높아짐**과 동시에,
 
불변객체와 순수함수를 사용하므로써 **에측가능한 상황** 속에서 코드를 작성할 수 있게해준다
 
이러한 특징들이 **예기치못한 버그**나, **디버깅**에 있어서 매우 많은 이점을 가져다주고, **유지 보수**에 있어서 매우 편리한 프로그래밍 패러다임 중 하나이다

객체 지향과 함수형 프로그래밍의 차이

결국 프로그래밍이란 데이터의 변화, 즉 상태의 변화 를 다루는 것인데 프로그램의 덩치가 커지고 복잡해지면 너무나 많은 상태들을 관리하는것에 대해 혼란스러워진다 따라서 객체지향, 함수형 프로그래밍은 서로 다른 관점에서 상태관리를 바라본다

  • 객체지향은 서로 관심있는 것들끼리 묶어서 관리를 하자는 입장이다. 문제가 발생했을 때, 관심사가 같은 것들끼리 묶어서 관리를 하게되면 문제의 범위를 각 객체로 좁힐 수 있고, 동일한 관심사로 모인 객체들을 작은 프로그램으로 취급하여 조립하고, 서로 소통할 수 있도록 하자는 관점이다
  • 함수형프로그래밍은 상태가 변화하는 것과 그렇지 않은것을 분리해서 관리하자는 입장이다. 결국 상태관리가 어려운 이유는 상태들이 변화하기 때문인데 상태와 무관한 함수들을 만들면 문제가 발생하지 않거나 검증된 함수들이 만들어지고 이 함수들을 조립한 함수 역시 문제가 없을 것이기에 문제가 발생할 수 있는 범위를 부수효과에 한정할 수 있도록 하자는 관점이다

코드로 차이점 살펴보기

은행 입출금 예시

```ad-white
title: 객체지향 프로그래밍
~~~ js
class BankAccount {
  constructor(balance) {
    this.balance = balance;
  }
 
  deposit(amount) {
    this.balance += amount;
  }
 
  withdraw(amount) {
    if (amount > this.balance) {
      console.log("Insufficient funds");
    } else {
      this.balance -= amount;
    }
  }
}
 
let account = new BankAccount(100);
account.deposit(50);
console.log(account.balance);  // 150
 
account.withdraw(75);
console.log(account.balance);  // 75
~~~
상태를 저장하는 객체와 객체의 메소드를 통해 상태를 제어
```
 
```ad-white
title: 함수형프로그래밍
~~~ js
const deposit = (balance, amount) => balance + amount;
 
const withdraw = (balance, amount) => {
  if (amount > balance) {
    console.log("Insufficient funds");
    return balance;
  }
  return balance - amount;
};
 
let balance = 100;
 
balance = deposit(balance, 50);
console.log(balance);  // 150
 
balance = withdraw(balance, 75);
console.log(balance);  // 75
~~~
함수만을 이용해서 상태를 제어
```

함수형, 객체지향의 장단점

함수형프로그래밍 비교적 우위

  1. 순수함수를 사용하기 때문에 코드가 단순해진다. 상태를 저장하는 객체가 없기 때문에, 코드를 이해하기 쉽다
  2. 순수함수를 사용하기 때문에 테스트(Jest 등)가 쉬워진다. 함수의 출력을 예측할 수 있기 때문에 테스트 작성이 쉬워진다
  3. 순수함수를 사용하기 때문에 코드의 부작용이 없어진다. 순수함수는 외부의 상태에 의존하지 않기 때문에 부작용을 일으키지 않는다

객체지향 비교적 우위

  1. 완성된 객체는 관심사가 같은 것들로 묶여있기 때문에 이해하기 쉽고 사용하기 매우 쉽다
    • IDE에.(쩜)만 찍어도 어떤 메소드가 있는지 알 수 있는 반면, 함수형 코딩은 각 함수들에 대해 다 알고 있어야한다
  2. 캡슐화로 인해서 외부에서 몰라도 될 정보들을 숨길 수 있도록 하여 더 간결한 형태의 코드를 만들어 내기에 용이하다
    • 반대로 테스트 불리하게 작용된다
  3. 일반적으로 더 익숙한 프로그래밍 방식이며, 관심사를 분리하기 쉬워서 코드의 가독성이나 유지보수성이 높게 할 수 있다

공통점으로는 두 방식 모두 가독성, 유지보수성을 높여주는 방식으로 작용을 하지만,

  • 함수형 프로그래밍은 좀더 에러를 검출하거나, 디버깅하는데에 있어서 결과들이 예측 가능하기 때문에 유지 보수적인 측면에서 더 우위에 있는 것 같고,
  • 객체지향 프로그래밍은 우리에게 익숙한 방식이고, 관심사를 분리하기 쉽기 때문에 가독성 측면에서 좀 더 우위에 있는것 같다.

두 패러다임 모두 각자에 어울리는 프로젝트들이 존재하며, 함수형 프로그래밍은 함수로 프로그램을 구성하기 때문에 커스터마이즈가 객체지향보다 쉽지 않다는 점에 비해 객체 지향은 다형성 및 상속을 활용한 커스터마이즈 비교적 간단하여 복잡한 시스템 구조화에 유리하다는 특징이 있다


함수형 프로그래밍 특징

어떻게(How) 보다는 무엇(What) 을 수행할 것인지에 집중한다

  • Side-Effect 발생하지 않는다
  • 순수 함수
  • 변경 불가능한 값(불변객체) 활용
  • 1급 객체
  • 참조 투영성

부수효과(Side-Effect)

여기서 부수효과란 다음과 같은 변화 또는 변화가 발생하는 작업을 뜻한다

  • 변수의 값이 변경
  • 자료구조를 제자리에서 수정
  • 객체의 필드값을 설정
  • 예외나 오류가 발생하여 실행이 중단됨
  • 콘솔 또는 파일 I/O 가 발생함
title: 모나드
그럼 함수형 프로그래밍에서는 파일 I/O를 어떻게 한다는거지?
IO 모나드: [하스켈로 배우는 함수형 언어 5](https://1ambda.github.io/haskell/intro-to-haskell-5/)

순수함수(Pure Function)

부수효과들을 제거한 함수, 함수형 프로그래밍에서 사용하는 함수

  • Memory or I/O 의 관점에서 Side-Effect가 없는 함수
  • 함수의 실행이 외부에 영향을 끼치지 않는 함수

1급 객체(First-Class Object)

다음과 같은 것들이 가능한 객체를 의미

  • 변수나 데이터 구조 안에 담을 수 있다
  • 파라미터로 전달할 수 있다
  • 반환값으로 사용할 수 있다
  • 할당에 사용된 이름과 무관하게 고유한 구별이 가능하다

함수형 프로그래밍에서 함수는 1급객체로 취급 받기 때문에 파라미터로 넘기는 등 작업이 가능하다

참조 투명성(Referential Transparency)

  • 동일한 인자에 대해 항상 동일한 결과를 반환해야 한다
  • 참조의 투명성으로 인해 기존의 값은 변경되지 않고 유지된다(Immutable Data)

참고사이트