✅ Kotlin은 함수 자체를 우선적으로 다루며, 함수형 프로그래밍 개념을 적극 반영합니다. 자주 등장하는 함수 선언 방법, 함수 참조, 고차 함수, 람다 제어, 재귀, 확장 함수 등을 정리합니다.
🔹 1. 함수 선언 문법 (기본)
📌 Kotlin에서 함수는 fun 키워드로 선언하며, 반환 타입을 명시합니다.
fun add(x: Int, y: Int): Int {
return x + y
}
// 한 줄로 작성 가능
fun square(x: Int): Int = x * x
🔹 2. 함수 타입 (함수를 값처럼 다루기)
📌 함수는 변수처럼 저장하거나 전달 가능하며, 이를 위해 함수 타입 (Int, Int) -> Int 형식을 사용합니다.
val sum: (Int, Int) -> Int = ::add
val multiply: (Int, Int) -> Int = { a, b -> a * b }
println(sum(2, 3)) // 5
println(multiply(3, 4)) // 12
- 함수 타입:
(파라미터 타입) -> 반환 타입 ::함수이름으로 기존 함수 참조 가능
🔹 3. 고차 함수 (함수를 인자로 받거나 반환)
📌 고차 함수란 다른 함수를 인자로 받거나, 함수 결과로 반환하는 함수입니다. map, filter, sortedBy 등이 대표적인 고차 함수입니다.
fun operate(a: Int, b: Int, op: (Int, Int) -> Int): Int {
return op(a, b)
}
val result = operate(3, 5) { x, y -> x * y }
println(result) // 15
🔹 4. 익명 함수 (이름 없는 함수)
📌 익명 함수는 함수 이름 없이 정의되며, 일반 함수와 문법이 유사합니다. return이 명확하며, 람다와 달리 라벨이 필요 없습니다.
val isEven = fun(n: Int): Boolean = n % 2 == 0
println(isEven(4)) // true
fun()키워드를 사용해 선언- 명시적 타입 지정 및 return 가능
🔹 5. 람다에서 return 제어 (return@label)
📌 람다 내부에서 return을 사용할 경우, 전체 함수를 종료할 수 있으므로 return@함수명으로 블록 탈출 위치를 지정합니다.
fun example() {
listOf(1, 2, 3).forEach {
if (it == 2) return@forEach // forEach만 건너뜀
println(it)
}
}
return@함수명→ 해당 람다 블록만 종료return만 쓰면 전체 함수 종료 → 주의
🔹 6. Currying (커링) 비공식 지원
📌 Currying이란 여러 인자를 갖는 함수를 다단계 함수로 쪼개는 방식입니다. Kotlin은 이를 명시적으로 지원하지 않지만, 함수 반환 방식으로 유사하게 구현할 수 있습니다.
fun add(a: Int): (Int) -> Int {
return { b -> a + b }
}
val add3 = add(3)
println(add3(7)) // 10
🔹 7. 재귀 함수 & 꼬리 재귀 (tailrec)
📌 Kotlin에서는 재귀 호출을 지원하며, 꼬리 재귀 최적화가 가능한 경우 tailrec 키워드를 통해 반복문처럼 처리됩니다.
tailrec fun factorial(n: Int, acc: Int = 1): Int {
return if (n == 0) acc else factorial(n - 1, acc * n)
}
println(factorial(5)) // 120
tailrec키워드 → 꼬리 호출 최적화 (Tail Call Optimization)
🔹 8. inline 함수, noinline, crossinline
📌 inline 함수는 호출되는 대신 호출부에 코드가 삽입되어 오버헤드를 줄이고 성능을 개선합니다.
inline fun doTwice(action: () -> Unit) {
action()
action()
}
inline: 코드 자체를 호출부에 삽입noinline: 특정 람다는 인라인 제외 가능crossinline: 람다 안에서return으로 빠져나가는 것 방지
🔹 9. 확장 함수와 일반 함수 차이
📌 확장 함수는 기존 클래스에 새로운 함수처럼 정의해 사용하는 문법입니다. 실제로는 정적 메서드지만, 클래스 멤버처럼 보입니다.
fun String.addQuote(): String = "\"$this\""
println("Hello".addQuote()) // 출력: "Hello"
- 호출 객체는 수신 객체 (
this)로 참조 - 기존 타입에 기능 추가할 때 유용
✅ 정리
🔹 10. 람다 vs 익명 함수 차이
📌 람다(lambda)는 함수 리터럴이며 return이 제어 불가할 수 있고, 익명 함수는 명시적 fun으로 정의되는 이름 없는 함수입니다.
// 람다 표현식
val square = { x: Int -> x * x }
// 익명 함수
val square2 = fun(x: Int): Int { return x * x }
- 람다는 return@label 사용 필요, 익명 함수는 return 사용 가능
- 람다는 타입 추론에 의존, 익명 함수는 타입 명시 가능
🔹 11. SAM 변환 (Java interop)
📌 Kotlin은 단일 추상 메서드(SAM: Single Abstract Method)를 가진 Java 인터페이스를 람다로 변환해 사용할 수 있습니다. 이를 통해 Kotlin은 Java 생태계와의 상호 운용성(interoperability)을 뛰어나게 제공합니다.
Java에서는 Runnable, Comparator, Callable처럼 메서드가 하나만 존재하는 인터페이스(SAM)를 많이 사용합니다. Kotlin에서는 이런 Java 인터페이스를 람다(lambda)로 대체할 수 있습니다.
예를 들어:
// Java 스타일
Thread(object : Runnable {
override fun run() {
println("Hello")
}
}).start()
// Kotlin SAM 변환
Thread(Runnable { println("Hello") }).start()
// Kotlin은 더 나아가 람다만으로도 가능
Thread { println("Hello") }.start()kotlin
Thread(Runnable { println("Hello") }).start()
- 자바 interop 시 자주 사용
- Kotlin에서는 고차 함수로 래핑하지 않고도 람다 사용 가능
🔹 12. 람다의 클로저 (closure)
📌 람다는 외부 변수나 상태를 캡처(참조)할 수 있으며, 이 변수는 메모리에 유지됩니다. 이를 클로저(closure)라고 합니다.
var count = 0
val inc = { count++ }
inc()
println(count) // 1
- 외부 변수 캡처로 상태 변경 가능 → side-effect 주의
🔹 13. inline 함수의 주의점
📌 inline 함수는 성능 향상에 기여하지만, 너무 큰 함수나 재귀적 함수는 인라인되지 않으며 코드 부피 증가 유의
- 인라인 부작용: 코드 중복으로 인한 바이너리 증가 가능
- 반복 사용되는 짧은 유틸 함수에 적합
| 개념 | 설명 | 예시 |
|---|---|---|
| 고차 함수 | 함수 인자로 함수 전달 / 반환 | map, filter, operate(f) |
| 함수 타입 | 함수 자체를 변수처럼 다루기 | (Int, Int) -> Int |
| 람다 제어 | return@label로 흐름 통제 |
forEach, run 등 내부 제어 |
| 커링 | 다단계 함수 적용 | add(3)(4) |
| 꼬리 재귀 | 종료 조건에서 바로 반환 → 스택 오버플로 방지 | tailrec factorial() |
| inline 함수 | 성능 최적화를 위한 코드 치환 | inline fun repeat() |
| 확장 함수 | 클래스 외부에서 새로운 멤버처럼 정의 | String.addQuote() |
다음 시리즈 ⑮: 람다, 수신 함수, 클로저 개념과 활용으로 이어집니다.
'Code Odyssey' 카테고리의 다른 글
| Kotlin 코딩테스트 문법 시리즈 ⑯ : 널 처리 & 안전 호출 (0) | 2025.07.16 |
|---|---|
| Kotlin 코딩테스트 문법 시리즈 ⑮ : 람다, 수신 함수, 클로저 개념과 활용 (0) | 2025.07.15 |
| Kotlin 코딩테스트 문법 시리즈 ⑬ : Scope Function 정리 (let, also, apply, run, takeIf) (0) | 2025.07.13 |
| Kotlin 코딩테스트 문법 시리즈 ⑫ : 누적 함수 정리 (reduce, fold, scan) (1) | 2025.07.12 |
| Kotlin 코딩테스트 문법 시리즈 ⑪ : 컬렉션 유틸 함수 정리 (zip, chunked, windowed 등) (4) | 2025.07.11 |