들어가기 전에
람다식을 구성할 때 가끔 외부의 변수를 사용해야할 때가 있습니다. 이 때 어떻게 변수의 내용을 가져와서 어떻게 갱신할 수 있을까? 라고 생각하셨다면 클로저의 개념을 이해할 때가 되었습니다.
핵심 키워드
- 클로저(closure)
- 변수의 포획 (capture)
- 래퍼(wrapper)로 감싼 특수한 데이터 구조
학습하기
들어가기 전에
람다식을 구성할 때 가끔 외부의 변수를 사용해야할 때가 있습니다. 이 때 어떻게 변수의 내용을 가져와서 어떻게 갱신할 수 있을까? 라고 생각하셨다면 클로저의 개념을 이해할 때가 되었습니다.
핵심 키워드
학습하기
클로저
람다식 함수를 이용하다 보면 내부 함수에서 외부 변수를 사용하고 싶을 때가 있습니다. 클로저란 람다식으로 표현된 내부 함수에서 외부 범위에 선언된 변수에 접근할 수 있는 개념입니다. 이 때 람다식 안에 있는 외부 변수는 값을 유지하기 위해 람다가 포획(capture)한 변수라고 부릅니다.
실행 시점에서 람다식의 모든 참조가 포함된 닫힌(closed) 객체를 람다 코드와 함께 저장합니다. 이때 이러한 데이터 구조를 클로저(closure)라고 부르는 것입니다.
기본적으로 함수 안에 정의된 변수는 로컬 변수로 스택에 저장되어 있다가 함수가 끝나면 같이 사라지게 됩니다. 하지만 클로저 개념에서는 포획한 변수는 참조가 유지되어 종료되어도 사라지지 않고 접근하거나 수정할 수 있게 됩니다.
fun main() {
val calc = Calc()
var result = 0 // 외부의 변수
calc.addNum(2,3) { x, y -> result = x + y } // 클로저
println(result) // 값을 유지하여 5가 출력
}
class Calc {
fun addNum(a: Int, b: Int, add: (Int, Int) -> Unit) { // 람다식 add에는 반환값이 없음
add(a, b)
}
}
위 코드와 같이 result는 람다식 내부에서 재할당 되어 사용되는데 이때 할당된 값은 유지되 출력문에서 사용할 수 있게 됩니다. 클로저에 의해 독립된 복사본을 가지고 사용되는 것입니다.
함수에서는 다음과 같이 매개변수를 이용할 수도 있습니다.
// 길이가 일치하는 이름만 반환
fun filteredNames(length: Int) {
val names = arrayListOf("Kim", "Hong", "Go", "Hwang", "Jeon")
val filterResult = names.filter {
it.length == length // 바깥의 length에 접근
}
println(filterResult)
}
...
filteredNames(4)
이렇게 클로저를 사용하면 내부의 람다식 함수에서 외부 함수의 변수에 접근해 처리해서 효율성을 높일 수 있고 완전히 다른 함수에서 변수의 접근을 제한할 수 있습니다.
코틀린의 표준 라이브러리는 이러한 개념들이 사용되어 설계되었습니다.
참고자료
http://www.yes24.com
생각해보세요.
이제 클로저의 사용 개념을 이해하셨나요? 클로저 사용된 사례들을 검색하고 그 예를 댓글을 통해 남겨보세요!
comment
안드로이드 스튜디오에서 해당 람다식 외부 변수를 이용할 수 있다.
클로저는 접근 권한 제어, 부분 적용 함수, 커링 함수에 사용될 수 있습니다.