[PHP] register_shutdown_function() (종료된 후 함수실행하기)

항해자·2023년 3월 27일
1

PHP

목록 보기
2/3
post-thumbnail

끝난소스에 부가적인 로직을 실행한다? 그걸 어디에 쓰나요?

아래와 같은 상황을 상상해봅시다.

1. 로직이 종료될때, 사용중이던 파일 핸들러와 DB커덱션을 종료하고 싶다.
2. 에러가 발생했을때 무언가 처리하고 싶다.
3. 로직이 종료되면 백그라운드에서 대용량 파일을 다운받고 싶다.

우선 1번과 2번의 상황은 모두 굳이 내장함수를 사용하지 않아도 충분히 구현이 가능합니다.

파일 핸들러는 fclose()를 사용하면 되고, DB커넥션도 mysqli_close()등 적절한 종료함수를 사용하면 되니까요.

에러 발생도 결국 try{}catch{} 를 통해 처리해버리면 그만입니다.

원하는 로직들을 처리하는 함수를 만들어서 소스코드 제일 하단에서 실행시키면 간단하니까요.


그런데 소스가 종료되기도 전에 타임아웃으로 스크립트가 중간에 종료되었다면?

만약 내가 작성한 소스코드의 실행이 너무 오래걸려서 하단에 배치한 함수를 실행하기도 전에 타임아웃이 되었다고 가정해봅시다.

결국 마지막에 배치한 내 함수는 어떤 내용이던 간에 실행되지 못한채 프로세스는 종료될 것 입니다.

크론탭을 활용한 스케쥴링등에서 발생할 만한 상황일겁니다.
대용량 데이터를 정제한다던지, 외부 API와 오랜시간 통신해야 한다던지 하는 로직에서요.

PHP는 작성한 로직이 모두 실행된 후 내장함수인 register_shutdown_function()을 활용해서 부가적인 로직을 실행할 수 있습니다.

이러한 경우 사용할 수 있는 함수가 바로 register_shutdown_function()입니다.

register_shutdown_function()의 기본형태는 아래와 같습니다.

register_shutdown_function(callable $callback, mixed ...$args): void

이 내장함수는 인자로 콜백함수와, 콜백함수에 사용될 인자들로 구성되며 별도의 리턴값은 존재하지 않습니다.

또한 스크립트가 종료되었을때 실행될 함수를 등록하는 역할을 하기때문에, 소스코드 어디에 위치해도 무방합니다.

앞서 말씀드린 예시처럼 소스 중간에 시간지연이 과도하게 발생할 수 있는 로직이 있는 경우라면, 소스 상단에 배치하면 됩니다.


function final_running($msg, $param1)
{
	echo '내가 마지막에 실행될것이야!'. $msg. ' '.$param1;
}

register_shutdown_function('final_running', '메세지', '파라미터1');


//시간지연이 오래걸리는 로직

//소스종료

위 예시코드의 final_running()과 같은 함수를 생성하고 해당 함수 안에 종료 후 내가 하고싶은것들,

예를 들어 사용중인 파일 핸들러를 닫는다던지, DB의 커넥션을 종료한다던지와 같은 리소스의관리는 물론 별도의 로그를 생성한다던지 여러가지 프로세스들을 구현하여 사용할 수 있습니다.

register_shutdown_function()의 특성은 또 다른 활용사례를 생각해 볼 수 있습니다.

예를들어 소스가 종료되었을때, 용량이 큰 대용량 파일을 다운받는 로직을 php가 아닌 백그라운드에서 실행한다고 했을때,

exec()함수를 응용하여 final_running()안에서 사용할 수 도 있습니다.

※exec()와 같은 함수는 시스템명령을 실행할 수 있으니 보안처리에 주의해주세요

스크립트는 종료되었어도 백그라운드에서 대용량 파일의 다운로드를 비동기로 실행할 수 있게 되니까요.

만약 final_running()외에도 다른 함수들을 실행하고 싶다면?

final_running()내에 여러개의 함수를 추가하여 사용할 수도 있지만 기타 여러가지 여건상 분리하여 함수를 관리해야 한다면?

그냥 register_shutdown_function()을 여러개 사용하면됩니다.

final_running()
{
	//종료후 실행 로직1
}

final_running2()
{
	//종료후 실행될 로직2
}


register_shutdown_function('final_running');
register_shutdown_function('final_running2');

이와 같이 작성하는경우, register_shutdown_function()이 호출된 순서에따라 final_running()final_running2()가 순서대로 실행됩니다.

끝으로 이 함수는 로직의 종료 뿐만 아니라 exit()가 호출되었을 경우에도 함께 동작하는 점도 알아두시면 좋겠습니다.

profile
웹개발자

0개의 댓글