최근 면접에서 함수형 프로그래밍을 사용해야 하는 이유를 설득해 보라는 요청을 받았습니다. 제가 꾸준히 함수형 패러다임에 대해 관심을 가지고 공부를 하고 있지만, 상대방을 조리 있게 말로 설득하는 능력은 많이 부족하여 어버버거렸습니다. 그래서 이번 기회에 함수형 패러다임의 세 가지 주요 개념에 대해, 저의 생각들을 글로 정리해 보았습니다.
1. 일급 함수(First-class function)
일급 함수는 함수를 값으로서 다룬다는 것을 의미합니다. 즉, 변수에 함수를 할당할 수 있다는 뜻입니다. 변수를 값에 할당할 수 있다면 어떤 일이 일어날까요?
프로그램에서 변수를 이리저리 전달하는 것과 같이, 함수를 이곳저곳에 주고받을 수 있습니다. 주고받은 함수를 활용할 수 있으니, 자연스럽게 재사용성이 증가합니다.
리액트로 개발을 하다 보면 자식 컴포넌트에 함수를 전달하고 자식은 프로퍼티로 받은 함수를 호출하는 패턴을 종종 사용하실 것입니다.
이 외에도 React.memo 와 같은 HOC, 리액트의 훅, 다양한 Array 메소드들에도 이러한 일급 함수의 개념이 적용되어 있습니다.
2. 순수 함수
순수 함수라는 것은 동일한 입력에 동일한 출력을 하는 함수를 의미합니다. 수학적 용어로 설명하자면 결정론적 함수입니다.
동일한 입력에 동일한 출력을 하는 것이 왜 중요할까요? 바로 “안전”하기 때문입니다. 예를 들어, 키보드의 “a” 버튼을 눌렀을 때, “a” 가 출력되는 게 아니라 “z”가 출력된다면 어떨까요? 더 나아가서 누를 때마다 무작위의 알파벳이 출력되면 어떨까요? “a” 출력을 기대하지만 실제 동작은 그렇지 않기에 불안정합니다. 불안정은 상황을 제어하는 능력을 저하시킵니다.
사람은 누구나 안정감을 찾으려는 본능이 있습니다. 불안정이 커지면 예측할 수 없는 돌발 상황이 발생할 확률이 높아지고, 이는 신변에 위협을 가할 수 있기 때문이죠. 그래서 사람은 늘 주변 상황을 안정적으로 제어하고 싶어합니다. 안정적으로 주변을 제어하기 위해서는 특정 함수가 내가 기대하는 대로 동작하는 것을 보장해야 합니다.
순수 함수는 이러한 예측 가능성과 위기 관리 측면에서 아주 좋은 수단입니다. 일관된 동작을 보장하니까 결과를 예측하기 쉬워지고, 예측하기 쉬워지면 위기를 관리하기 쉬워집니다.
TDD를 들어보신 분이라면 “테스트하기 용이하다”는 말도 들어보셨을 것입니다. 일관된 동작을 하는 함수는 내가 원하는 동작을 수행하는지 확인하기 편리합니다. 이는 디버깅하기 쉽다는 것을 의미하고, 테스트 코드를 작성하기 위해서는 함수를 순수하게 작성하는 것이 중요합니다.
순수 함수의 개념은 리액트의 함수 컴포넌트에도 적용됩니다.
2.1. 부수효과
순수 함수는 동일한 입력에 동일한 결과를 반환합니다. 반대로 말하자면 입력이 바뀌지 않는 한 영원히 동일한 렌더링을 보여준다는 뜻입니다.
웹의 기능이 다양해지고 사용자들의 요구가 늘어남에 따라, 생동감 있는 웹을 구현하기 위해서는 상태를 변경하거나 애니메이션을 시작하는 것과 같은 변화가 필요합니다. 이 변화를 부수 효과(side effect)라고 부르며, 이러한 부수 효과는 말 그대로 렌더링 중이 아닌 사이드에서 발생합니다.
리액트에서는 이러한 부수 효과(다양한 기능)를 훅을 통해 제공하고 있습니다. 예를 들어 useState 는 컴포넌트가 시간에 따라 변할 수 있는 상태를 가지도록 만들어주고, useEffect 는 컴포넌트가 외부 시스템과 상호작용할 수 있게 해줍니다.
3. 불변성
불변성이란 한 번 만든 값은 변경하지 않고, 변경해야 한다면 새롭게 만드는 것을 말합니다.
위 코드에서 useEffect 의 의존성 배열에는 객체인 gildongRef.current 가 들어있습니다. 이 값은 객체이며, 버튼의 동작은 가변적으로 값을 변경하고 있고, 렌더링을 트리거하지 않기 때문에 버튼을 아무리 눌러도 useEffect 훅이 호출되지 않습니다.
마무리
이렇게 함수형 패러다임의 주요 개념인 일급 함수, 순수 함수, 불변성의 장점을 정리해보았습니다.
일급 함수의 경우에는 함수를 주고받을 수 있다는 점과 동작의 조합의 관점에서 바라보았고 순수 함수와 불변성은 예측 가능성과 위험 관리의 측면에서 바라보았습니다.
원론적인 얘기만 하기보다는 체감할 수 있는 예제와 리액트에 적용된 부분들을 같이 곁들였는데, 독자 여러분들이 잘 느끼셨을지 모르겠네요. 독자분들은 설득이 되셨나요? 함수형 패러다임의 매력을 느끼셨나요?
개인적으로 동작을 작은 함수들을 조합해 나가는 바텀-업 방식은 함수형 프로그래밍을 공부했을 때 신선한 충격이었습니다. ‘이 동작을 이렇게 조합해서 구현한다고?’ 라는 생각을 했었습니다. 저는 아직 그런 경지에 오르지는 못했지만, 제가 상상할 수 있는 한계 밖을 본 것만으로도 충분한 가치가 있다고 생각합니다.
여러분들은 함수형 패러다임에 대해 어떻게 생각하시나요? 생각을 자유롭게 댓글로 달아주세요!