Kotlin 코딩테스트 문법 시리즈 ⑭ : 함수 패턴 정리

2025. 7. 14. 05:11·Code Odyssey

✅ 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
'Code Odyssey' 카테고리의 다른 글
  • Kotlin 코딩테스트 문법 시리즈 ⑯ : 널 처리 & 안전 호출
  • Kotlin 코딩테스트 문법 시리즈 ⑮ : 람다, 수신 함수, 클로저 개념과 활용
  • Kotlin 코딩테스트 문법 시리즈 ⑬ : Scope Function 정리 (let, also, apply, run, takeIf)
  • Kotlin 코딩테스트 문법 시리즈 ⑫ : 누적 함수 정리 (reduce, fold, scan)
Celion
Celion
오늘도 평소처럼 화이팅!
  • Celion
    Orion Log
    Celion
  • 전체
    오늘
    어제
    • 전체 글 (144)
      • Uncompiled Thoughts (8)
        • 네이버 부스트캠프 10기 (5)
      • CS 기초부터 한 걸음씩 (34)
      • Code Odyssey (22)
      • Algorithm (77)
        • Coding Test Records (63)
      • Git (3)
      • reference (0)
  • 블로그 메뉴

    • 태그
    • 방명록
  • 태그

    java
    Level2
    프로그래머스
    시뮬레이션
    Kotlin
    알고리즘고득점kit
    greedy
    백준
    Level3
    코테
    boostcamp
    문법정리
  • 최근 글

  • 인기 글

  • 최근 댓글

  • hELLO· Designed By정상우.v4.10.4
Celion
Kotlin 코딩테스트 문법 시리즈 ⑭ : 함수 패턴 정리
상단으로

티스토리툴바