NAS를 뒤늦게 6.0으로 업데이트한 후부터 php 스크립트를 실행하면 60초 timeout에 걸려 504 gateway error가 나는 것 때문에 고생했었다. flush() 함수를 사용해서 버퍼를 실시간으로 출력시켜주는 것으로 문제를 해결했다가, 최종적으로는 nginx timeout 시간을 300초로 늘이는 방법을 찾아서 적용했다.

브라우저에서 스크립트를 실행했을 때 실시간으로 화면에 결과가 보이는게  편할 때가 있다. 그래서, 특정 스크립트는 이전 처럼 버퍼를 실시간으로 출력하게 바꿔서 쓰고 있었는데, 오랫만에 실행을 했더니 flush() 함수가 전혀 먹지를 않았다. nginx timeout 설정을 원복해봐도 변화가 없고 60초 timeout으로 인한 504 gateway error도 나지 않는다.

기본 설정에서 에러가 발생하지 않는 것은 좋은데, 실시간 출력이 안된다는 것이 아쉬워 방법을 찾아보았다. 많은 글들이 있었지만, 내 경우에 정확히 적용되는 방법은 Streaming PHP – disabling output buffering in PHP, Apache, Nginx, and Varnish 라는 글에서 찾을 수 있었다.

터미널에서는 flush() 함수가 정상적으로 동작하여 실시간 출력이 되지만, 브라우저에서는 브라우저 내부 버퍼 및 압축 설정 등으로 실시간 출력이 그냥 안된다는 것이 해당 글의 요지다.

아래는 해당 글을 조금 수정하여 실제로 적용하고 있는 코드이다.

////// Nginx에서 실시간 출력을 하기 위한 설정 추가 - 171212

// Set a valid header so browsers pick it up correctly.
header('Content-type: text/html; charset=utf-8');

// Explicitly disable caching so Varnish and other upstreams won't cache.
header("Cache-Control: no-cache, must-revalidate");

// Setting this header instructs Nginx to disable fastcgi_buffering and disable
// gzip for this request.
header('X-Accel-Buffering: no');

if($_REQUEST["debug"])    $string_length = 32768;
else $string_length = 0;

////// Nginx에서 실시간 출력을 하기 위한 설정 추가 - 171212

string_length를 가이드에서 알려주는 4096으로 설정하면, 여러줄이 한번에 출력이 되기에 내 상황에 맞게 숫자를 키웠다. 32768 이상은 별 차이가 없었다. terminal에서 실행하면 string_length만큼 빈칸이 출력되기 때문에 브라우저에서 클릭하는 링크에만 debug=1 쿼리를 넣고, cron으로 돌릴때는 debug 쿼리를 없앤다.

php의 가장 상단에 위의 코드를 넣고, 실시간 출력이 필요한 부분 앞에 아래의 코드를 추가 한다.

////// Nginx에서 실시간 출력을 하기 위한 설정 추가 - 171212

$string = str_pad('', $string_length);
echo $string;

////// Nginx에서 실시간 출력을 하기 위한 설정 추가 - 171212

echo $result;
flush();

string_length만큼 빈칸을 먼저 출력하여 브라우저의 버퍼를 채워버리게 된다. 이 다음에 출력되는 result는 버퍼가 이미 채워져 있으니 flush() 함수가 나오면 result가 화면에 바로 뿌려진다. for문 안에서 사용시 가장 효과적이다.