시작하는 중

함수형 프로그래밍 본문

자바스크립트

함수형 프로그래밍

싱욱 2023. 5. 15. 23:56

유인동님의 함수형 프로그래밍 기본편

유인동님의 함수형 프로그래밍 응용편

쏙쏙 들어오는 함수형 코딩

 

9일부터 지금까지 팀 프로젝트 + 강의 두개 + 책 한권을 읽느냐고 포스팅도 못한 것 같다.. 라우터도 만들어봐야하고 리액트 쿼리도 정리해야하고 취준도 해야하는 바쁜 시간인데, 너무 재밌어서 좀 빠진 것 같다.

 

코드와 프로그래밍에 대한 고민을 많이 했던 시간인 것 같다. 함수형 프로그래밍이 왜 필요한가, 어떤 패러다임인가를 생각해볼 수 있었다. 그리고 프로그래밍에 대한 시각을 하나 더 생성하는 인사이트를 기른 시간인 듯 싶다.


책에서 말하는 함수형 프로그래밍의 패러다임

 

함수형 프로그래밍은 함수를 순수 함수로써 데이터를 다루고자 함이다. 하지만, 현재 프로덕트들에서는 온전한 순수함수들만 존재할 수가 없다. HTTP 요청을 보내던가, 렌더링하는 요소를 바꾸던가 하는 것들은 순수 함수를 벗어나지만, 이는 프로그램 존재의 이유이다. 이들이 없으면, 계산기와 다른 것이 없다. 즉, 액션은 반드시 필요한 것이다.

 

그래서 책에서는 이를 최소화하고자 하고 있다. 함수를 데이터 + 계산 + 액션으로 나누고, 전역변수를 최소화하며 계산으로 원하는 데이터까지 가공하여 액션을 취하는 방식을 택하고 있다.

 

여기서 데이터는 항상 불변성이다. 이 데이터 자체를 변경하는 것을 지양하고 있다.

let numbers = [1, 2, 3, 4, 5];

let newNumbers = numbers.map(function(number) {
    return number + 1;
});

console.log(numbers); // [1, 2, 3, 4, 5]
console.log(newNumbers); // [2, 3, 4, 5, 6]

이렇게 늘 계산된 값을 새로운 변수에 할당하여 이전의 데이터의 상태를 변경하지 않아야한다.

 

계산은 항상 어떤 값을 넘겨도, 동일한 출력을 반환하는 순수 함수이다. 어떤 계산을 기반으로 새로운 변수에 할당해야하는 것이다. 위의 예시처럼, 모든 것은 함수의 입출력으로만 이를 해결해야한다. 쉽게 말해서, 전역변수를 사용하는 것이 아니라 함수의 인자로 데이터를 받아, 그 데이터를 계산하고 return해주는 것을 말한다.

 

액션이란, 그 이외의 작업들을 말하고 있다. 액션은 전역변수를 가져와서 이를 직접 변형시키는 것과 이메일을 보낸다거나, API 요청을 보내는 등의 계산과 관련이 없고, 그 실행 시점이 중요한 함수들이다.

 

예를 들어, input 태그가 있고 이 태그에 인풋을 담아서 API 요청을 보낸다고 했을 때, 인풋에 담긴 value의 값이 무엇인가에 따라서 요청이 다르게 갈 수 있다.

또한, DB를 읽는 것도 액션이다. 데이터를 읽어오는 것처럼 보이지만, DB의 데이터가 바뀔수도 있기 때문에, 호출하는 시점이 중요하다. 때문에 액션이라고 한다.


 

 

이건 기본 중의 기본이다. 책에서는 이 밖에도 함수형 사고로 로직을 바라보는 방법, 계층형 설계, 일급 추상등의 개념도 다루고 있다. 이해도 부족하고, 지적 재산권 때문에 모든 내용을 나열하기도 좀 그래서 .. 여튼 많은 것들을 배울 수 있는 시간이었다.

 

강의에서도 JS ES6+에서 적용된 이터레이터 같은 개념들을 활용해서 더 많은 것들을 할 수 있다. 특히 유인동님은 함수가 일급 객체라는 사실을 기본으로 한 많은 것들을 알려주시는데, 이해하는데 좀 시간이 걸렸긴 해도 강의의 내용은 이해할 수 있었고 적용해볼 수 있었다.


 

내가 이해해본 함수형 프로그래밍의 특징

 

1. 예측이 가능하다.

어떤 데이터가 어떤 함수에 들어간다면 어떻게 동작할지 쉽게 예측할 수 있다는 것이다. 이는 함수형 프로그래밍이 지향하는 바이자 패러다임이다.

 

2. 디버깅하기가 쉽다.

어떤 지점에서 버그가 발생했는가를 쉽게 찾을 수 있다. 이유는, 어떤 데이터에서 잘못됬는지를 변수를 기반으로 찾아가면 찾을 수 있기 때문이라고 생각한다.

 

3. 메모리와 시간 복잡도의 위험

불변성을 유지하기 위해 데이터 복사가 많이 일어난다. 메모리 적 측면에서 부하가 올 듯해도 자바스크립트의 가비지 컬렉션은 많이 발전해왔다. 때문에, 잘못된 참조는 함수형 프로그래밍에서 일어날 일이 없는 것이니깐, 메모리 적 측면에서는 큰 걱정을 하지 않아도 된다.

 

시간 복잡도에서도, 배열에서 어떤 값 하나를 바꾸는 것은 함수형 프로그래밍에서는 복사 + 할당이 걸리기에 당연히 더 오래걸릴 수도 있다.

 

하지만 모든 것은 최적화를 해주어서 큰 문제가 되지 않는다면 굳이 계산을 액션으로 바꿀 이유는 없어보인다고 생각한다.


그리고 이런 개념들은 프레임 워크에서도 적용되고 있다.

 

recoil을 쓰면서 알게된 것인데, 리코일은 상태를 가장 작은 atom(원자)단위까지 쪼개어 이를 순수 함수로 접근할 수 있도록 하고 있다. 또한, React를 사용하다보면, useState의 상태를 직접 접근하여 업데이트하는 것을 막는다는 것도 볼 수 있다. 뿐만 아니라, 리액트 훅도 순서를 보장해야한다며, 조건문 같은 곳에서 사용할 수 없게 하는 것을 접해봤을 것이다.

 

이 모든 것은 데이터의 불변성을 유지하기 위한 것이다. 리액트에서 우리는 상태를 useState의 dispatcher 함수로만 업데이트하는 것처럼 데이터에 직접 접근하는 것을 막고, 그 데이터는 언제나 그 데이터임을 유지해야하는 것이 바로 데이터의 불변성이다.

화내지마세요

 

그리고, 내가 정리했던 글 중에 다음과 같은 말이 있다.

https://mystacks.tistory.com/76 리액트의 개념적 모델 글 중에서 리액트의 핵심 전제파트에서

웹 페이지의 UI는 단순히 데이터를 다른 형태의 데이터로 반영한 것에 불과하기에 순수 함수로써 동일한 입력이라면 동일한 출력을 가진다는 전제가 깔려 있다.

라는 말이 있다. 이 말은 함수형 프로그래밍과 일치한다. 웹 페이지의 UI를 구성하게 하는 함수는 순수 함수로써 해야하는 것이다. 

 

책과는 다르게 DOM에 무언가를 그리는 것도 계산의 영역에 포함하는 듯 싶은데.. 나도 동의하는 바이다. 결국 어떤 컴포넌트가 렌더링된다는 것은, Props나 어떤 State에 기반하여 return되는 것이기에 이런 생각을 하는 것 같다.


여태껏 let을 많이 써왔다. 충분히 통제할 수 있기 때문이다.. 하지만 함수형 프로그래밍에서는 이를 지향하고 있다. 또한, 컴포넌트 내에서 전역변수로 상태들을 참조하기도 하고 그랬는데, 조금은 지향해야할 듯 싶기도 하다.

 

어떻게 마무리 짓지?? 정말 많이 배운 시간이었는데, 아직 적용하기엔 부족한 것 같아서 책을 좀 더 읽고 적용해보려고 한다. 할게 산더미야~~

 

 

reference

유인동님의 함수형 프로그래밍 기본편

유인동님의 함수형 프로그래밍 응용편

쏙쏙 들어오는 함수형 코딩