웹서버 응답제한시간 초과에 대응하기 위해 웹서버 버퍼 내보내기를 해보자. php flush() 사용법

웹서버 응답제한시간 초과에 대처하는 php 의 방안

모든 웹 언어는 아무리 늦어도 수초 안에 동적인 페이지지 생성을 끝내고 웹서버 혹은 WAS 에서 바로 웹 브라우저로 내보내기(flush)를 처리하지만

동보메일 처럼 여러 사람에게 수천통의 메일발송을 웹페이지로 구현해야 하는 경우
처리 시간이 길어저 웹서버에 설정된 응답 제한시간 초과하는 일이 발생한다.

이럴때는 웹서버 응답시간 이내에 브라우저로 뭔가를 지속적으로 보내주는 처리를 해야 한다.

이럴때 사용하는 명령이 flush() 입니다.

사용법은 아주 간단하다.

sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송)
echo "

====1===
";
flush();

sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송)
echo "

====2===
";
flush();

sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송)
echo "

====3===
";
flush();

뭥미?
이게 전부임?

뭘 바랬는지 모르지만 이게 전부다.
다른 언어도 이와 비슷한 함수들이 있으니 언어별로 조금만 바꾸면 모두 적용 할 수 있다.

여기서 끝내면 뭔가 찝찝하다. 마치 화장실 갔다가 휴지가 없어서 알아서(?) 뒷처리를 하고 나온 것 처럼…

실제로 딱 위 내용 까지만 적용했다가 고객 클레임 전화를 받고 이라이더에게 전화나 카톡, 이메일 (최신 연락처는 언제든 블로그 하단이나 공지사항에 공개 되어 있다)로 항의 할지도 모르다.

실제로 해보면 내가 테스트 할때는 퍼펙트하게 잘 되지만 서비스에 적용해 놓으면 여기 저기서 전화오고 난리가 날것이다.
여기에 하나 빠진것이 있는데 사용자의 브라우저 종류와 버전 이다.

여기서 기초적인 웹페이지를 가져오는 방식을 알아야 한다.
사용자는 브라우저가 웹서버에 웹페이지를 요청하고
웹서버는 요청한 페이지를 동적으로 생성해서 버퍼에 넣고 끝나면 자동으로 버퍼의 내용을 브라우저에 전송하고 웹페이지가 끝났다고 신호를 같이 보낸다

하지만 flush() 는 웹서버의 현재 버퍼에 있는 데이터(웹페이지)를 먼저 사용자의 브라우저에 보내지만 끝났다는 신호는 안 보낸다는것이 문제다.
(왜? 아직 페이지를 동적으로 생성중이니까!)

그래서 어떤 브라우저는 화면에 아무 출력도 없이 끝났다는 신호가 들어올때까지 마냥 기다리거나 아니면 응답없음으로 접속을 끊어 버린다.

그럼 flush() 는 처음 부터 쓸수 없는 것이였나?
결론만 얘기하면 아니다.

flush() 는 웹서버 입장에서 정상적으로 동작한것인데 문제는 웹브라우저에 있다.
크롬, 오페라 같은 브라우저는 flush() 로 내보낸 데이터를 바로 받아서 화면에 뿌려주지만(화면 출력을 이렇게도 표현한다)
FF(Fire Fox : 파이어폭스) 는 1024byte 가 다 찰때까지 기다리고
IE 10(Internet Explorer 10)은 4096byte 가 다 찰때까지 기다리는것이 문제다.

브라우저 별로 정리하면 다음과 같다. (IE11 이나 엣지, 사파리 같은 나머지 최신 브라우저는 알아서 조사해서 댓글로 좀 알려 주세요)

 * IE 10 : 4096 바이트
 * FF 21.0 : 1024 바이트 / 하위버젼 호환성을 위해 최초 제일 뒤에 "n" 넣을것
 * 크롬 29.0 : 상관없음
 * Opera 16.0 : 상관없음

이렇다 보니 개발자가 크롬에서 개발할 때는 아주 잘 되다가
서비스에 올리면 사용자의 브라우저에 따라서 화면에 아무것도 출력이 안될 수 있다.

그럼 해결 방법은 아주 간단하다.
웹서버 버퍼에 강제로 4096 byte 이상을 넣은 후에 flush() 를 하면 된다.

sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송)
echo "

====1===
";
echo str_repeat(' ', 4096). "n";
flush();

sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송)
echo "

====2===
";
echo str_repeat(' ', 4096). "n";

sleep(2); // 시간이 걸리는 업무 처리중 (예시: 메일 10건 발송)
echo "

====3===
";
echo str_repeat(' ', 4096). "n";
flush();

참 쉽죠?
오류, 오타, 건의 사항은 이메일, 카톡으로 연락 부탁드립니다. (글 하단이나 공지사항에 연락처 있음)

2016년 11월 15일 추가 :

str_repeat(‘ ‘, 4096)  중간에 ‘ ‘ 사이에 공백이 있습니다.

#브라우저 #php #flush #웹서버 #응답시간 #응답시간초과