인라인 함수 - swkim0128/PARA GitHub Wiki
코틀린의 **인라인 함수(inline function)**는 함수 호출에 따른 오버헤드를 줄이기 위해 함수 본문을 호출 위치에 직접 삽입하는 기능이다.
특히 고차 함수(higher-order function)**에서 사용하면 성능을 최적화할 수 있다.
인라인 함수의 주요 특징
- ✅ 함수 호출 오버헤드를 제거 (코드가 직접 삽입됨)
- ✅ 람다를 인자로 받는 함수의 성능 최적화 (람다 객체 생성 방지)
- ✅ 재사용성이 뛰어나면서도 성능을 유지할 수 있음
- ❌ 함수 크기가 커지면 코드 중복 발생 가능 (주의 필요)
inline fun 함수이름(매개변수: 타입): 반환타입 {
// 함수 본문
}
예제 1: 기본적인 인라인 함수
inline fun printMessage(message: String) {
println("메시지 출력: $message")
}
fun main() {
printMessage("Hello, Kotlin!")
}
이 코드는 다음과 같이 실제 코드가 삽입되는 효과를 가진다.
fun main() {
println("메시지 출력: Hello, Kotlin!")
}
✅ 함수 호출 없이 코드가 직접 삽입되므로 성능이 향상됨.
- 일반적인 함수 호출 시 스택 프레임(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
}
✅ 함수 호출 없이 바로 계산이 수행됨.
inline fun execute(action: () -> Unit) {
action()
}
fun main() {
execute {
println("인라인 함수 실행!")
}
}
이 코드는 실제 실행될 때 람다 객체 생성 없이 코드가 직접 삽입됨.
- 인라인 함수의 매개변수 중 일부 람다는 인라인하지 않도록 설정할 수 있다.
inline fun process(action: () -> Unit, noinline anotherAction: () -> Unit) {
action() // 인라인 처리됨
anotherAction() // 인라인되지 않음
}
fun main() {
process(
{ println("인라인된 람다") },
{ println("인라인되지 않은 람다") }
)
}
✅ anotherAction은 람다 객체로 유지됨.
- 람다가 다른 컨텍스트로 전달될 경우, return을 사용하지 못하도록 방지해야 할 때 사용한다.
inline fun execute(crossinline action: () -> Unit) {
val runnable = Runnable { action() }
runnable.run()
}
fun main() {
execute {
println("crossinline 사용 예제")
// return ❌ (컴파일 오류 발생)
}
}
✅ crossinline을 사용하면 return을 통한 조기 종료를 방지할 수 있다.
일반적인 제네릭 함수는 **런타임에 타입 정보가 사라지는 문제(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
}
✅ 인라인 함수 덕분에 제네릭 타입 정보가 런타임에도 유지됨.
- 인라인 함수는 호출될 때마다 코드가 복사되므로 함수의 크기가 크면 바이너리 크기가 증가할 수 있음.
- 인라인 함수가 자기 자신을 호출할 경우 무한 복사(재귀 복사) 문제가 발생하므로 허용되지 않음.
inline fun recursiveFunction(n: Int) {
if (n > 0) {
println(n)
// recursiveFunction(n - 1) ❌ (컴파일 오류 발생)
}
}
- 코드가 컴파일 시 인라인 처리되므로 디버거에서 함수 호출이 사라질 수 있음.
비교 항목 | 일반 함수 | 인라인 함수 |
---|---|---|
호출 방식 | 함수 호출(스택 프레임 생성) | 함수 코드가 호출 위치에 직접 삽입됨 |
실행 속도 | 상대적으로 느림 | 상대적으로 빠름 (호출 오버헤드 제거) |
람다 객체 생성 | 람다 객체가 생성됨 | 람다 객체 생성 없이 코드 삽입 |
사용 제한 | 모든 함수에서 사용 가능 | 재귀 함수에서는 사용 불가 |
✅ 람다를 인자로 받는 고차 함수에서 사용하면 성능이 향상됨. ✅ 자주 호출되는 작은 함수의 경우 인라인을 사용하면 성능 최적화 가능. ❌ 함수 크기가 크다면 인라인 사용 시 코드 중복이 발생할 수 있으므로 주의. ❌ 재귀 함수에는 사용할 수 없음.
💡 결론적으로, 인라인 함수는 적절한 상황에서 사용하면 성능 최적화에 매우 유용한 기능이다! 🚀