[Kotlin]함수형 프로그래밍 초간단 이해하기

이영규
이영규
Sep 3, 2018 · 7 min read

함수형 프로그래밍. 개발하다 보면 한 번쯤은 들어봤을 법한 말이다. 안 들어봤다 해도 지금 이 순간 봤으니 들어본 것이라 할 수 있다. 아무튼 일단 함수형 프로그래밍을 하기에 앞서 무엇인지 모르는 분들을 위해 잠깐 설명하고 넘어가겠다.


함수형 프로그래밍?

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

가장 마지막인 par1 + par2가 리턴 값이 된다.

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

인자가 없을 때

이상 람다에 대해 간단히 알아보았다. 그런데 눈치가 빠른 여러분들이라면 아마 뭔가 미심쩍은 부분이 있을 것이다. 그건 바로~~~

함수 타입

위에까지 글을 읽다가 혹시나 이런 생각을 하셨다면 상당히 훌륭한 생각이며 오늘 밤 좋은 꿈 꾸길 바란다. 정답이다. 함수형 변수 역시 타입을 지정할 수 있다. 다만 변수와는 약간 상이한 부분이 있다면 타입의 형식이 [(인자들) ->반환형]이라는 것이다. 거두절미 예시를 봐보도록 하자.

타입을 명시한 함수형 변수

여러울 것 없이 차근차근 살펴보자면, 우선 [(인자들) -> 반환형]을 통해 이 변수를 호출할 때 어떤 타입의 값을 주어야 하며 또한 그 결과가 어떤 타입인지 알 수 있다. 위의 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이라는 키워드로 대체할 수 있으니 알아두도록 하자.(단, 타입이 무엇인지 꼭 명시되어야 한다.)

인자가 1개인 lambda09c의 it 변형

간결한 건 알겠는데..

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

주석

*최신 자바 버전에서는 자바 역시 함수형 프로그래밍이 가능하나 객체 지향 언어의 대표 격인 만큼 클래스를 더 부각하였다.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade