개발자 도전기

[STUDY] 함수형 프로그래밍 본문

개발공부/코딩용어

[STUDY] 함수형 프로그래밍

jnnjnn 2024. 3. 21. 20:09

프로그래밍 패러다임

-명령형 프로그래밍 : 절차 지향 프로그래밍, 객체 지향 프로그래밍

 

-선언형 프로그래밍 : 함수형 프로그래밍, 논리형 프로그래밍

 

 

 

 

명령형 프로그래밍과 선언형 프로그래밍의 차이

명령형 프로그래밍은 어떤 작업을 수행하기 위해 명령을 지시하는 방식으로 설계된다.

그 과정에서 변수의 값을 변경하거나 상태를 변화시키는 등의 부작용이 일어날 수 있다.

// 1~10 까지의 값이 i에 할당된다
for (int i = 0; i < 10; i++) {
        System.out.println(i);
    }

 

선언형 프로그래밍은 무엇을 수행해야 하는지 보다는 무엇을 달성해야 하는지 설명하는데 중점을 둔다

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        List<Integer> evenNumbers = numbers.stream()
                                           .filter(num -> num % 2 == 0)
                                           .collect(Collectors.toList());

        System.out.println("Even numbers: " + evenNumbers);

 

위 코드에서는 명시적으로 반복문이나 조건문을 사용하여 짝수를 필터링하는 것이 아니라 , Stream API의 filter() 메소드를 사용하여 짝수인 요소들만 선택한다. 어떻게 짝수를 찾을지에 대한 세부적인 지시는 없지만 오직 원하는 결과물을 얻기 위한 명세만 제공된다.

 

또 다른 선언형 언어의 예시로는 HTML이 있다.

HTML이 어떻게 동작을 수행할지 명령하지 않고 원하는 형태를 선언만 한다면 HTML을 사용할 수 있다.

 

 

 

 

함수형 프로그래밍의 이해

수학적 함수를 사용하고 가변 데이터를 멀리하며 프로그래밍을 하는 패러다임을 말한다.

따라서 부작용이 없고 데이터의 불변성이 유지된다.

**수학적 함수란?**

같은 인자로 실행했을 때 결과값이 무조건 동일한 하나가 나오는 함수

수학적 함수는 순수 함수로 볼 수 있다

 

함수형 프로그래밍에서 함수를 설계할 때는 명령형을 사용하지 않는 것이 목표이다.

 

 

 

함수형 프로그래밍을 사용하는 이유?

멀티 스레드 환경이 대두됨에 따라 부작용이 없고 오류로부터 상대적으로 안전한 함수형 프로그래밍이 주목을 받게 되었다. 명령형 프로그래밍에서는 멀티 스레드 환경에서 두 개의 스레드가 동시에 같은 변수를 증가시키거나 하는 오류가 발생할 수 있다.

 

또한 함수형 프로그래밍을 사용하면 코드가 간편해지므로 가독성이 좋아진다.

함수형 프로그래밍에서는 전역 변수를 사용하지 않고 파라미터를 사용해서 프로그램을 만들기 때문에 문제가 발생했을 때 검토해야 할 범위가 줄어든다. 이는 오류를 줄이고 오류가 발생하더라도 파악하기 쉽게 한다.

 

 

 

함수형 프로그래밍의 특징

1. 순수 함수

: 부작용(side effect)이 없는 함수, 함수의 실행이 외부에 영향을 미치지 않는다.

부작용(side effect)란
-변수의 값이 변경됨
-자료 구조를 제자리에서 수정함
-객체의 필드값을 설정함
-예외나 오류가 발생하며 실행이 중단됨
-콘솔 또는 파일 I/O가 발생함
순수 함수 순수 함수X
sin(x), length() random(), today()

 

다음의 코드는 어떤 인자값을 넣건 동일한 인자를 넣으면 동일한 값이 나오기 때문에 순수함수이다

int add(a+b){
	return a + b;
}

static final result = add(2,3);

 

 

어떻게 변화하는 값 없이 프로그래밍을 할 수 있을까?

함수형 프로그래밍에서는 프로그램을 액션, 계산, 데이터로 구분한다.

-   액션 : 변화하는 값, 호출 시점과 실행 횟수에 의존
-   계산 : 입력과 출력으로 나뉘어져 값을 처리함
-   데이터 : 이벤트에 대한 사실

변화하는 값(액션)과 일정한 결과를 도출하는 계산을 분리함으로 계산을 순수함수로 만들 수 있다.  

 

 

2. 불변성

 

함수형 프로그래밍에서는 데이터가 변하지 않고 불변해야한다.

데이터의 변경이 필요한 경우, 데이터를 그대로 가져다 사용하지 않고 데이터를 복사하여 그 데이터의 복사본을 사용한다.

// 불변성을 유지하는 예시
const immutableArray = [1, 2, 3, 4, 5];

// 배열의 요소를 변경하지 않고 새로운 배열을 생성하여 반환
const doubledArray = immutableArray.map(num => num * 2);

console.log(immutableArray); // [1, 2, 3, 4, 5]
console.log(doubledArray);   // [2, 4, 6, 8, 10]

 

 

3. 1급 객체와 고차 함수

함수형 프로그래밍에서는 함수가 1급 객체가 된다.

1급 객체의 특징은 다음과 같다

  • 변수나 데이터 구조에 담을 수 있다
  • 파라미터로 전달 할 수 있다
  • 리턴값으로 사용할 수 있다
const addTwo = (num) => num + 2;
const multiplyTwo = (num) => num * 2;
const transform = (numbers) => numbers.map(addTwo).map(multiplyTwo);

console.log(transform([1, 2, 3, 4])); // [6, 8, 10, 12]

(예제는 자바 스크립트)

 

이런 1급 객체인 함수를 인자나 값으로 받는 함수를 고차 함수라고 한다.

// 고차 함수
const addInform = (name) => (age) => age + name;
const jongmin = addInform("종민"); // 나이 입력을 대기하고 있는 상태

console.log(jongmin("96")); // 96종민

 

위 코드는 addInform이 name을 인자로 받고 age => age + name; 함수를 결과값으로 반환하고 있다.

 

 

멀티 패러다임

자바스크립트, 그리고 우리가 사용하는 자바 등은 멀티 패러다임 언어이다. 자바는 객체 지향 언어를 추구하면서 동시에 함수형 프로그래밍을 구현할 수 있는 환경을 제공한다.

상황에 맞는 패러다임을 사용해서 유연하게 대처한다면 더 좋은 코드를 짤 수 있을 것이다.