실시간 채팅 기능을 PHP로 구현할 수 있을지에 대한 궁금증에서 출발하여,
WebSocket 서버 환경을 직접 구성하고 동작을 확인해본 내용을 정리하였습니다.
시작하게 된 배경입니다
최근 실시간 기능에 대한 관심이 생기면서, PHP로도 실시간 채팅을 구현할 수 있는지 알아보게 되었습니다.
조사 과정에서 PHP에서 WebSocket 서버를 실행할 수 있도록 도와주는 Swoole 확장을 알게 되었으며,
이를 통해 직접 환경을 구성하고 실행해보았습니다.
특히 Swoole은 C 언어로 개발된 PHP 확장으로, PHP로 작성된 기존의 WebSocket 라이브러리보다 훨씬 뛰어난 성능을 제공합니다.
네이티브 수준의 처리 속도와 낮은 메모리 소비 덕분에 실시간 통신 기능에 적합하다는 평가를 받고 있습니다.
Apache + PHP + 확장 모듈 설치입니다
다음 명령어를 통해 Apache 및 PHP, 그리고 각종 PHP 확장 모듈들을 설치하였습니다.
sudo apt update && sudo apt install -y \
apache2 \
php \
php-cli \
php-fpm \
php-dev \
php-pear \
libcurl4-openssl-dev \
php-curl \
php-mbstring \
php-xml \
php-mysql \
php-pgsql \
php-sqlite3 \
php-gd \
php-zip \
php-json \
php-bcmath \
php-intl \
php-readline \
php-memcached \
php-redis \
php-imagick \
php-xdebug \
composer \
unzip \
git \
curl
Bash
복사
•
php-dev는 Swoole을 컴파일하기 위해 필수적인 패키지입니다.
•
기타 확장들은 이후 개발 실험을 위한 환경을 고려하여 함께 설치하였습니다.
Swoole 소스 설치 과정입니다
Swoole은 현재 apt로 직접 설치가 불가능하기 때문에, GitHub의 공식 저장소에서 소스를 내려받아 직접 빌드하였습니다.
git clone https://github.com/swoole/swoole-src.git
cd swoole-src
phpize
./configure
make
sudo make install
Bash
복사
•
phpize는 PHP 확장을 컴파일할 수 있는 환경을 설정하는 명령어입니다.
•
make install 이후에는 swoole.so 파일이 생성되며, PHP에서 사용할 수 있게 됩니다.
PHP에 swoole 확장을 등록합니다
CLI에서 swoole을 사용할 수 있도록 확장 설정 파일을 생성합니다.
echo "extension=swoole.so" | sudo tee /etc/php/8.1/cli/conf.d/20-swoole.ini
Bash
복사
•
WebSocket 서버는 CLI 환경에서 실행하므로, CLI 전용 설정 경로에 등록하였습니다.
swoole 설치 여부 확인입니다
다음 명령어를 통해 swoole 확장이 정상적으로 등록되었는지 확인할 수 있습니다.
php -m | grep swoole
Bash
복사
•
출력 결과에 swoole이 포함되어 있으면 정상적으로 설치된 것입니다.
설치 후 소스 디렉토리 정리입니다
사용이 끝난 소스 디렉토리는 아래와 같이 삭제하였습니다.
cd ..
rm -rf swoole-src/
Bash
복사
Apache 가상 호스트를 이용한 WebSocket 프록시 구성입니다
Swoole는 자체적으로 HTTP 서버를 구동하지만, 기존 Apache 웹 서버와 통합하기 위해 프록시 설정을 추가하였습니다.
이를 통해 도메인을 통해 Swoole WebSocket 서버에 접근할 수 있도록 구성하였습니다.
HTTP, HTTPS용 가상 호스트 설정입니다
<VirtualHost *:80>
ServerAdmin example@domain.com
ServerName example-domain.com
RewriteEngine on
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /ws ws://localhost:9502/
ProxyPassReverse /ws ws://localhost:9502/
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /ws/(.*) ws://localhost:9501/$1 [P,L]
ErrorLog "/var/log/apache2/example-domain.com-error.log"
CustomLog "/var/log/apache2/example-domain.com-access.log" common
</VirtualHost>
<VirtualHost *:443>
ServerAdmin example@domain.com
ServerName example-domain.com
SSLEngine on
SSLProtocol all -SSLv2 -SSLv3
SSLCertificateKeyFile /home/example/ssl/current/example-domain_com_SHA256WITHRSA.key
SSLCertificateFile /home/example/ssl/current/example-domain_com.crt
SSLCACertificateFile /home/example/ssl/current/ChainCA/SectigoRSADomainValidationSecureServerCA.crt
SSLCertificateChainFile /home/example/ssl/current/ChainCA/rsa-dv.chain-bundle.pem
ErrorLog "/var/log/apache2/example-domain.com-ssl_error.log"
CustomLog "/var/log/apache2/example-domain.com-ssl_access.log" common
ProxyRequests Off
ProxyPreserveHost On
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Ssl "on"
RequestHeader set X-Forwarded-Port "443"
<Location "/ws">
ProxyPass ws://localhost:9502/ timeout=300 connectiontimeout=300 keepalive=On
ProxyPassReverse ws://localhost:9502/
</Location>
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteCond %{HTTP:Connection} =Upgrade [NC]
RewriteRule /ws(.*) ws://localhost:9501$1 [P,L]
</VirtualHost>
Bash
복사
이 설정을 통해, wss://example-domain.com/ws 경로로 WebSocket 서버에 접근할 수 있게 됩니다.
SSL 인증서도 함께 적용하여 보안 연결을 지원하고 있습니다.
간단한 WebSocket 서버 예제입니다
Swoole을 이용하여 아래와 같이 기본적인 WebSocket 서버를 실행할 수 있습니다.
<?php
$server = new Swoole\WebSocket\Server("0.0.0.0", 9502);
$server->on("open", function ($server, $req) {
echo "Connection opened: {$req->fd}\n";
});
$server->on("message", function ($server, $frame) {
echo "Received message: {$frame->data}\n";
$server->push($frame->fd, "Server: {$frame->data}");
});
$server->on("close", function ($server, $fd) {
echo "Connection closed: {$fd}\n";
});
$server->start();
PHP
복사
•
위 코드를 실행하면 9502 포트에서 WebSocket 서버가 동작하게 됩니다.
php websocket.php
Bash
복사
브라우저에서 WebSocket 연결 예제입니다
아래는 JavaScript를 이용한 클라이언트 연결 예제입니다.
const ws = new WebSocket("ws://localhost:9502");
ws.onopen = () => {
ws.send("Hello from browser!");
};
ws.onmessage = e => {
console.log("From server:", e.data);
};
JavaScript
복사
마무리하며
Swoole을 활용하면 PHP에서도 충분히 WebSocket 기반의 실시간 통신 기능을 구현할 수 있다는 사실을 확인하였습니다.
기존의 요청-응답 기반 방식과는 다른 방식으로 서버를 구성할 수 있어 흥미로웠으며,
무엇보다도 C 언어로 개발된 확장인 만큼 성능과 안정성 측면에서 매우 우수하다는 인상을 받았습니다.
이제 이 환경을 기반으로 실시간 채팅 기능을 직접 구현해볼 계획이며,
앞으로는 Redis 연동이나 채팅방(Room) 기능, 메시지 브로드캐스트 등 다양한 기능을 실험해볼 예정입니다.