inline, noinline, crossinline 세 가지 키워드의 역할과 차이inline 이란?“함수 호출을 인라인(복붙) 하여 호출 오버헤드를 줄이는 키워드”
inline 함수는 컴파일 시 함수 본문을 호출 위치에 그대로 삽입합니다.inline fun repeatTwice(action: () -> Unit) {
action()
action()
}
fun main() {
repeatTwice { println("Hi") }
}
컴파일 시 내부적으로 이렇게 바뀜 👇
(즉, 함수 호출 자체가 사라집니다.)
fun main() {
println("Hi")
println("Hi")
}
효과
return하면 바깥 함수 종료)noinline 이란?“인라인 함수 안에서 특정 람다 파라미터만 인라인하지 않도록 예외 처리”
inline 함수 안에서는 기본적으로 모든 람다 파라미터가 인라인됨.noinline을 붙여야 함.noinline이 붙는다면 선언할때마다 계속 생성함inline fun doSomething(
inlineBlock: () -> Unit,
noinline normalBlock: () -> Unit
) {
inlineBlock() // 인라인됨
val ref = normalBlock // ❌ 일반 람다는 저장 불가 → noinline 덕분에 가능
ref() // 나중에 호출 가능
}
정리
inline 함수 내부에서 람다를 저장/전달해야 한다면 → noinlinecrossinline — 비지역 반환 금지 + 안전한 컨텍스트 호출 허용“인라인 함수 안의 람다를 다른 컨텍스트(비동기, 콜백 등) 에서 호출할 수 있도록 허용하되,
비지역 반환은 컴파일 단계에서 금지시킴”
inline fun runAsync(crossinline block: () -> Unit) {
Thread {
block() // 다른 스레드(비동기) 안에서 실행
}.start()
}
fun main() {
runAsync {
println("Running in background")
// return ❌ 불가능 (비지역 반환 금지)
return@runAsync ✅ 가능 (지역 반환)
}
}
핵심 의미 두 가지
컴파일 타임에 비지역 반환을 차단
→ 다른 컨텍스트에서 return이 호출돼 프로그램 흐름이 꼬이는 걸 방지
비동기 컨텍스트 허용
→ 람다가 스레드, 콜백, 리스너 안에서도 안전하게 실행 가능
| 키워드 | 인라인 여부 | 비지역 반환 가능 | 다른 컨텍스트 호출 가능 | 람다 저장 가능 | 주요 사용 목적 |
|---|---|---|---|---|---|
inline | ✅ | ✅ 가능 | ⚠️ 위험할 수 있음 | ❌ 불가능 | 성능 최적화, 호출 오버헤드 제거 |
noinline | ❌ | ❌ 불가능 | ✅ 가능 | ✅ 가능 | 람다를 저장하거나 전달해야 할 때 |
crossinline | ✅ | ❌ 금지 | ✅ 가능 | ❌ 불가능 | 비동기/리스너 컨텍스트에서 안전하게 호출 |
inline fun call(block: () -> Unit) {
block()
println("After block")
}
fun main() {
call {
println("Inside")
return // ✅ main()까지 빠져나감
}
println("This line never runs")
}
→ inline 함수이기 때문에 block() 내부의 return이
바깥 함수(main) 까지 영향을 미침.
즉, 이것이 “비지역 반환(non-local return)”입니다.
crossinline을 붙이면 이런 식의 제어 흐름을 컴파일러가 막습니다.
SearchView 검색어 리스너SearchView의 setOnQueryTextListener() 콜백을
확장 함수로 더 간결하게 만들 수 있습니다.
inline fun SearchView.onQueryTextChanged(
crossinline onQuery: (String) -> Unit
) {
setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?) = true
override fun onQueryTextChange(newText: String?): Boolean {
onQuery(newText.orEmpty()) // crossinline: 안전하게 콜백 호출
return true
}
})
}
searchView.onQueryTextChanged { keyword ->
// 실시간 검색어 추천
adapter.submitList(allItems.filter { it.contains(keyword, ignoreCase = true) })
}
콜백이 익명 객체(다른 컨텍스트) 안에서 실행되므로crossinline을 써서 비지역 반환을 금지 + 안전한 호출을 허용.
| 키워드 | 핵심 개념 | 한 줄 정리 |
|---|---|---|
inline | 코드 인라인화, 호출 오버헤드 제거 | 함수 호출을 복붙하듯 최적화 |
noinline | 인라인 제외, 람다 저장/전달 허용 | 람다를 변수처럼 다뤄야 할 때 |
crossinline | 비지역 반환 금지, 다른 컨텍스트 호출 허용 | 비동기/리스너 안에서 안전하게 람다 실행 |
| 비지역 반환 | 인라인된 람다의 return이 바깥 함수까지 탈출 | crossinline으로 막을 수 있음 |