1장 패러다임의 전환

함수형 프로그래밍을 알아보기 전에 왜 함수형 프로그래밍이 최근 자주 이야기되고 있는지 짚고 넘어가야 할 필요가 있을 것 같다. 이렇게 약을 팔아야 이 긴 글을 읽어주실 것이니까. 가볍게 읽을 수 있는 서문으로 준비했다. 자 이제 시작해보자.

1.1 프로그래밍 패러다임

패러다임의 사전적 의미를 살펴보면 다음과 같다. "어떤 한 시대 사람들의 견해나 사고를 근본적으로 규정하고 있는 테두리로서의 인식의 체계. 또는 사물에 대한 이론적인 틀이나 체계". 프로그래밍에도 이런 패러다임이 존재한다. 개발자들의 견해나 인식의 체계가 바로 프로그래밍의 패러다임이다. 달리 이야기해서 프로그래밍 패러다임은 기능에 따라 프로그래밍 언어를 분류하는 방법이라고 이야기 할 수 있다. 프로그래밍 패러다임은 크게 2가지로 분류가 되는데 명령형 패러다임(imperative paradigm)과 선언형 패러다임(declarative paradigm)이다.

명령형 패러다임은 때때로 절차적(Procedural)과 동의어로 사용되며, 프로그래밍의 상태와 상태를 변경시키는 구문의 관점에서 연산을 설명하는 프로그래밍들을 말한다. 잘 알려져 있는 C 언어, Java, 포트란, 알골, 파스칼, 에이다 까지가 이 패러다임을 따르고 있다.

선언형 패러다임은 연산을 설명하기 보다는 문제를 해결하는 방법을 제시하는 프로그래밍을 가리킨다. 이러한 패러다임에 속하는 것이 함수형 프로그래밍이며, 잘 알려져 있는 언어로 Scala, Groovy, 클로져, 하스켈 등을 들 수 있다.

코드로 살펴보면 두가지의 차이를 좀 더 명확하게 느낄 수 있다. 예제는 누구나 이해할 수 있는 수준인 1 ~ 10 사이의 정수를 더하는 프로그램을 자바 코드로 준비했다. 아래의 코드를 살펴보자.

코드1.1 명령형의 자바 코드
int sum = 0
for(int i = 1 ; i <= 10; i++ ) {
    sum = sum + i;
}
코드2.1 선언형의 자바 코드
int sum = IntStream.rangeClosed(1, 10).reduce(0, (a, b) -> a+b)

우선 코드1을 살펴보면 전형적인 명령형 프로그래밍으로 우선 sum 변수를 만들고(; 프로그래밍의 상태) 1 부터 10까지를 반복하면서 그 수를 sum에 반복적으로 더한다 (; 그 상태를 변경 ).

코드2에 대해서 살펴보자 IntStream은 자바8에서 추가 된 것으로 IntStream.rangeClosed(1, 10)코드 까지 실행되고 나면 1 ~ 10까지의 배열이 생기게 되고(; 실제로 배열이 생성되는 건 아니지만 지금은 그렇게 생각하자.), 이후에 reduce는 초깃 값은 0이고 각 원소에 대해서 두 개를 더하라고 지시(; 문제 해결 방법을 제시)하게 된다.

자 이제 명령형 프로그래밍과 선언형 프로그래밍에 차이를 조금 느낄 수 있는가? 이 작은 프로그래밍으로 그 구분이 명확하게 되지 않을 테지만 그 조그만 차이를 느끼는 것만으로도 지금은 충분하다.

1.2 과거에서 미래로

그렇다면 왜 세계의 주류 프로그래밍 패러다임은 선언적 프로그래밍이 아니라 명령형 프로그래밍이 되었을까? 오래부터 두 패러다임은 함께 존재했지만 7~80년대가 지나가면서 주류가 된 것이 명령형 프로그래밍이었다. 그 이유는 아마도 기계어 였을 것이다. ADD, MOV, INTO, SUM등의 명령어가 컴퓨터에게나 사람에게나 더 직관적이었다. 1:1로 옮기기만 하면 되었을테니까. 또한 그 시대의 컴퓨터 성능이 그렇게 좋지 못했다는 것도 한 몫 할 것이라고 추측된다. 컴퓨터 성능이 나쁘다는 것은 컴파일러의 성능이 좋지 못하단 이야기가 될 것이고, 컴파일러의 성능이 나쁘다는 이야기는 곧 명령형 프로그래밍이 더 좋은 개발 환경이었다는 이야기가 될 것이다.

그렇지만 기뻐하시라. 더이상 명령형 프로그래밍만 해야 하는 시대는 지났다. 세계에 많은 프로그래머들이 선언형 프로그래밍에 매력을 느껴 앞다투어 이 흐름에 참여하고 있다. 또한 많은 언어들이 선언형 프로그래밍을 지원하며, 컴파일러의 성능 또한 이를 지원하는데 부족함이 없다.

물론 명령형 프로그래밍의 선두, 난공불락의 자바를 넘어서기엔 아직도 갈길이 한참 멀었지만 JDK8에 주요 기능인 Stream API가 들어오면서 익명 함수 사용이 가능해졌다. 아직은 부족함이 많지만 이제 자바로도 선언형 프로그래밍을 하는 것이 가능해졌다는 이야기다. 필자들은 앞으로 자바 진영에서 더욱 선언형 프로그래밍을 받아들이리라고 생각한다.

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

명령형 프로그래밍의 대표는 단연코 객체지향 프로그래밍이다. 그렇다면 선언형 프로그래밍의 대표는 무엇일까? 짐작하고 있겠지만 이는 함수형 프로그래밍이다. 자 이제 드디어 함수형 프로그래밍에 대해서 이야기 해보자.

함수형 프로그래밍에 대해서 위키피디아를 검색해보면 아래와 같이 설명하고 있다.

함수형 프로그래밍은 자료 처리를 수학적 함수의 계산으로 취급하고 상태와 가변 데이터를 멀리하는 프로그래밍 패러다임의 하나이다. 명령형 프로그래밍에서는 상태를 바꾸는 것을 강조하는 것과는 달리, 함수형 프로그래밍은 함수의 응용을 강조한다. 함수형 프로그래밍은 1930년대에 계산가능성, 결정문제, 함수정의, 함수응용과 재귀를 연구하기 위해 개발된 형식체계인 람다 대수에 근간을 두고 있다. 다수의 함수형 프로그래밍 언어들은 람다 연산을 발전시킨 것으로 볼 수 있다.

수학적 함수와 명령형 프로그래밍에서 사용되는 함수는 차이가 있는데, 명령형의 함수는 프로그램의 상태의 값을 바꿀 수 있는 부작용이 생길 수 있다. 이 때문에 명령형 함수는 참조 투명성이 없고, 같은 코드라도 실행되는 프로그램의 상태에 따라 다른 결과값을 낼 수 있다. 반대로 함수형 코드에서는 함수의 출력값은 그 함수에 입력된 인수에만 의존하므로 인수 x에 같은 값을 넣고 함수 f를 호출하면 항상 f(x)라는 결과가 나온다. 부작용을 제거하면 프로그램의 동작을 이해하고 예측하기가 훨씬 쉽게 된다. 이것이 함수형 프로그래밍으로 개발하려는 핵심 동기중 하나이다. 위의 글에서 핵심 키워드를 뽑아보면 수학적 함수, 불변 데이터(;가변 데이터를 멀리함), 재귀, 람다, 부작용을 찾아볼 수 있다. 자 이 네 가지 키워드를 꼭 마음속에 기억해두자. 함수형 프로그래밍을 공부하면서 꼭 기억해야 하는 키워드 들이다.

1.4. 정리

이번 장을 통해서 프로그래밍 패러다임에 대해서 살펴봤다. 명령형 프로그래밍은 "프로그래밍의 상태와 상태를 변경시키는 구문의 관점에서 연산을 설명하는 프로그래밍" 이며, 객체지향 프로그래밍이 있고, 선언적 프로그래밍은 "문제를 해결하는 방법을 제시하는 프로그래밍"이며, 함수형 프로그래밍이 있다는 것을 알아보았다. 함수형 프로그래밍의 4가지 핵심 키워드 수학적 함수, 불변 데이터, 람다, 부작용 이라는 것을 살펴보았다. 자 함수형 프로그래밍에 대해서 어느정도 알아 보았으니 이제 다음으로 넘어갈 준비가 끝났다.

results matching ""

    No results matching ""