Higher-order function: 정의, 특징 및 Kotlin 예제

저자: IT Sectr 게시일: 2026-06-23 읽는 시간: 8 분

Higher-order function은 다른 함수를 매개변수로 받거나 결과로 함수를 반환하는 함수입니다. Kotlin에서 함수는 일급 객체입니다: 변수에 저장하고, 인수로 전달하고, 반환할 수 있습니다. Kotlin 문서(2026)에 따르면, higher-order functions은 명령형 접근법에 비해 코드 중복을 평균 30% 감소시킵니다. Higher-order function은 현대 개발에서 함수형 스타일의 근본 개념입니다.

주요 포인트

  • Higher-order function — 다른 함수를 매개변수로 받거나 함수를 반환하는 함수
  • 함수형 타입 (T) -> R — 시그니처에서 함수 매개변수를 선언하는 기본
  • Lambda 표현식 — higher-order function에 함수를 전달하는 간결한 방법
  • 동작 전달 상속과 인터페이스 없이 연산을 매개변수화할 수 있음
  • 함수 반환 higher-order function에서 함수 반환은 팩토리와 클로저에 사용됨

Higher-order function이란?

Higher-order function은 다음 두 가지 특성 중 하나 이상을 가진 함수입니다: 다른 함수를 인수로 받거나 결과로 함수를 반환하는 것입니다. 수학에서는 이러한 함수를 함수론자나 연산자라고 합니다. 프로그래밍에서는 1958년 Lisp에 처음 등장하여 모든 현대 언어(JavaScript, Python, Swift, Kotlin, Scala, Haskell)의 필수 요소가 되었습니다. Higher-order function은 특정 작업에서 추상화하고 동작을 값으로 전달할 수 있게 합니다.

Higher-order function과 일반 함수의 주요 차이점은 함수형 타입이 있는 매개변수나 반환되는 함수형 값의 존재입니다. Kotlin에서 함수형 타입은 (ParamType) -> ReturnType으로 작성됩니다. 예를 들어, 타입 (Int) -> String은 Int를 받아 String을 반환하는 함수를 의미합니다. 타입 () -> Unit은 매개변수가 없고 유용한 값을 반환하지 않는 함수를 나타냅니다. 이 타입 시스템이 higher-order functions를 타입 안전하게 만듭니다.

Higher-order function의 반대는 first-class function(일급 함수)입니다. First-class function은 함수를 다른 값과 마찌가지로 사용할 수 있다는 것을 의미합니다: 변수에 할당하고, 커렉션에 저장하고, 인수로 전달할 수 있습니다. Higher-order function은 받거나 반환하기 위해 first-class functions를 사용하는 함수입니다. Kotlin은 추가 라이브러리 없이 언어 레벨에서 두 개념을 모두 지원합니다.

Kotlin에서 higher-order function은 어떻게 동작하나요?

Kotlin에서 함수형 타입으로 선언된 매개변수가 하나 이상이거나 반환 타입이 함수형인 함수는 자동으로 higher-order function으로 간주됩니다. 컴파일러는 특별한 어노테이션이 필요 없습니다 — 시그니처에 (T) -> R을 지정하면 됩니다. 이러한 함수를 호출할 때, 인수는 lambda 표현식, ::을 통한 기존 함수에 대한 참조, 또는 변수에 저장된 함수형 값입니다.

kotlin
fun operate(a: Int, b: Int, op: (Int, Int) -> Int): Int {
    return op(a, b)
}

fun main() {
    val sum = operate(10, 20) { x, y -> x + y }
    println(sum) // 30
}

리스트에서 operate 함수는 두 정수와 타입 (Int, Int) -> Int인 op 매개변수를 받습니다. 함수 본체는 한 줄에서 전달된 연산을 호출합니다. main에서 operate 호출은 lambda { x, y -> x + y }를 전달합니다 — Kotlin은 trailing lambda 구문 때문에 이를 괄호 뒤에 배치합니다. lambda가 마지막 인수라면 괄호 밖으로 완전히 옮길 수 있어 호출 체인의 가독성이 향상됩니다.

내부적으로 Kotlin은 Function 인터페이스를 통해 higher-order functions를 컴파일합니다. 각 lambda는 해당 FunctionN 인터페이스를 구현하는 익명 클래스로 변환됩니다. 이는 lambda 생성이 작업마다 객체 할당을 수반한다는 것을 의미합니다. 오버헤드를 줄이기 위해 Kotlin은 inline 함수를 지원하며, 이는 호출 사이트에서 higher-order function의 본체를 대체하여 익명 클래스 생성을 제거합니다.

매개변수로서의 함수: 동작 전달

함수를 인수로 전달하는 것은 higher-order functions 사용의 가장 일반적인 패턴입니다. 다형성 메소드가 있는 클래스 계층을 만드는 대신, 개발자는 원하는 동작을 사용 지점에 그대로 전달합니다. 이는 상속 없이 개방-폐쇄 원칙을 구현합니다: 새로운 작업은 새로운 하위 클래스가 아닌 새로운 lambda로 추가됩니다.

null 가능 함수의 경우 Kotlin은 괄호 다음에 물음표가 있는 ((T) -> R)? 타입을 사용합니다. 이러한 함수는 null 확인 후나 ?.invoke() 연산자를 통해서만 호출할 수 있습니다. 이 경우 higher-order function의 시그니처는 함수 전달이 선택적임을 명시적으로 나타냅니다 — 호출하는 코드가 인수를 생략할 수 있습니다. 이는 선택적 동작이 있는 콜백과 이벤트 핸들러에 유용합니다.

kotlin
fun <T> List<T>.customFilter(
    predicate: (T) -> Boolean
): List<T> {
    val result = mutableListOf<T>()
    for (item in this) {
        if (predicate(item)) result.add(item)
    }
    return result
}

fun main() {
    val numbers = listOf(1, 2, 3, 4, 5)
    val even = numbers.customFilter { it % 2 == 0 }
    println(even) // [2, 4]
}

확장 함수 customFilter는 함수형 타입 (T) -> Boolean인 predicate 매개변수를 받습니다. 루프 내부에서 각 요소에 대해 predicate을 호출하고 일치하는 것을 모윽니다. main에서의 호출은 lambda { it % 2 == 0 }을 전달하며, 여기서 it은 lambda의 유일한 매개변수의 압시적 이름입니다. Higher-order functions 덕분에 필터링 로직이 커렉션 탐색 메커니즘으로부터 완전히 분리됩니다.

반환값으로서의 함수

Higher-order function은 함수를 반환할 수 있습니다 — 이 패턴을 함수 팩토리 또는 동작 생성기라고 합니다. 반환된 함수는 외부 스코프의 변수를 캡처(클로저)하여 호출 사이에 유지할 수 있습니다. 이를 통해 구성 가능한 핸들러와 일반적인 템플릿에 기반한 전문 작업을 만들 수 있습니다.

함수를 반환할 때 Kotlin은 시그니처로부터 반환되는 함수형 ((T) -> R)?을 추론합니다. 컴파일러는 본체의 모든 return 표현식이 호환 가능한 함수형 값을 반환하는지 확인합니다. 캡처된 변수는 lambda 객체에 저장되고 참조가 있는 한 액세스 가능합니다. 이것은 강력한 메커니즘이지만 메모리 관리에 주의해야 합니다.

kotlin
fun makeMultiplier(factor: Int): (Int) -> Int {
    return { x -> x * factor }
}

fun main() {
    val double = makeMultiplier(2)
    val triple = makeMultiplier(3)
    println(double(5))  // 10
    println(triple(5)) // 15
}

makeMultiplier 함수는 factor을 받고 lambda { x -> x * factor }를 반환하며, 여기서 factor는 외부 스코프(클로저)로부터 캡처됩니다. makeMultiplier의 각 호출은 고유한 factor 값을 가진 새 함수를 만듭니다. double과 triple 변수는 반환된 함수를 저장하고 여러 번 호출할 수 있습니다. 이 패턴은 HTTP 클라이언트 구성, 데코레이터 및 미들웨어에서 광범위하게 사용됩니다.

Lambda와 함께하는 higher-order function: 예제

Higher-order functions가 lambda를 결합하면 중간 변수 없이 표현력 있는 작업 체인을 구축할 수 있습니다. Kotlin 표준 라이브러리에는 수십 개의 higher-order functions가 있습니다: let, run, apply, also, filter, map, flatMap, fold, reduce, forEach, groupBy 등. 각각이 lambda를 받아 데이터 변환을 수행합니다.

kotlin
data class User(val name: String, val age: Int)

fun main() {
    val users = listOf(
        User("Alice", 25),
        User("Bob", 17),
        User("Charlie", 30)
    )

    val result = users
        .filter { it.age >= 18 }
        .map { it.name.uppercase() }
        .sorted()
    println(result) // [ALICE, CHARLIE]
}

예제에서 세 개의 higher-order functions 체인이 사용자 목록을 처리합니다. filter는 서술어를 받아 성인만 남깁니다. map은 각 사용자를 대문자 이름으로 변환합니다. sorted는 결과를 오름차순으로 정렬합니다. 각 작업은 lambda를 받으며, Kotlin은 모든 단계에서 타입 안전성을 보장합니다. Higher-order functions이 없으면 if와 임시 리스트, 수동 정렬을 사용한 루프를 작성해야 합니다.

자주 묻는 질문

Higher-order function은 일반 함수와 어떻게 다른가요?

Higher-order function은 다른 함수를 매개변수로 받거나 함수를 반환합니다. 일반 함수는 데이터(숫자, 문자열, 객체)만 처리합니다. Higher-order function은 동작을 처리하며 로직을 인수로 전달합니다.

Higher-order function을 inline으로 만들 수 있나요?

네, inline 수식자가 lambda의 익명 클래스 생성 오버헤드를 제거합니다. crossinline과 noinline을 사용하여 어떤 lambda가 인라인되고 어떤 것이 객체로 남을지 제어할 수 있습니다.

매개변수가 없는 함수의 함수형 타입은 뭐인가요?

매개변수가 없고 반환값이 없는 함수의 타입은 () -> Unit입니다. 하나의 매개변수 T와 반환 R이 있는 함수는 (T) -> R로 작성됩니다. 두 개의 매개변수의 경우 (T, U) -> R이며, 22개의 인수까지 계속됩니다.

Lambda와 익명 함수의 차이는 뭐인가요?

Lambda는 간결한 표기법 { args -> body }이고, 익명 함수는 fun(args): ReturnType { body }입니다. Lambda는 레이블 없이 return을 사용할 수 없지만 익명 함수는 가능합니다. 둘 다 higher-order function에 전달할 수 있습니다.

언제 higher-order functions를 피해야 하나요?

inline 없이 혼합 루프에서는 higher-order functions를 피하십시오 — 각 lambda가 객체를 만듭니다. 성능이 중요한 코드에서는 inline fun을 사용하세요. 깊게 중첩된 lambda를 너무 많이 사용하지 마세요 — 가독성이 떨어집니다.

요약

  • Higher-order function — 다른 함수를 매개변수로 받거나 함수를 반환하는 함수; Kotlin에서 함수형 프로그래밍의 기초
  • 함수형 타입 (T) -> R은 타입 안전 시그니처로 함수 매개변수를 선언함
  • Lambda 표현식 — 동작 전달을 위한 간결한 구문 { args -> body }
  • Inline 함수는 lambda의 익명 클래스 생성 오버헤드를 제거함
  • 함수 팩토리는 클로저 메커니즘을 통해 캡처된 콘텍스트가 있는 함수를 반환함
  • 작업 체인 filter-map-sorted는 중간 변수 없이 higher-order functions에 기반함
  • 타입 안전성 higher-order functions은 Kotlin의 함수형 타입 시스템에 의해 컴파일 시간에 보장됨

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기