Dev/개잘알

함수형 프로그래밍(Functional Programming)

아콩2 2023. 6. 2. 14:59
반응형

1. 함수형 프로그래밍에 대한 이해

프로그래밍 패러다임 (Programming Paradigm)

프로그래밍 패러다임은 프로그래머에게 프로그래밍의 관점을 갖게 하고 코드를 어떻게 작성할 지 결정하는 역할을 한다.

새로운 프로그래밍 패러다임을 통해서는 새로운 방식으로 생각하는 법을 배우게 되고, 이를 바탕으로 코드를 작성하게 된다

  • 명령형 프로그래밍 : 무엇(what)을 할 것인지를 나타내기보단 어떻게(How) 할 건지를 설명하는 방식
    • 절차지향 프로그래밍 : 수행되어야 할 순차적인 처리 과정을 포함하는 방식 (C, C++)
    • 객체지향 프로그래밍 : 객체들의 집합으로 프로그램의 상호작용을 표현 (c++ , java, c#)
  • 선언형 프로그래밍 : 어떻게 할건지 (How)를 나타내기보다 무엇(What)을 할 건지를 설명하는 방식
    • 함수형 프로그래밍 : 순수 함수를 조합하고 소프트웨어를 만드는 방식 (클로저,하스켈,리스프)

함수형 프로그래밍의 등장

명령형 프로그래밍을 기반으로 개발했던 개발자들은 개발하는 소프트웨어의 크기가 커짐에 따라, 복잡하게 엉켜있는 스파게티 코드를 유지보수 하는 것이 매우 힘들다는 것을 깨닫게 되었다. 그리고 이를 해결하기 위해 함수형 프로그래밍이라는 패러다임에 관심을 갖게 되었다.

 

함수형 프로그래밍은 거의 모든 것을 순수 함수로 나누어 문제를 해결하는 기법으로, 작은 문제를 해결하기 위한 함수를 작성하여 가독성을 높이고 유지보수를 용이하게 해준다.

 

유명한 책인 클린 코드의 저자 Robert C.Martin은 함수형 프로그래밍을 대입문이 없는 프로그래밍이라고 정의 하였다.

 

대입문이 없다는 것은 변수를 선언하고 그에 대한 값을 지정해주지 않는다는 의미인데 어떻게 대입문이 없는 프로그램을 작성 하는걸까?

그 동안 명령형 프로그래밍으로 개발을 해왔던 사람들에게 대입문이 없는 프로그래밍은 상당히 생소할 수밖에 없다.

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


왜냐하면 다음과 같이 간단한 코드에서도 변수가 할당되고 값이 대입되기 때문이다.

내부적인 동작을 보면 메모리에 할당된 i 값을 반복해서 변화시킨다.

 

하지만 함수형 프로그래밍에서는 이러한 개념을 사용하지 않는다고 한다. 

함수형 프로그래밍은 대입문을 사용하지 않는 프로그래밍이며, 작은 문제를 해결하기 위한 함수를 작성하는 프로그래밍 패러다임이다.
그렇기 때문에 함수형 프로그래밍에서는 위와 같은 코드를 다음과 같이 해결할 수 있다.

process(10,print(num));

 

process 함수는 첫 번째 인자로 몇까지 iteration을 돌 것인가를 매개변수로 받고 있고,두 번째 인자로 전달받은 값을 출력하라는 함수를 매개변수로 받고 있다.

 

실제 Java 개발자들이 본다면 상당히 띠용스러운 코드인데, 바로 이 점이 함수형 프로그래밍의 중요한 특징이다.

💡 함수형 프로그래밍에서는 출력하는 함수를 파라미터로 넘길 수 있음 

       ➡️ 함수를 1급 시민(First-Class Citizen) 또는 1급 객체 (First-Class Object)로 간주하기 때문

 

명령형 프로그래밍에서는 메소드를 호출하면 상황에 따라 내부의 값이 바뀔 수 있다. 즉, 우리가 개발한 함수 내에서 선언된 변수의 메모리에 할당된 값이 바뀌는 등의 변화가 발생할 수 있다.

 

하지만 함수형 프로그래밍에서는 대입문이 없기 때문에 메모리에 한 번 할당된 값은 새로운 값으로 변할 수 없다.

 

함수형 프로그래밍의 특징

함수형 프로그래밍이란 ? 

부수 효과가 없는 순수 함수를 1급 객체로 간주하여 파라미터나 반환값으로 사용할 수 있으며, 참조 투명성을 지킬 수 있다.

 

부수 효과 , 순수 함수, 1급 객체 ,참조 투명성 각각의 키워드에 대해 자세히 알아보자

 

1 . 부수효과 (Side Effect)

  • 여기서 부수효과란 다음과 같은 변화 또는 변화가 발생하는 작업을 의미한다
    • 변수의 값이 변경됨
    • 자료 구조를 제자리에서 수정함
    • 객체의 필드 값을 설정함
    • 예외나 오류가 발생하여 실행이 중단됨
    • 콘솔 또는 파일 I/O가 발생함

2. 순수 함수 (Pure Function)

  • 그리고 이러한 부수 효과들을 제거한 함수들을 순수 함수라고 부르며, 함수형 프로그래밍에서 사용하는 함수는 이러한 순수 함수들이다.
    • Memory or I/O 의 관점에서 부수효과가 없는 함수
    • 함수의 실행이 외부에 영향을 끼치지 않는 함수
  • 순수 함수의 장점 :
    • 함수 자체가 독립적이며 Side-Effect가 없기 때문에 Thread에 안정성을 보장받을 수 있다.
    • Thread에 안정성을 보장받아 병렬 처리를 동기화 없이 진행할 수 있다.

3. 1급 객체 (First-Class Object)

  • 1급 객체란 다음과 같은 것들이 가능한 객체를 의미한다.
    • 변수나 데이터 구조안에 담을 수 있다.
    • 파라미터로 전달 할 수 있다.
    • 반환값으로 사용할 수 있다.
    • 할당에 사용된 이름과 무관하게 고유한 구별이 가능하다.

함수형 프로그래밍에서는 함수는 1급 객체로 취급받기 때문에 위의 예제에서 본 것 처럼 함수를 파라미터로 넘기는 등의 작업이 가능한 것이다.
또한 우리가 일반적으로 알고 개발했던 함수들은 함수형 프로그래밍에서 정의하는 순수 함수들과는 다르다는 것을 인지해야 한다.

4. 참조 투명성 (Referential Transparency)

  • 동일한 인자에 대해 항상 동일한 결과를 반환해야 한다.
  • 참조 투명성을 통해 기존의 값은 변경되지 않고 유지된다.

명령형 프로그래밍과 함수형 프로그래밍에서 사용하는 함수는 부수효과의 유/무에 따라 차이가 있다.
그에따라 함수가 참조에 투명한지 안한지 나뉘어 지는데, 참조에 투명하다는 것은 말 그대로 함수를 실행하여도 어떠한 상태의 변화없이 항상 동일한 결과를 반환하여 동일하게 (투명하게) 실행 결과를 참조(예측)할 수 있다는 것을 의미한다..

 

이는 어떠한 환경, 어떠한 조건에서도 같은 함수를 호출하면 항상 같은 값을 반환한다는 것을 의미하며, 우리가 멀티코어 환경이나 멀티쓰레드 환경의 개발을 할 때 골머리를 앓는 Race condition등의 문제에 대한 고려비용이 줄어든다는 것을 의미한다.

즉 , 프로세서들이 메모리 영역을 동시에 사용해도 아무런 문제가 없음을 의미한다.

🏷 Race condition ?
두 개 이상의 프로세스가 공통 자원을 병행적으로(concurrently) 읽거나 쓰는 동작을 할 때, 공용 데이터에 대한 접근이 어떤 순서에 따라 이루어졌는지에 따라 그 실행 결과가 같지 않고 달라지는 상황을 말한다.
 Race 의 뜻 그대로, 간단히 말하면 경쟁하는 상태, 즉 두 개의 스레드가 하나의 자원을 놓고 서로 사용하려고 경쟁하는 상황을 말한다.

부작용을 제거하여 프로그램의 동작을 이해하고 예측을 용이하게 하는 것은 함수형 프로그램으로 개발하려는 핵심 동기 중 하나이다.

 

마치며 

함수형 프로그래밍이라는 개념이 아직은 낯선 자바 개발자입니다. 😅😅

 

함수형 프로그래밍의 아주 기본적인 개념 및 특징을 공부했으니 Java에서 어떻게 적용하는지 코드 레벨에서 공부해봐야겠습니다.

다음 포스팅에서는 이 부분을 다루면 되겠네요. 긴 글 읽어주셔서 감사합니다. 

 

출처 

https://cyberx.tistory.com/55

https://mangkyu.tistory.com/111

반응형