PHP 통합 가이드
NetFUNNEL PHP 에이전트는 웹 서버에서 요청 단위로 유입을 제어합니다. run()의 결과에 따라 아래와 같이 처리합니다.
| 반환 값 | 후속 처리 |
|---|---|
true |
원래 페이지를 그대로 응답합니다. |
false |
getRedirectUrl()로 대기실 URL을 받아 302로 리다이렉트합니다. |
1. 최소 요구 사항
섹션 제목: “1. 최소 요구 사항”- PHP 7.4 이상
- PHP 확장:
ext-json,ext-curl - NetFUNNEL 서버와 HTTPS(443) 통신 가능
2. 에이전트 설치
섹션 제목: “2. 에이전트 설치”2.1 설치 위치
섹션 제목: “2.1 설치 위치”에이전트는 프로젝트 안, DocumentRoot 밖에 설치합니다.
| 구성 | 설치 위치 |
|---|---|
| Composer 사용 | vendor/netfunnel/php-agent/ (자동) |
| Zend Framework 1 등 | library/netfunnel-php-agent/ |
| CodeIgniter 3 | application/third_party/netfunnel-php-agent/ |
| CodeIgniter 4 | app/ThirdParty/netfunnel-php-agent/ |
| 프레임워크 없음 | lib/netfunnel-php-agent/ |
2.2 설치
섹션 제목: “2.2 설치”프로젝트의 composer.json에 아래 내용을 추가한 뒤 composer install을 실행합니다.
{ "require": { "netfunnel/php-agent": "4.6.0" }, "repositories": [ { "type": "package", "package": { "name": "netfunnel/php-agent", "version": "4.6.0", "dist": { "url": "https://agent-lib.stclab.com/agents/was/php/netfunnel-php-agent-4.6.0.tar.gz", "type": "tar" }, "autoload": { "psr-4": { "NetfunnelAgent\\": "src/" } }, "require": { "php": "^7.4 || ^8.0", "ext-json": "*" } } } ]}내려받은 파일을 설치 위치에 압축 해제합니다. <설치위치>는 2.1 설치 위치를 참고해 바꿉니다.
mkdir -p <설치위치>/netfunnel-php-agenttar -xzf netfunnel-php-agent-4.6.0.tar.gz --strip-components=1 \ -C <설치위치>/netfunnel-php-agent3. 에이전트 적용
섹션 제목: “3. 에이전트 적용”애플리케이션 구성에 맞춰 하나를 선택합니다.
| 구성 | 적용 방법 |
|---|---|
| Pure PHP | auto_prepend_file |
| Zend Framework 1 | 프론트 컨트롤러 플러그인 |
| Laravel | 글로벌 미들웨어 |
| CodeIgniter 3 / 4 | 진입점 index.php |
코드의 {CLIENT_ID}는 콘솔에서 발급받은 값으로 바꿉니다. timeoutMs는 NetFUNNEL 서버 응답을 기다리는 최대 시간(ms)이며, 이 시간을 넘기면 제어 없이 통과합니다.
3.1 Pure PHP
섹션 제목: “3.1 Pure PHP”auto_prepend_file을 사용하면 기존 PHP 파일을 수정하지 않고 적용할 수 있습니다. 프로젝트 루트(DocumentRoot 밖)에 netfunnel-prepend.php를 만듭니다.
<?php/** * NetFUNNEL 유입 제어. auto_prepend_file 로 모든 PHP 진입점 앞에서 실행된다. */if (PHP_SAPI === 'cli') { return;}require_once __DIR__ . '/lib/netfunnel-php-agent/autoload.php';if (!class_exists('NetfunnelAgent\Netfunnel')) { return;}try { $netfunnel = new NetfunnelAgent\Netfunnel(array( 'clientId' => '{CLIENT_ID}', 'timeoutMs' => 1500, )); $allowed = $netfunnel->run();} catch (Throwable $error) { error_log('[netfunnel] fail-open: ' . $error->getMessage()); return;}if ($allowed) { return;}$redirectUrl = $netfunnel->getRedirectUrl();if ($redirectUrl !== '') { header('Location: ' . $redirectUrl, true, 302); exit;}실행 방식에 맞춰 아래 중 하나로 auto_prepend_file을 설정합니다. 경로는 절대경로로 지정합니다.
| 실행 방식 | 설정 위치 | 설정 값 |
|---|---|---|
| mod_php | .htaccess |
php_value auto_prepend_file <프로젝트루트>/netfunnel-prepend.php |
| mod_php | php.ini |
auto_prepend_file = <프로젝트루트>/netfunnel-prepend.php |
| php-fpm | pool 설정 | php_value[auto_prepend_file] = <프로젝트루트>/netfunnel-prepend.php |
3.2 Zend Framework 1
섹션 제목: “3.2 Zend Framework 1”프론트 컨트롤러 플러그인으로 라우팅 전에 유입을 제어합니다.
1) 오토로더 추가 — public/index.php에서 프레임워크 부트스트랩보다 앞에 넣습니다.
// NetFUNNEL 에이전트 오토로더require_once __DIR__ . '/../library/netfunnel-php-agent/autoload.php';require_once 'Zend/Application.php';2) 플러그인 작성 — library/Netfunnel/Plugin.php를 새로 만듭니다.
<?php/** * NetFUNNEL 유입 제어 플러그인. 라우팅 전에 동작한다. */class Netfunnel_Plugin extends Zend_Controller_Plugin_Abstract{ public function routeStartup(Zend_Controller_Request_Abstract $request) { if (PHP_SAPI === 'cli') { return; } if (!class_exists('NetfunnelAgent\Netfunnel')) { return; } try { $netfunnel = new NetfunnelAgent\Netfunnel(array( 'clientId' => '{CLIENT_ID}', 'timeoutMs' => 1500, )); if ($netfunnel->run()) { return; } $redirectUrl = $netfunnel->getRedirectUrl(); } catch (Throwable $error) { error_log('[netfunnel] fail-open: ' . $error->getMessage()); return; } if ($redirectUrl === '') { return; } $this->getResponse() ->setRedirect($redirectUrl, 302) ->sendResponse(); exit; }}3) 플러그인 등록 — application/Bootstrap.php에서 플러그인 스택 맨 앞(작은 stackIndex)에 등록합니다.
protected function _initNetfunnel(){ Zend_Controller_Front::getInstance()->registerPlugin(new Netfunnel_Plugin(), 1);}3.3 Laravel
섹션 제목: “3.3 Laravel”글로벌 미들웨어로 모든 요청에 대기열 제어를 적용합니다.
<?phpnamespace App\Http\Middleware;
use Closure;use Illuminate\Http\Request;use NetfunnelAgent\Netfunnel;use Throwable;
class NetfunnelMiddleware{ public function handle(Request $request, Closure $next) { try { $netfunnel = new Netfunnel(['clientId' => '{CLIENT_ID}']); $allowed = $netfunnel->run(); } catch (Throwable $error) { return $next($request); // fail-open } return $allowed || $netfunnel->getRedirectUrl() === '' ? $next($request) : redirect()->away($netfunnel->getRedirectUrl(), 302); }}미들웨어는 글로벌 미들웨어 맨 앞에 등록합니다.
->withMiddleware(function (Middleware $middleware) { $middleware->prepend(\App\Http\Middleware\NetfunnelMiddleware::class);})protected $middleware = [ \App\Http\Middleware\NetfunnelMiddleware::class, // ... 기존 미들웨어];3.4 CodeIgniter
섹션 제목: “3.4 CodeIgniter”에이전트를 설치한 디렉터리 옆에 netfunnel.php를 만들고, 진입점에서 프레임워크 부트스트랩보다 앞에 불러옵니다.
1) 제어 파일 작성 — CodeIgniter 3은 application/third_party/, CodeIgniter 4는 app/ThirdParty/에 netfunnel.php를 새로 만듭니다.
<?php/** * NetFUNNEL 유입 제어. 진입점 index.php 에서 프레임워크 부트스트랩보다 앞에 실행된다. */if (PHP_SAPI === 'cli') { return;}require_once __DIR__ . '/netfunnel-php-agent/autoload.php';if (!class_exists('NetfunnelAgent\Netfunnel')) { return;}try { $netfunnel = new NetfunnelAgent\Netfunnel(array( 'clientId' => '{CLIENT_ID}', 'timeoutMs' => 1500, )); $allowed = $netfunnel->run();} catch (Throwable $error) { error_log('[netfunnel] fail-open: ' . $error->getMessage()); return;}if ($allowed) { return;}$redirectUrl = $netfunnel->getRedirectUrl();if ($redirectUrl !== '') { header('Location: ' . $redirectUrl, true, 302); exit;}2) 진입점에 추가 — 버전에 맞는 위치에 한 줄을 추가합니다.
index.php에서 BASEPATH.'core/CodeIgniter.php'를 불러오는 줄 바로 위에 추가합니다.
// NetFUNNEL 유입 제어require_once APPPATH . 'third_party/netfunnel.php';require_once BASEPATH.'core/CodeIgniter.php';public/index.php에서 app/Config/Paths.php를 불러오는 줄 바로 위에 추가합니다.
// NetFUNNEL 유입 제어require_once __DIR__ . '/../app/ThirdParty/netfunnel.php';require FCPATH . '../app/Config/Paths.php';4. Initialize 설정
섹션 제목: “4. Initialize 설정”new NetfunnelAgent\Netfunnel(...)에 넘기는 배열의 키입니다.
| 필드 | 타입 | 기본값 | 필수 | 설명 | 에이전트 버전 |
|---|---|---|---|---|---|
clientId |
STRING | N/A | O | 콘솔에서 발급받은 클라이언트 아이디를 입력합니다. | 4.6.0 이상 |
timeoutMs |
INTEGER | 3000 | X | NetFUNNEL 서버 응답을 기다리는 최대 시간(ms)입니다. 시간을 넘기면 제어 없이 통과합니다. | 4.6.0 이상 |
returnKey |
BOOLEAN | true | X | 사용자가 대기열을 통과해 페이지에 진입하면 즉시 다음 사용자가 입장할 수 있습니다. 비활성화하면 진입 후에도 일정 시간 다음 사용자가 대기합니다. (타임아웃은 콘솔의 세그먼트 설정 > 고급설정에서 가능합니다.) | 4.6.0 이상 |
goodBots |
ARRAY | N/A | X | 선의의 봇(검색엔진 등)을 진입 요청에서 제외합니다. User-Agent에 해당 문자열이 포함되는지로 판단하며, 대소문자를 구분합니다. 예시: ['Googlebot', 'Bingbot'] |
4.6.0 이상 |
vwrPageDomain |
STRING | N/A | X | CNAME 도메인만으로 VWR Page URL을 구성할 때 사용합니다. 예시: https://vwr.example.com |
4.6.0 이상 |
cookieDomain |
STRING | N/A | X | 발급되는 NetFUNNEL 쿠키의 도메인(Domain) 값을 직접 지정합니다. | 4.6.0 이상 |
5. 적용 확인
섹션 제목: “5. 적용 확인”아래 명령으로 에이전트가 정상 적용되었는지 확인합니다. <고객사도메인>과 <제어대상URL>은 실제 값으로 바꿉니다.
# 에이전트 탑재 확인curl -si https://<고객사도메인>/ | grep -i x-nf-ver
# 제어 대상 URL 확인curl -si -H 'Accept: text/html' 'https://<고객사도메인>/<제어대상URL>'| 확인 항목 | 기대 결과 |
|---|---|
| 에이전트 탑재 | 응답에 x-nf-ver: 4.6.0 헤더가 포함됩니다. |
| 제어 대상 URL | _nf_key로 시작하는 쿠키가 발급됩니다. 대기가 발생하면 302 응답과 함께 대기실 URL이 Location으로 내려옵니다. |