웹프로그래밍/PHP

[PHP] 클로저(Closure)

정민교 2022. 3. 21. 17:00

개 념

PHP 공식 문서 발췌

익명 함수(Anonymous function)는 말 그대로 함수의 이름이 없는 함수로 클로저(Closure) 또는 콜백(Callback) 이라고도 부르고 PHP 5.3 부터 추가된 기능이며 5.4 에서 기능이 보강되었습니다.

JavaScript의 함수형 프로그래밍을 모르는 사람은 그렇게 드물지 않을 것이다. PHP에서도 클로저를 이용한 함수형 프로그래밍이 가능하며 그 방법을 포스팅 하려고 한다. 


먼저 클로저란 익명함수 라고도 부르며, 일반 함수와의 차이점은 다음과 같다.

차이점

1. 클로저는 일반 함수와 다르게 외부 함수나 변수에 접근할 수 있다.

2. 클로저는 실행이 완료된 시점에도 함수의 상태와 내부 변수들의 상태 값은 유지된다. (외부함수가 소멸된 후에도 환경(변수)를 기억)

코드로 예시를 들어 자세히 알아보자

1번 차이점

// 일반함수
$strString = "hello";
$fnClosure = function() {
    echo $strString;
}
$fnClosure(); // Undefined variabl: strString

// 클로저
$strString = "hello";
$fnClosure = function() use ($strString) {
    echo $strString;
}
$strString = "Bye";
$fnClosure(); // hello

클로저는 use 키워드를 사용하여 일반 변수와는 다르게 외부 변수에 접근할 수 있다.

 

2번 차이점

// 일반함수
function hello($name) {
    $_name = $name;
    echo "Hello".$_name;
}
hello("민교");    // Hello민교
hello("정민교");  // Hello정민교

// 클로저
function hello($name) {
    $_name = $name;
    return function() {
        echo "Hello".$_name;
    }
}

$hello1 = hello("민교");
$hello2 = hello("정민교");
hello1();    // Hello민교
hello2();    // Hello정민교

두번째 hello function 의 return 값은 클로저(익명함수)로 되어있다. 아래 함수 사용부를 보면, 일반함수는 $_name 값으로 "민교"라는 문자열이 바인딩 되는데 해당 함수가 호출된 후에는 함수가 소멸되어 같은 함수를 사용하기 위해서 또 다시 "민교"라는 함수를 선언해야 한다. 

하지만 클로저의 경우 hello("민교")로 바인딩 된 함수가 함수 실행 후에도 소멸하지 않고 클로저가 전역변수의 값을 기억하고 있어서 별 다른 파라미터 값 설정없이 hello1()만 사용해도 클로저가 외부의 전역변수 값을 가져와서 출력한다.

 

클로저의 사용법

[ 예제 1 ]

function($name, $age) {
    return 'name:'.$name.' age:'.$age;
}

클로저는 익명함수이기 때문에 function 이름 없이 파라미터변수만 작성하면 된다.

 

[ 예제 2 ]

$fnPeople = function($name, $age) {
    return 'name:'.$name.' age:'.$age;
}
echo $fnPeople('gyo', 5);

일반변수에 바로 할당도 가능하다.

 

[ 예제 3 ]

$age = 5;

function fnNormal($name) {
    return function($sex) use ($age, $name) {
        return "name=".$name.", age=".$age.", sex=".$sex;
    }
}

$test = fnNormal("민교");

echo $test("남"); // name=민교, age=5, sex=남

use 키워드를 사용하여 외부변수를 사용가능하며 여러개의 파라미터 변수가 필요하면 , 를 구분자로 사용한다. fnNormal 함수가 $test에 바인딩 되면서 실행이 되고 소멸이 되지만 use 키워드로 받은 $name 파라미터는 소멸되지 않고 계속해서 남게 된다. 따라서 $test에서는 fnNormal의 return 값인 클로저(익명함수)가 할당되고 클로저의 파라미터인 $sex에는 $test 함수가 실행될때의 파라미터인 '남' 이 되며, $age는 전역변수, $name은 소멸되지 않고 남아있던 fnNormal의 $name 값이 들어가게 된다.


마무리

클로저는 콜백을 만들때 아주 유용하다. 특히 php 프레임워크인 라라벨에서는 다양하게 클로저를 사용하고 있고, 대표적으로 URL을 매핑하는 route(라우트)에서 사용하고 있으므로 클로저의 이해가 매우 중요하다고 할 수 있다. 

간단하게 예를 들자면

Route::get('/hello', function() 
{
    return "Hello, World!";
});

/hello 라는 URL로 접근했을 때 Hello, World!를 출력하는 라우팅 처리로 클로저를 사용하고 있다.


참고사이트

https://bkjeon1614.tistory.com/219

http://daplus.net/php-php%EC%97%90%EC%84%9C-%ED%81%B4%EB%A1%9C%EC%A0%80-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B4%EB%A9%B0-%EC%99%9C-%EC%82%AC%EC%9A%A9%EC%8B%9D%EB%B3%84%EC%9E%90%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%A9/

https://demain18-blog.tistory.com/28