2025. 2. 7. 14:55ㆍ프로그래밍 언어/Kotlin 기초
나는 Kotlin에서 함수를 만들 때 inline 함수를 자주 쓰는가?
솔직히 말하면 그냥 일반 함수로도 충분한데 굳이 사용할 필요성을 느끼지 못했다.
그런데 inline 함수가 성능 최적화에 도움이 된다는 말을 들었다.
사실일까?
1. inline 함수란?
inline 키워드는 고차 함수(high-order function)를 사용할 때 함수 호출을 제거하고,
함수 본문을 직접 호출 위치에 삽입하는 기능이다.
즉, 컴파일러가 해당 함수를 호출하는 대신 코드를 직접 복사하셔 삽입(inlining)한다.
일반 함수와 inline 함수를 비교한 예제를 확인해보자 !
일반 함수 vs inline 함수 예제
fun executeLambda(lambda: () -> Unit) {
println("Before lambda execution")
lambda()
println("After lambda execution")
}
fun main() {
executeLambda {
println("Lambda executed!")
}
}
우리는 일반적으로 고차 함수를 작성할 때 위와 같이 사용한다.
그럼 이걸 inline 함수로 바꿔보자.
inline fun executeLambda(lambda: () -> Unit) {
println("Before lambda execution")
lambda()
println("After lambda execution")
}
fun main() {
executeLambda {
println("Lambda executed!")
}
}
코드 상에서는 inline이라는 키워드가 추가된 것 외에는 변화가 없다.
inline 함수의 차별점은 컴파일에서 발생되기 때문이다.
일반적인 고차 함수에서는 executeLambda 내부에서 lambda()를 호출하기 때문에
실행 시점에 람다 객체가 생성되고 함수 호출 오버헤드가 발생한다.
그렇다면 inline 함수의 컴파일 파일은 어떻게 바뀔까?
fun main() {
println("Before lambda execution")
println("Lambda executed!")
println("After lambda execution")
}
컴파일 된 코드 본문을 보면 executeLambda 함수의 본문이 main() 함수 내부에 직접 삽인된다.
이렇게 되면 람다 객체 생성 비용과 함수 호출 오버헤드가 사라져 성능이 향상될 수 있다.
public class MainKt {
public static void executeLambda(Function0<Unit> lambda) {
System.out.println("Before lambda execution");
lambda.invoke(); // 람다 실행
System.out.println("After lambda execution");
}
public static void main(String[] args) {
// executeLambda 호출
executeLambda(new Function0<Unit>() {
@Override
public Unit invoke() {
System.out.println("Lambda executed!");
return Unit.INSTANCE; // Kotlin의 Unit에 해당하는 값
}
});
}
}
일반적인 고차함수의 컴파일 파일과 비교하면 차이점이 확 와닿는다.
2. inline 함수의 장점
(1) 함수 호출 오버헤드 감소
inline 함수는 함수 호출을 제거하고, 본문을 직접 삽입하기 때문에 호출 오버헤드가 줄어든다.
(2) 람다 객체 생성 방지
일반적으로 람다를 사용하면 람다 객체가 힙(heap)에 할당되지만,
inline을 사용하면 객체 생성을 방지하여 메모리 사용량을 줄일 수 있다.
(3) 성능 최적화 (특히 작은 함수에서 효과적)
작고 자주 호출되는 함수에서 inline을 사용하면 성능 향상 효과가 크다.
3. inline 함수의 단점
(1) 코드 크기 증가 (메서드 크기 증가)
inline 함수는 호출될 때마다 코드가 복사되기 때문에 함수가 클 경우 코드 크기가 급격히 증가할 수 있다.
(2) 재귀 함수에는 사용 불가
inline 함수는 자신을 재귀적으로 호출할 수 없습니다.
inline fun recursiveFunction(n: Int) {
if (n > 0) {
recursiveFunction(n - 1) // ERROR!
}
}
컴파일 오류가 발생하며, inline 함수는 반복 호출을 지원하지 않습니다
4. 언제 inline 함수를 사용해야 할까?
- 자주 호출되며 짧은 함수
- 람다를 자주 생성하는 함수라면 inline을 적용하면 메모리 사용량이 줄어들 수 있음
- 하지만, 함수가 길어지거나, 여러 곳에서 재사용되는 경우에는 코드 중복이 발생하여 성능이 떨어질 수 있다.
- 큰 함수에서는 inline을 사용하면 코드 크기가 급격히 증가하여 오히려 역효과가 날 수 있다.
inline 함수는 적절히 사용하면 성능 최적화에 도움이 되지만, 무분별하게 사용하면 코드 크기 증가 등의 부작용이 있을 수 있다.
따라서 짧고 자주 호출되는 함수에 사용하면 좋고, 긴 함수나 재사용성이 높은 함수에서는 사용을 피하는 것이 좋다.
하지만 성능 최적화 경험을 해보기에 간단한 방법인 것 같다.
'프로그래밍 언어 > Kotlin 기초' 카테고리의 다른 글
Kotlin에서 유용한 고차 함수 정리 (0) | 2025.02.27 |
---|---|
Kotlin 코딩테스트의 Kick! 우선순위큐 (Priority Queue) (0) | 2025.02.15 |
Kotlin 상태 관리 | Sealed Class vs Enum Class 차이점 (0) | 2025.02.06 |
Kotlin에서 launch와 async는 무엇이 다를까? (0) | 2025.02.03 |
[프로그래머스/Kotlin]Level3 - 양과 늑대 (0) | 2023.06.25 |