[Kotlin]함수형 프로그래밍 초간단 이해하기
함수형 프로그래밍. 개발하다 보면 한 번쯤은 들어봤을 법한 말이다. 안 들어봤다 해도 지금 이 순간 봤으니 들어본 것이라 할 수 있다. 아무튼 일단 함수형 프로그래밍을 하기에 앞서 무엇인지 모르는 분들을 위해 잠깐 설명하고 넘어가겠다.
함수형 프로그래밍?
개발을 갓 접했을 때 꼭 듣는 용어가 있다. C로 대표되는 절차지향 프로그래밍과 C++, JAVA로 대표되는 객체지향 프로그래밍이 대표적이다. 이 둘은 오늘 살펴볼 함수형 프로그래밍과 더불어 프로그래밍 방식에 한 축이라고 볼 수 있다. 해서 동시에 간단히 알아보자면 다음과 같다.
- 절차지향 프로그래밍 : 로직 위주로 동작하는 프로그래밍 방식. ex) C
- 객체지향 프로그래밍: 클래스가 프로그래의 최우선이 되는 프로그래밍 방식. ex) C++, JAVA
- 함수형 프로그래밍 : 함수의 유기적 연결 및 동작이 프로그램의 최우선이 되는 프로그래밍 방식. 함수가 일급 객체로써의 의미를 가짐. ex) Kotlin, javascript
함수형 프로그래밍이 뭔지는 알겠는데 그러면 일급객체는 무엇일까? 쉽게 설명하자면 포함관계를 갖는 데 있어서 가장 최상위 레벨이라 생각하면 되겠다. 객체 지향 프로그래밍의 대표주자인 JAVA에서는 클래스*가 변수, 함수를 클래스 안에 둘 수 있는 것을 넘어서 클래스마저도 안에 품을 수 있다.(명확한 표현은 아니지만 의미는 전달 됐으리라 생각한다.) 이와 마찬가지 원리로 함수형 프로그래밍에선 함수가 그 안에 다른 변수, 함수, 클래스 등을 담을 수 있기 때문에 일급 객체로서 의미를 갖는다.(담을 수 있다는 것은 선언 및 정의가 가능하다는 것을 뜻한다.)
일급 객체로서의 함수
일급 객체라는 것은 앞서 설명했듯이 변수, 함수, 클래스 등을 함수 구성요소로 둘 수 있다는 것이다. 즉 다음과 같이 구성이 가능하다.

handSome09라는 함수를 살펴보면 pikachu라는 상수(변수), pokemon이라는 함수, 그리고 SubHandSome이라는 클래스를 담고 있다. 모든 구성 요소를 담을 수 있는 만큼 함수가 일급 객체로서 역할을 하고 있다고 볼 수 있다. 하지만 이것이 완전한 일급 객체로서의 역할을 의미하지는 않는다. 함수를 변수처럼 사용할 수 있어야 진정한 완전한 의미를 갖게 된다.
함수를 변수처럼
함수를 변수처럼 사용하려면 어떻게 해야 할까. 우선 함수를 변수(상수)에 대입한다는 상식적인 접근이 우선시 되어야 할 것이다. 그런데 무턱대고 변수에 함수를 대입하면 될까?

아쉽게도 안 된다. 역시 모든 일은 날로 먹으려 하면 안 되는 것 같다. 그러면 어떻게 해야할까? 다행히도 코틀린 제작자들은 이것이 가능하도록 몇 가지 방법을 만들어 놓았다. 그 중 대표적인 것이 함수 참조(function reference)와람다식(lambda)을 이용하는 방법이다.
함수 참조(function reference)
함수 참조는 상당히 간단하다. 미리 fun을 통해 만들어둔 함수를 ‘::’ 키워드를 통해 변수에 그대로 대입하는 방식이다. 방법은 다음과 같다.

변수(상수)를 선언한 뒤 [::함수 이름]형식으로 대입하면 끝이다. 이 변수(상수)를 통해 할당 된 함수를 사용하려면 [변수.call()]을 해주면 된다. 만약 함수에 인자가 있다면 call 안에 타입에 맞게 인자값을 넣어두면 된다.

람다식(lambda)
람다식(이하 람다)은 익명 함수를 지칭한다. 익명 함수라는 말이 생소할 수 있는데 쉽게 말해서 [fun] 키워드를 통해 생성한 함수가 아닌 것을 의미한다. fun 없이 함수를 생성한다? 지금까지 습관적으로 했던 fun을 안 써도 가능하다는 사실에 뭔가 당황스럽지만 천천히 살펴 보도록 하자. 우선 기본 형태는 다음과 같다.

감이 오는가? fun 키워드 하나 빼고 [->] 하나 써줬을 뿐인데 바로 변수(상수)에 할당이 되다니..! 뿐만 아니라 이름이 없다. 그래서 익명 함수인 것이다. 형태는 이미 나와있지만 그래도 한 번 더 짚고 넘어가자면 [매개변수(들) -> 내용]으로 구성되는 매우 간단한 형태다. 내용이 여러 줄일 경우 가장 마지막 줄이 반환값이 되니 참고하도록 하자.

추가적으로 인자가 없는 함수를 작성하고 싶을 땐 매개변수 부분을 살포시 비워두면 되니 알아두면 좋을 듯 하다.

이상 람다에 대해 간단히 알아보았다. 그런데 눈치가 빠른 여러분들이라면 아마 뭔가 미심쩍은 부분이 있을 것이다. 그건 바로~~~
함수 타입
‘함수가 변수처럼 쓰일 수 있다면 타입 지정도 가능한 거 아닐까’
위에까지 글을 읽다가 혹시나 이런 생각을 하셨다면 상당히 훌륭한 생각이며 오늘 밤 좋은 꿈 꾸길 바란다. 정답이다. 함수형 변수 역시 타입을 지정할 수 있다. 다만 변수와는 약간 상이한 부분이 있다면 타입의 형식이 [(인자들) ->반환형]이라는 것이다. 거두절미 예시를 봐보도록 하자.

여러울 것 없이 차근차근 살펴보자면, 우선 [(인자들) -> 반환형]을 통해 이 변수를 호출할 때 어떤 타입의 값을 주어야 하며 또한 그 결과가 어떤 타입인지 알 수 있다. 위의 lambda09c의 경우 인자가 Int형 변수이고 반환도 Int형 변수이다. 그래서 main에서 인자로 정수인 3을 넘겨 주었고 반환 값이 30(3 * 10)이므로 실행하면 30이 출력 된다. 마찬가지 원리로 lambda09d는 3(Int 타입), 4(Int 타입)를 인자로 받아 12(3 * 4)가 출력 된다. 마지막으로 lambda09e는 pikachu(String 타입), 25(Int 타입)를 인자로 받아 pikachu number is 25가 출력 된다.
참고로 인자가 1개라면 별도의 매개변수 지정을 하지 않고 it이라는 키워드로 대체할 수 있으니 알아두도록 하자.(단, 타입이 무엇인지 꼭 명시되어야 한다.)

간결한 건 알겠는데..
함수 하나를 만들기 위해 코드가 길어진다거나 함수 내용 자체에 불필요한 문장이 더러 생긴다거나 하는 건 확실히 줄어든 것 같다. 그런데 객체지향이나 절차지향에 익숙하신 분들이라면 아무래도 쉽게 와닿지는 않을 수 있다. 오히려 당장은 더 불편하게 느껴지는 것이 당연할 터.(포인터도 아니고 -> 이거 부터가 어색할 수도..) 하지만 함수가 일급 객체로서 역할을 한다는 의미만 잘 이해한다면 금세 익숙해지리라 믿어 의심한다. 이것이 익숙해질 즈음에 다음 내용인 고차 함수의 문을 두드려 보면 좋을 것 같다.(즉, 아직 끝나지 않았다는 뜻이다 :D)
주석
*최신 자바 버전에서는 자바 역시 함수형 프로그래밍이 가능하나 객체 지향 언어의 대표 격인 만큼 클래스를 더 부각하였다.
