인라인 함수 - swkim0128/PARA GitHub Wiki

1. 인라인 함수란?

코틀린의 **인라인 함수(inline function)**는 함수 호출에 따른 오버헤드를 줄이기 위해 함수 본문을 호출 위치에 직접 삽입하는 기능이다.

특히 고차 함수(higher-order function)**에서 사용하면 성능을 최적화할 수 있다.

인라인 함수의 주요 특징

  • 함수 호출 오버헤드를 제거 (코드가 직접 삽입됨)
  • 람다를 인자로 받는 함수의 성능 최적화 (람다 객체 생성 방지)
  • 재사용성이 뛰어나면서도 성능을 유지할 수 있음
  • 함수 크기가 커지면 코드 중복 발생 가능 (주의 필요)

2. 인라인 함수의 기본 문법

inline fun 함수이름(매개변수: 타입): 반환타입 {
    // 함수 본문
}

예제 1: 기본적인 인라인 함수

inline fun printMessage(message: String) {
    println("메시지 출력: $message")
}

fun main() {
    printMessage("Hello, Kotlin!") 
}

이 코드는 다음과 같이 실제 코드가 삽입되는 효과를 가진다.

fun main() {
    println("메시지 출력: Hello, Kotlin!") 
}

✅ 함수 호출 없이 코드가 직접 삽입되므로 성능이 향상됨.

3. 인라인 함수의 장점

1) 함수 호출 오버헤드 제거

  • 일반적인 함수 호출 시 스택 프레임(Stack Frame)이 생성되지만, 인라인 함수를 사용하면 이 과정이 생략된다.
inline fun add(a: Int, b: Int): Int {
    return a + b
}

fun main() {
    val result = add(5, 10)
    println(result) // 출력: 15
}

이 코드는 컴파일 시 다음과 같이 변경된다.

fun main() {
    val result = 5 + 10
    println(result) // 출력: 15
}

✅ 함수 호출 없이 바로 계산이 수행됨.

2) 람다 표현식과 함께 사용하면 성능 최적화

inline fun execute(action: () -> Unit) {
    action()
}

fun main() {
    execute {
        println("인라인 함수 실행!")
    }
}

이 코드는 실제 실행될 때 람다 객체 생성 없이 코드가 직접 삽입됨.

4. 인라인 함수와 noinline, crossinline

1) noinline 키워드

  • 인라인 함수의 매개변수 중 일부 람다는 인라인하지 않도록 설정할 수 있다.
inline fun process(action: () -> Unit, noinline anotherAction: () -> Unit) {
    action()          // 인라인 처리됨
    anotherAction()   // 인라인되지 않음
}

fun main() {
    process(
        { println("인라인된 람다") },
        { println("인라인되지 않은 람다") }
    )
}

✅ anotherAction은 람다 객체로 유지됨.

2) crossinline 키워드

  • 람다가 다른 컨텍스트로 전달될 경우, return을 사용하지 못하도록 방지해야 할 때 사용한다.
inline fun execute(crossinline action: () -> Unit) {
    val runnable = Runnable { action() }
    runnable.run()
}

fun main() {
    execute {
        println("crossinline 사용 예제")
        // return ❌ (컴파일 오류 발생)
    }
}

✅ crossinline을 사용하면 return을 통한 조기 종료를 방지할 수 있다.

5. reified 타입과 인라인 함수

일반적인 제네릭 함수는 **런타임에 타입 정보가 사라지는 문제(Type Erasure)**가 발생한다. 이를 해결하기 위해 reified 키워드를 인라인 함수와 함께 사용하면 타입 정보를 유지할 수 있다.

예제: reified를 사용한 타입 정보 유지

inline fun <reified T> getClassName(): String {
    return T::class.java.simpleName
}

fun main() {
    println(getClassName<String>()) // 출력: String
    println(getClassName<Int>()) // 출력: Integer
}

✅ 인라인 함수 덕분에 제네릭 타입 정보가 런타임에도 유지됨.

6. 인라인 함수의 한계점 및 주의사항

1. 함수 크기가 크면 코드 중복 발생 가능

  • 인라인 함수는 호출될 때마다 코드가 복사되므로 함수의 크기가 크면 바이너리 크기가 증가할 수 있음.

2. 재귀 함수에는 사용할 수 없음

  • 인라인 함수가 자기 자신을 호출할 경우 무한 복사(재귀 복사) 문제가 발생하므로 허용되지 않음.
inline fun recursiveFunction(n: Int) {
    if (n > 0) {
        println(n)
        // recursiveFunction(n - 1) ❌ (컴파일 오류 발생)
    }
}

3. 디버깅이 어려울 수 있음

  • 코드가 컴파일 시 인라인 처리되므로 디버거에서 함수 호출이 사라질 수 있음.

7. 인라인 함수와 일반 함수 비교

비교 항목 일반 함수 인라인 함수
호출 방식 함수 호출(스택 프레임 생성) 함수 코드가 호출 위치에 직접 삽입됨
실행 속도 상대적으로 느림 상대적으로 빠름 (호출 오버헤드 제거)
람다 객체 생성 람다 객체가 생성됨 람다 객체 생성 없이 코드 삽입
사용 제한 모든 함수에서 사용 가능 재귀 함수에서는 사용 불가

8. 결론: 언제 인라인 함수를 사용할까?

람다를 인자로 받는 고차 함수에서 사용하면 성능이 향상됨.자주 호출되는 작은 함수의 경우 인라인을 사용하면 성능 최적화 가능.함수 크기가 크다면 인라인 사용 시 코드 중복이 발생할 수 있으므로 주의.재귀 함수에는 사용할 수 없음.

💡 결론적으로, 인라인 함수는 적절한 상황에서 사용하면 성능 최적화에 매우 유용한 기능이다! 🚀

⚠️ **GitHub.com Fallback** ⚠️