문제: SSE 연결이 자주 끊어짐
해결책: 적절한 헤더 설정과 keep-alive
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
while (true) {
echo "data: " . json_encode(['message' => 'Hello']) . "\n\n";
ob_flush();
flush();
sleep(5);
}
문제: SSE 실행 중 다른 페이지 접근 불가
해결책: 세션 조기 종료
session_start();
$userId = $_SESSION['user_id'];
session_write_close(); // 세션 잠금 해제
header('Content-Type: text/event-stream');
// SSE 로직 계속...
문제: 실시간 확인을 위한 과도한 DB 쿼리
해결책: Redis를 이용한 pub/sub 패턴
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 알림 발송
$redis->publish('notifications', json_encode([
'user_id' => 123,
'message' => '새 메시지가 도착했습니다'
]));
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->subscribe(['notifications'], function($redis, $channel, $message) {
echo "data: $message\n\n";
ob_flush();
flush();
});
문제: 브라우저당 동시 연결 수 제한
해결책: 단일 SSE 연결로 모든 알림 처리
header('Content-Type: text/event-stream');
while (true) {
$notifications = getNotifications($userId);
if (!empty($notifications)) {
foreach ($notifications as $notification) {
echo "data: " . json_encode($notification) . "\n\n";
}
ob_flush();
flush();
}
sleep(2);
}
문제: 장시간 실행으로 인한 메모리 부족
해결책: 메모리 사용량 모니터링 및 제한
ini_set('memory_limit', '128M');
while (true) {
if (memory_get_usage() > 100 * 1024 * 1024) { // 100MB
break;
}
// 알림 처리 로직
unset($notifications); // 변수 해제
gc_collect_cycles();
sleep(1);
}
문제: 웹서버에서 장시간 실행 스크립트 종료
해결책: 타임아웃 설정 조정
set_time_limit(0); // 무제한
ignore_user_abort(true); // 사용자 연결 끊어져도 계속 실행
header('Content-Type: text/event-stream');
header('X-Accel-Buffering: no'); // Nginx 버퍼링 비활성화
while (connection_status() == CONNECTION_NORMAL) {
// 알림 로직
sleep(1);
}
문제: 같은 알림이 여러 번 전송됨
해결책: 알림 상태 관리
function sendNotification($userId, $message) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$notificationId = uniqid();
$key = "notification:$userId:$notificationId";
if (!$redis->exists($key)) {
$redis->setex($key, 3600, 1); // 1시간 동안 중복 방지
echo "data: " . json_encode([
'id' => $notificationId,
'message' => $message
]) . "\n\n";
}
}
문제: 모바일에서 백그라운드 시 연결 끊김
해결책: 재연결 로직 구현
function connectSSE() {
const eventSource = new EventSource('/notifications.php');
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
showNotification(data.message);
};
eventSource.onerror = function() {
eventSource.close();
setTimeout(connectSSE, 5000); // 5초 후 재연결
};
}
문제: 웹 브라우저 닫힘 시 알림 불가
해결책: 웹 푸시 알림 구현
use Minishlink\WebPush\WebPush;
$webPush = new WebPush([
'VAPID' => [
'subject' => 'mailto:admin@example.com',
'publicKey' => $publicKey,
'privateKey' => $privateKey
]
]);
$report = $webPush->sendOneNotification(
$subscription,
json_encode(['title' => '새 알림', 'body' => '메시지 내용'])
);