본문으로 바로가기
728x90

TL;DR 함수형 프로그래밍

 

1. 순수함수 → 코드를 액션과 계산, 데이터로 분리하자. 특히 액션에서 계산을 분리하는 코드를 작성하자.

 

 

// 함수형 프로그래밍 관점에서 분리해보자.
function App() {

  // 데이터
  const [count, setCount] = useState(0)

  // 계산
  const increase = (value) => value + 1

  // 액션
  const onClick = () => setCount(increase(count))
  
  // 선언적 패턴
  return <button onClick={onClick}>{count}</button>
}

액션과 계산을 확실히 분리해서 액션을 최소화하고 계산함수를 많이 만들어서 관리를 하는 것을 목표로 합니다.

// 잘못 분리된 계산함수
// 계산은 반드시 입출력으로 이루어져야 하며 같은 입력에 대해서는 항상 같은 출력값을 내놓아야 합니다.
const increase = () => {
  ...
  setState(count + 5)
}

const onClick = () => {
  ...
  increase()
}

 

2. 불변성 → 카피온라이트와 방어적복사를 이용하여 불변성을 유지하자.

 

값을 조회하고 변경하여 출력값을 만들어야 할때 원본의 값을 복사해서 수정한다면 외부세계에 영향을 끼치지 않는 카피 온 라이트(Copy on Write) 혹은 얕은 복사를 사용하여 계산하자.

// spread 표기법을 쓴다면 더 간결하게 작성할 수 있다.
const increase = (arr) => [...arr, arr[arr.length - 1]] // arr
const setObjectName = (obj, name) => ({...obj, name}) // obj

// 중첩된 객체에 대한 카피 온 라이트
// 계산 (너무 복잡)
const someCalcuation = (obj, value = 200) => {
  return {
    ...obj,
    foo: {
      ...obj.foo,
      bar: {
        ...obj.foo.bar,
        baz: value
      }
    }
  }
}

// immer.js (라이브러리 사용해보자)
const nextState = produce(obj, draft => draft.foo.bar.baz = 200)

라이브러리를 통해 수정할 수 없어 계산 함수에 액션이 존재하게 되거나 혹은 mutaion 함수를 이용해야만 하는 경우에는 방어적 복사를 사용하자.

// 액션을 써야하지만 라이브러리 함수라서 내가 수정할 수가 없다.
import someActionLibray from "lib"

const someCalcuation = (obj, value) => {
  const clone = structuredClone(obj); // 완전한 clone을 만들어 낸다.
  someActionLibray(clone, value) // clone값을 변경해도 원본은 변하지 않는다.
  return clone
}

최근 structuredClone() 이라는 API가 Native 기능이 되었기에 이 API를 사용하면 됩니다.

 

3. 선언적 패턴 → 계층형 설계와 추상화 벽을 이용하여 무엇과 어떻게를 구분하여 좋은 설계를 유지하자.

 

 

코드를 작게 분리하면 좋은 점

재사용하기 쉽다.
유지보수하기 쉽다.
테스트하기 쉽다.

 

이렇게 액션, 계산, 데이터로 코드를 구분하고 계층을 만들고, 계층을 넘나들지 않는 코드를 짜다보면 자연스럽게 좋은 코드의 구조를 만들 수 있고 계산의 비중을 높여가고 계층을 넘나들지 않도록 코드를 쪼개다보면 좋은 설계과 리팩토링에 대한 좋은 근거가 될 수 있습니다.

 

함수형 프로그래밍의 개념을 익히는 것은 좋은 코드를 볼 수 있는 새로운 관점을 얻게 되는 과정입니다.

전부 100% 함수형으로 바꾸는 것이 더 나은 결과는 또 아니었기에 함수형 프로그래밍에 집착해서 더 나은 방식을 뒤로 하고 굳이 불편한 길을 걸어서도 안됩니다. 언젠나 이 밸런스가 중요합니다.

 

https://velog.io/@teo/functional-programming

 

다시 쓰는 함수형 프로그래밍

> 참 좋은데 어떻게 표현할 방법이 없네... 오랜 기간 개발을 공부하게 되면서 여러가지 패러다임의 변화를 겪었는데 그 중에서 인상깊었던 것중에 하나는 객체지향 패러다임에서 함수형 패러다

velog.io