함수형 프로그래밍

이 글은 윤준성의 개발꼬맹이 시절, 혼자 노션에 공부하며 정리해둔 것 중 괜찮은 것을 추려올린 글입니다. 기술블로그 글 기고 목적으로 작성되지 않아, 가독성이 좋지 않거나 알 수 없는 워딩이 있을 수 있습니다.

번역 - 함수형 프로그래밍이란 무엇인가?

함수형 프로그래밍이란?

  1. 순수함수(pure function)를 조합하고
  2. 공유 상태(shared state), 변경 가능한 데이터(mutable data)를 피하는
  3. 선언형(declarative)의 프로그래밍 방법

순수 함수(Pure Function)

  1. 같은 입력이 주어지면, 같은 출력을 반환하고,
  2. 부작용(side effect)가 없다!

부작용(Side Effects)

  • 함수 외부의 전역/멤버 변수 값 수
  • 콘솔에서 로깅
  • 파일 쓰기 작업 / 외부와 소통
  • 부작용을 동반한 다른 함수 호출

공유 상태(Shared State)

공유하고 있는 범위(scope) 내에 있는 변수, 객체, 메모리 공간

공유 상태에 관련된 두가지 문제

  1. 경쟁 조건(race condition)에 관한 문제

    • 게임 속 캐릭터 객체가 있다.
    • updateAvator()로 프로필 사진을 변경 요청을 서버에 보낸다.
    • 이 요청을 첫번째로 보내고, 두번째로 또 보냈는데… 두번째 응답이 먼저 도착한다면????
  2. 함수 호출 순서에 관한 문제
const x = {
	val: 2
};

const x1 = () => x.val += 1;
const x2 = () => x.val *= 2;

x1();
x2();

console.log(x.val); // 6

//만일 호출 순서가 달랐다면?

x2();
x1();

console.log(x.val); // 5

⇒ 함수형 프로그래밍스럽게 바꾼다면?

const x = {
	val: 2
};

const x1 = x => Object.assign({}, x, { val: x.val + 1 });
const x2 = x => Object.assign({}, x, { val: x.val * 2 });
// 전역변수 x의 속성 값을 직접 바꾸는 것이 아닌, 아예 새로운 객체를 반환!

console.log(x2(x1(x))).val); // 6

⇒ 이로써 공유상태의 불변성을 유지하는 것이 아주 중요하다!

⇒ 명령형 흐름 제어 보다는 합성함수를 이용하자!

선언형 vs 명령형(Declarative vs Imperative)

  • 숫자 배열의 각 원소들을 두 배로 한 새 배열을 반환하는 함수를 각각의 패러다임으로 짜보자

명령형

const doubleMap = numbers => {
  const doubled = [];
  for (let i = 0; i < numbers.length; i++) {
    doubled.push(numbers[i] * 2);
  }
  return doubled;
};

console.log(doubleMap([2, 3, 4]));
  • for, if, switch, throw 등의 구문(statement)을 자주 사용한다.

선언형

const doubleMap = numbers => numbers.map(n => n  * 2);

console.log(doubleMap([2, 3, 4]));  // [4, 6, 8]
  • 표현(expression)에 더 의존한다
  • 아래 것들이 표현의 예시
2 * 2
doubleMap([2, 3, 4])
Math.max(4, 3, 2)

Written by@Junsung Yoon
Software Enginner focusing on Node.js

GitHubLinkedIn