PHP에서 웹소켓 통신을 구현할 때 자주 발생하는 문제들과 해결책을 정리했습니다.
문제: PHP 기본 웹소켓 지원 부족
해결책: Ratchet 라이브러리 설치
composer require ratchet/pawl
use Ratchet\Client\WebSocket;
use Ratchet\Client\Connector;
$connector = new Connector();
$connector('ws://localhost:8080')
->then(function (WebSocket $conn) {
$conn->send('Hello World!');
});
문제: 웹소켓 핸드셰이크 과정에서 오류
해결책: 올바른 핸드셰이크 헤더 구성
function createHandshake($key) {
$acceptKey = base64_encode(
sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true)
);
return "HTTP/1.1 101 Switching Protocols\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"Sec-WebSocket-Accept: $acceptKey\r\n\r\n";
}
문제: 웹소켓 서버 포트 사용 중 오류
해결책: 포트 상태 확인 및 변경
netstat -tulpn | grep :8080
use Ratchet\MessageComponentInterface;
use Ratchet\App;
$app = new App('localhost', 8081); // 다른 포트 사용
$app->route('/chat', new ChatComponent);
$app->run();
문제: 웹소켓 메시지 형식 불일치
해결책: 올바른 프레임 구조 구현
function encodeFrame($message) {
$length = strlen($message);
$frame = chr(0x81); // FIN + text frame
if ($length < 126) {
$frame .= chr($length);
} elseif ($length < 65536) {
$frame .= chr(126) . pack('n', $length);
}
return $frame . $message;
}
문제: 클라이언트 연결 끊김 시 서버 오류
해결책: 연결 상태 모니터링
class ChatComponent implements MessageComponentInterface {
protected $clients;
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo "Connection {$conn->resourceId} disconnected\n";
}
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "Error: {$e->getMessage()}\n";
$conn->close();
}
}
문제: 브라우저에서 웹소켓 연결 시 CORS 오류
해결책: 적절한 CORS 헤더 설정
use Ratchet\Http\HttpServer;
use Ratchet\Http\OriginCheck;
$checkedApp = new OriginCheck($app, ['localhost', 'example.com']);
$server = new HttpServer($checkedApp);
문제: 장시간 실행 시 메모리 사용량 증가
해결책: 주기적인 가비지 컬렉션
use React\EventLoop\Loop;
$loop = Loop::get();
$loop->addPeriodicTimer(30, function() {
gc_collect_cycles();
echo "Memory usage: " . memory_get_usage(true) . "\n";
});
문제: 보안 웹소켓(WSS) 연결 실패
해결책: SSL 컨텍스트 설정
$app = new App('localhost', 443, '0.0.0.0', Loop::get());
$app->route('/secure-chat', new ChatComponent, ['*']);
$server = $app->getReactSocket();
$server->listen(443, [
'tls' => [
'local_cert' => '/path/to/cert.pem',
'local_pk' => '/path/to/private.key'
]
]);