함수형 프로그래밍이란 무엇이고, 왜 사용할까?

Lee Yechan·2023년 7월 19일
0

프로그래밍 지식들

목록 보기
2/10
post-thumbnail
post-custom-banner

이 글에서는…

함수형 프로그래밍에서 사용되는 용어를 정리하고, 함수형 프로그래밍을 왜 사용해야 하는지에 대한 개인적인 의견을 소개한다.


용어 정리

순수 함수

순수 함수는 ‘동일한 인자가 전달되면 항상 동일한 결과를 반환하는 함수’라고 정의된다.

순수 함수는 아래와 같은 특징을 가진다.

  • 참조 투명성: 함수 바깥의 데이터를 참조하지 않는다.
  • side effect가 없다: 함수 안의 동작이 바깥에 영향을 주지 않는다.
  • 불변성: 데이터가 한 번 만들어지면 변경되지 않는다.
  • lazy evaluation: 값이 필요할 때까지 계산을 미룬다.

즉, 수학에서의 함수와 같이, 어떤 값이 주어지면 인자가 아닌 그 어떤 것에도 영향을 주거나 받지 않은 채로 그 인자를 처리한 값을 반환하는 함수인 것이다.

여기에서 ‘불변성을 만족시키려면 너무 computational cost가 큰 것 아닌가?’ 라는 생각이 들 수 있을 것이다.

프로그램은 필연적으로 정해진 코드에 따라 데이터를 변경시키며 동작해야 하기 때문에, 불변성을 만족시키면서 값을 변경하기 위해서는 변경을 하려는 데이터가 복사되어야 하기 때문이다.

그래서 최적화를 위해 lazy evaluation이 필요하다. 계산을 계속 미루다가 데이터가 처리된 결과 값이 필요할 때가 오면, 그제서야 지금까지 그 데이터에 적용되어야 하는 연산들이 무엇인지 살펴보고 처리할 수 있기에, 불필요한 데이터의 복사를 막고, 필요 시 연산의 순서를 조정하는 등의 최적화가 가능하다.

일급(first class) 함수

‘일급’이라는 용어는 모든 것을 값으로 취급한다는 의미를 가진다. 즉, 숫자 등의 값이 있는 자리에 함수를 집어넣을 수 있다면 일급 함수이다.

자세한 조건은 다음과 같다.

  • 함수를 변수에 저장할 수 있다.
  • 함수를 배열에 저장할 수 있다.
  • 함수를 객체에 저장할 수 있다.
  • 언제든 필요할 때 함수를 만들 수 있다.
  • 함수에 함수를 전달할 수 있다.
  • 함수가 함수를 반환할 수 있다.

고차원 함수 (higher order function)

특히, 위 조건 중에서도 마지막 두 개의 정의를 사용하는 함수를 고차원 함수라고 한다.

함수형 프로그래밍에서는 고차원 함수를 이용해, 더 복잡하고 다양한 기능들을 구현할 수 있다.

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

함수형 프로그래밍에서는 값을 추상화의 단위로 바꾸며, 결국 그 바뀐 값들로 소프트웨어 시스템을 만들게 된다.

함수형 프로그래밍에서는

  • 추상화를 식별해 함수로 만든다.
  • 기존 함수를 이용해 더 복잡한 추상화를 만든다.
  • 기존 함수를 다른 함수에 제공해 더 복잡한 추상화를 만든다.

따라서, 함수형 프로그래밍 패러다임을 이용하면

  • 일급 함수의 특징을 활용하여, 함수를 이용해 소프트웨어 시스템을 단계적으로 추상화함과 동시에
  • 순수 함수의 특징을 활용하여, 더 안전하고 예측 가능하게 프로그래밍을 할 수 있도록

하는 장점을 가져온다.


함수형 프로그래밍, 왜 사용할까?

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


함수형 프로그래밍 패러다임에서는 처음에는 의미 없는 데이터들에 함수를 통해 연산하여 결국 큰 시스템을 만드는 반면, 객체지향 프로그래밍 패러다임에서는 프로퍼티와 메서드를 한데 묶은 단위인 객체를 통해, 그 객체들이 서로 협력하여 시스템의 일들을 처리하도록 한다.

함수형 프로그래밍에서는 함수가 추상화의 단위였다면, 객체지향 프로그래밍에서는 객체가 추상화의 단위인 것이다.

마찬가지로 함수형 프로그래밍에서는 함수가, 객체지향 프로그래밍에서는 객체가 데이터 은닉, 또는 캡슐화의 단위이다.

즉, 함수형 프로그래밍과 객체지향 프로그래밍은 같은 목표를 다른 방법으로 성취하는 셈이다.


그런데 지금까지의 설명만으로는 함수형 프로그래밍과 객체지향 프로그래밍 패러다임이 양립 불가능한 것처럼 보일 수 있지만, 사실은 두 가지 패러다임을 동시에 사용할 수 있다.

예를 들어, 대표적인 멀티 패러다임 언어인 자바스크립트는 객체지향 프로그래밍 패러다임과 함수형 프로그래밍 패러다임을 동시에 사용할 수 있는데, 예를 들어 (프로토타입 기반) 클래스와 같은 객체지향 도구를 활용하면서 map, reduce, filter와 같은 함수형 프로그래밍 도구를 사용할 수 있는 것이다.

함수형 프로그래밍과 객체지향 프로그래밍 모두 장점과 단점을 가지므로, 한쪽 극단에만 몰리지 말고, 경우에 따라 더 나은 것을 활용하는 게 가장 좋겠다는 게 나의 생각이다.


객체지향 프로그래밍은 아래와 같이 장단점을 정리할 수 있다.

장점

  • 상속과 다형성을 통해, 데이터와 그에 대한 연산을 구조화해 나타낼 수 있다.
  • 객체들간의 협력과 소통을 통해 프로그램이 동작한다는 점이 실세계의 동작과 비슷하여 이해하기 쉽다.

단점

  • 객체의 상태와 상호작용을 관리하기 위해서는 외부 문맥의 이해가 요구된다.
  • 예기치 않았던 side effect가 생길 수 있다.

함수형 프로그래밍은 아래와 같이 장단점을 정리할 수 있다.

장점

  • 데이터의 불변성 때문에 병렬화에 유리하다.
  • side effect로 인해 발생하는 버그의 소지가 적고, 디버깅 등의 코드 관리에 유리하다.

단점

  • 러닝 커브가 가파르다.
  • 성능 상 오버헤드가 존재할 수 있다.

그밖에도 함수형 프로그래밍을 이용하면 연산의 과정이 아닌 연산의 결과에만 관심을 가지기 때문에, 연산의 과정을 추상화한 경우가 많아 일반적으로 코드의 길이가 짧아진다.

하지만 코드의 길이가 짧아진다는 것만으로는 장점이 될 수 없고, 그로 인해 코드가 더 이해하기 좋아지고 유지보수하기 쉬워지느냐 하는 것은 다른 문제이기 때문에, 장점에도 단점에도 넣지 않았다.


함수형 프로그래밍, 언제 사용할까?

따라서 위 내용들을 정리하면, 객체지향 프로그래밍 패러다임이 가지고 있지 못한 함수형 프로그래밍만의 장점들을 활용하기 위해 함수형 프로그래밍을 사용한다고 할 수 있다.

그리고 이러한 장점의 효용이 객체지향 프로그래밍의 것을 넘어서는 분야, 도메인, 모듈 등에서 함수형 프로그래밍을 사용할 수 있을 것이다.

예를 들어 빅데이터를 처리하는 프레임워크인 Apache Spark에서는 Scala라는 함수형 프로그래밍 언어를 활용하는데, 빅데이터의 특성상 병렬화를 자주 이용하며, 버그가 발생했을 때 프로세싱, 시간, 비용적 손실이 크기 때문일 것이다.


사실 우리에게 더 익숙한 것은 객체지향일 것인데, 함수형 프로그래밍을 도입하자니 새로 무언가를 배워야 해서 불편한 느낌이 들 것이다.

하지만 앞서 살펴봤다시피 함수형 프로그래밍이 가지는 장점도 있고, 연산의 병렬화의 중요성이 커지고 있으며, 각종 프로그래밍 언어에서도 함수형 프로그래밍 패러다임을 차용한 최신 기능들을 탑재하는 요즘에는 함수형 프로그래밍 패러다임을 익히는 것은 더이상 선택의 영역이 아니라고 생각한다.

따라서 이 섹션의 제목을 ‘함수형 프로그래밍, 언제 사용할까?’라고 거창하게 달아두었지만, 나는 그 질문에 대한 답이 ‘지금’이라고 생각한다.

함수형 프로그래밍 패러다임을 이용해 무언가를 만들어보고, 본인만의 함수형 프로그래밍과 객체지향 프로그래밍에 대한 철학과 기준이 생기면 프로그래밍을 하는 데에 있어 선택할 수 있는 범위가 늘어나고, 이는 더 좋은 선택을 할 가능성을 늘려줄 것이다.


references

함수형 자바스크립트 (마이클 포거스, 한빛미디어)
Javascript - 자바스크립트를 통해 배우는 순수 함수의 개념
순수 함수란? (함수형 프로그래밍의 뿌리, 함수의 부수효과를 없앤다)

profile
이예찬
post-custom-banner

0개의 댓글