함수형 프로그래밍이란?

JGwon·2023년 10월 1일
0

프로그래밍

목록 보기
2/4

함수형 프로그래밍

<💻 함수형 프로그래밍의 등장>

명령형 프로그래밍을 기반으로 개발했던 개발자들은 개발하는 소프트웨어의 크기가 커짐에 따라, 복잡하게 엉켜있는 스파게티 코드를 유지보수하는 것이 매우 힘들다는 것을 깨닫게 되었다. 그리고 이를 해결하기 위해 함수형 프로그래밍이라는 프로그래밍 패러다임에 관심을 갖게 되었다. 함수형 프로그래밍은 거의 모든 것을 순수 함수로 나누어 문제를 해결하는 기법으로, 작은 문제를 해결하기 위한 함수를 작성하여 가독성을 높이고 유지보수를 용이하게 해준다.

함수형 프로그래밍은 명령형 프로그래밍으로 개발을 해왔던 사람들에게는 생소한 프로그래밍일 수 밖에 없다. 명령형 프로그래밍에서는 가변 데이터를 편하게 다뤘다면, 함수형 프로그래밍은 순수함수, 부수효과(side effect), 1급 객체, 참조 투명성 같은 어려운 개념들이 나와 머리가 지끈 거리는 느낌을 받기도 한다.

함수형 프로그래밍을 배운다는 것은 프로그램을 이해하는 새로운 관점을 제공합니다. 한 문제에 대해서 한 가지 사고법을 고수하기 보단 다양한 시각에서 문제를 해결할 수 있다면 좋겠죠?? 그래서 우리는 함수형 프로그래밍 사고법을 배우나 봅니다.




<💻 함수형 프로그래밍의 특징>

부수효과가 없는 순수 함수1급 객체로 간주하여 파라미터나 반환값으로 사용할 수 있으며, 참조 투명성을 지킬 수 있다.

지금부터 부수효과, 순수 함수, 1급 객체, 참조 투명성에 대해 알아보자.


💡 부수효과

부수효과란: 함수에서 참조하는 변수가 외부에 있어서 그것을 변화시킬 수 있을 때 생긴다. 즉 부수효과는 외부의 State에 의존하게 될 때 생긴다.

데이터의 불변성을 유지한다. => 부수효과를 없앤다.

  • 변수의 값이 변경됨
  • 자료 구조를 제자리에서 수정함
  • 객체의 필드값을 설정함
  • 예외나 오류가 발생하며 실행이 중단됨
  • 콘솔 또는 파일 I/O가 발생함

부수 효과(Side Effect)가 있는 예시

const arr = [1,2,3];

function change(arr){
  arr[1] = 4;
}

change(arr);

console.log(arr); // [1,4,3]

// 외부 배열의 값을 변경하고 있다. Side Effect가 발생하고 있다.

부수 효과가 없는 예시

const arr = [1,2,3];

function change(v, i) {
  return i === 1 ? (v = 4) : v; 
}

const changedArr = arr.map(change);

console.log(arr); // [1,2,3]
console.log(changedArr); // [1,4,3]

여기서 중요한 개념이 나왔다. map, filter, slice등등은 기존의 배열은 그대로 두고, 새 배열을 반환한다. 이 메서드들을 어떻게 사용하냐에 따라서 Side Effect가 발생하지 않도록 할 수 있는 것이다.




💡 순수함수(Pure Function)

Side Effect를 제거한 함수들을 순수 함수라고 부르며, 함수형 프로그래밍에서 사용하는 함수는 이러한 순수 함수들이다.

  • Memory or I/O의 관점에서 Side Effect가 없는 함수
  • 함수의 실행이 외부에 영향을 끼치지 않는 함수
  • 동일한 입력에는 항상 같은 값을 반환해야한다.
  • 함수의 출력(return)은 오로지 그 함수에 입력에(input)된 값에만 의존한다.
  • ⭐ 코드를 액션과 계산, 데이터로 분리하자. 특히 액션에서 계산을 분리하는 코드를 작성하자.

함수형 프로그래밍의 핵심순수함수의 조합으로 프로그래밍을 하는 것이다.


순수함수의 장점

순수함수를 이용하면 얻을 수 있는 효과는 다음과 같다.

  • 함수 자체가 독립적이며 Side-Effect가 없기 때문에 Thread에 안전성을 보장받을 수 있음.
  • Thread에 안전성을 보장받아 병렬 처리를 동기화 없이 진행할 수 있다.



💡1급 객체

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

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

변수나 데이터 구조 안에 담을 수 있다.

const add = function(a,b) {
  return a + b;
}

add(5, 3) // 8
// 이처럼 함수 자체를 하나의 데이터 구조에 담고 사용할 수 있음.

파라미터로 전달할 수 있다.

function printA(){
  console.log("A");
}

$target.addEventListener("click", printA);

함수 반환하기

function add(a) {
  return function(b) {
    return a + b;
  }
}

함수형 프로그래밍에서 함수는 1급 객체로 취급받기 때문에 위의 예제에서 본 것 처럼 함수를 파라미터로 넘기는 등의 작업이 가능한 것이다. 또한 우리가 일반적으로 알고 개발했던 함수들은 함수형 프로그래밍에서 정의하는 순수 함수들과는 다르다는 것을 인지해야 한다.




💡 참조 투명성

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


함수형 프로그래밍은 참조 투명성을 통해 부수효과를 없애고 프로젝트 디버깅을 좀 더 용이하게 할 수 있다.

이 쯤되면 부수효과, 1급 객체, 순수 함수, 참조 투명성에 대해 감을 잡았을 겁니다.




<💻 함수형 프로그래밍의 장점>

  • 함수형 프로그래밍은 모든 데이터가 변경 불가능(immutable)하고, 함수는 부수효과를 가지고 있지 않다. 따라서 동시성과 관련된 문제를 원천적으로 봉쇄가 가능하다.

비동기 같은 경우 스레드가 동시에 실행되기 때문에 명령형으로 코드를 작성할 경우 코드 디버깅 및 구현이 굉장히 힘들다. 특히 교착상태에 빠질 위험이 존재하고 명령형으로 구현시 복잡함과 고려해야할 요소들이 많다. 이러한 문제는 스레드간 공유 데이터나 상태 값이 변경 가능(mutable)하기 때문에 발생하는 문제이다.

  • 헷갈리는 문제와 오류를 피할 수 있다.
  • 테스트와 디버깅이 용이하다.
  • 더 나은 모듈화와 짧은 코드를 제공한다.
  • 개발 생산성을 높일 수 있다.
  • 가독성이 높은 코드를 작성하기 쉽다.
  • 부수효과를 제거할 수 있다.
  • 함수 단위의 코드 재사용이 쉽다.
  • 프로그램의 동작을 예측하기 쉽다.



<💻 함수형 프로그래밍의 단점>

함수형 프로그래밍은 참조 투명성을 위해 기존의 값은 변경하지 않고 계속해서 필요한 새로운 데이터를 만들어낸다. 앞선 예시에서 배웠던 map, slice, filter와 같은 메서드들 말이다.

다만 이러한 메서드들을 많이 호출하게 되면 메모리 낭비가 발생할 수도 있을 것 같다. 명령형 데이터는 프로세스 내에서 리소스들을 공유하지만, 함수형은 항상 새로운 함수를 호출하기에 공간복잡도 측면에서도 불리하다는 생각이 든다.

많은 프로그래머들은 이에 대한 고민을 했으며 이를 해결하기 위해 immutable.js나 immer 같은 라이브러리를 사용한다.

📚참고 자료

테오의 함수형 프로그래밍(강추)⭐ -> 함수형 프로그래밍을 액션, 계산, 데이터, 방어적 복사, 카피온라이트, 코드의 계층 구조 등등.. 배울 내용도 많고 재밌게 가르켜주신다. 위의 글을 읽고 읽으시면 아! 이게 순수함수구나..! 아 그런거구나~ 라고 말하시게 될 겁니다!
함수형 프로그래밍에 대해
함수형 프로그래밍이란?

profile
하루에 한 가지의 변화를 만들자.

0개의 댓글