티스토리 뷰

반응형
SMALL

이번 포스트에서는 함수형 프로그래밍 중 클로저의 개념에 대해 살펴보도록 하겠습니다.

클로저(Closure)는 함수가 호출될 때 발생하는 데이터를 함수가 호출된 이후에도 계속 유지해서 사용하는 기법입니다.

fun closureFunction(num: Int) {
    println("arguments : $num")
}

num이라는 변수는 함수가 종료되면 사라지는 즉, 스코프는 함수 내부가 됩니다.

함수형 프로그래밍에서는 함수에 선언된 변수가 호출 후에도 유지되어야 하는 경우도 있습니다.

그 이유는 함수형 프로그래밍에서는 함수가 1급 객체이기 때문에 함수 내부에 함수를 정의할 수 있기 때문입니다.

fun closureFunction(num: Int): (Int) -> Int {
    println("argument $num")
    return { it * 10 }
}

fun main(args: Array<String>) {
    val someFun1 = closureFunction(2)
    val someFun2 = closureFunction(3)
    
    println("${someFun1(10)}")
    println("${someFun2(10)}")
}

위의 코드의 실행 결과는 어떻게 될까요?

argument 2
argument 3
100
100

우선 closureFunction을 호출했고 이 함수의 결과로 람다 함수를 선언했습니다. 이 람다 함수는 함수 내부에서 선언된 함수입니다.

쉽게 말하면 closureFunction의 내장 함수입니다. 그런데 이 내장 함수는 closureFunction() 내부에서만 이용하지 않습니다.

main함수 안에서 someFun1과 someFun2에 각각 저장해놓았다가 이용하고 있습니다.

함수 내부에서 정의한 함수가 함수 실행 후에 이용되고 있는 것을 나타낸 예시 코드입니다. 이 코드를 자바로 변환하면 아래와 같습니다.

public static final Function1 closureFunction(int num) {
    String var1 = "argument " + num;
    System.out.println(var1);
    return (Function1)null.INSTANCE;
}

위에 코틀린 코드에서 람다 함수에서 closureFunction의 지역 변수에 접근하지 않았습니다.

만약 접근해서 이용하게 된다면 어떻게 될까요? 아래 코드를 살펴보도록 하겠습니다.

fun closureFunction(num: Int) : (Int) -> Int {
    println("argument $num")
    return { it * num }
}

fun main(args: Array<String>) {
    val someFun1 = closureFunction(2)
    val someFun2 = closureFunction(3)
    
    println("${someFun1(10)}")
    println("${someFun2(10)}")
}

무엇이 달라졌을까요? 딱 하나가 바뀌었습니다.

closureFunction의 반환값인 람다 함수에서 it * 10이 it * num으로 지역변수를 사용한 것을 알 수 있습니다.

분명 closureFunction은 종료가 되었음에도 불구하고 num이라는 지역변수가 계속 사용되었습니다.

이 때 이용되는 개념이 Closure라는 것입니다. 특정 코드 구현 방법이나 특별한 키워드가 있는 것은 아닙니다. 그저 함수가 종료된 후에도 사용할 수 있도록 바인딩을 해주는 기법들을 통칭하는 말입니다.

 

클로저가 적용된 자바 코드를 보면 아래와 같습니다.

public static final Function1 closureFunction(int num) {
    String var1 = "argument " + num;
    System.out.println(var1);
    return (Function1)(new Function1() {
        public Object invoke(Object var1) {
            return this.invoke((Number)var1).intValue());
        }
        
        public final int invoke(int it) {
            return it * num;
        }
    });
}

내부적으로 closureFunction에 포함된 변수까지 포함한 객체를 반환(Return)하기 때문에 함수가 종료되더라도 closureFunction의 변수를 사용할 수 있는 것입니다.

 

이번 포스트에서는 클로저에 대해 간단하게 살펴보았습니다.

반응형
LIST
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함