메인 콘텐츠로 건너뛰기

Octane이란

Laravel Octane은 고성능 애플리케이션 서버를 사용해 Laravel 애플리케이션의 성능을 극적으로 향상시키는 패키지입니다. 일반적인 PHP-FPM에서는 요청이 있을 때마다 애플리케이션이 시작·종료됩니다. Octane에서는 애플리케이션을 한 번만 시작해 메모리에 보관하고, 이후 요청을 고속으로 처리합니다. PHP-FPM과의 가장 큰 차이는 애플리케이션의 부트 처리(서비스 프로바이더 등록 등)가 요청마다 반복되지 않는다는 점입니다. 한 번 시작하면 그 이후에는 초고속으로 요청을 처리할 수 있습니다.

지원 서버

Octane은 다음 세 가지 서버를 지원합니다.
서버언어설치동시 태스크비고
FrankenPHPGo자동(바이너리)권장. HTTP/3·Brotli 지원
RoadRunnerGo자동(바이너리)심플하고 설정이 용이함
SwoolePHP 확장PECL로 수동동시 태스크·Octane 캐시 사용 가능
Laravel Cloud에서는 FrankenPHP를 사용한 Octane 운영이 권장되며, 완전 관리형으로 지원됩니다.

설치 및 설정

패키지 설치

composer require laravel/octane

Octane 초기 설정

php artisan octane:install
실행하면 서버를 선택하는 프롬프트가 표시됩니다. 선택하면 config/octane.php가 생성됩니다.

FrankenPHP

FrankenPHP를 선택하면 Octane이 자동으로 바이너리를 다운로드합니다. 추가 절차는 필요 없습니다.

RoadRunner

RoadRunner를 선택하면 Octane이 자동으로 바이너리를 다운로드합니다.

Swoole

Swoole은 PHP 확장으로 PECL을 통해 설치합니다.
pecl install swoole
Open Swoole을 사용하는 경우 다음 명령으로 설치합니다.
pecl install openswoole

실행 방법

서버 실행

php artisan octane:start
기본적으로 포트 8000으로 실행됩니다. http://localhost:8000에서 접근할 수 있습니다.

서버 지정

php artisan octane:start --server=frankenphp
php artisan octane:start --server=roadrunner
php artisan octane:start --server=swoole

워커 수 지정

php artisan octane:start --workers=4
Swoole에서 태스크 워커도 지정하는 경우는 다음과 같습니다.
php artisan octane:start --workers=4 --task-workers=6

파일 변경 감시

개발 중에는 파일을 변경해도 서버를 재시작하지 않으면 반영되지 않습니다. --watch 플래그를 사용하면 자동으로 재시작합니다.
php artisan octane:start --watch
--watch를 사용하려면 Node.js와 Chokidar가 필요합니다.
npm install --save-dev chokidar

기타 관리 명령

# 워커 리로드(배포 후 실행)
php artisan octane:reload

# 서버 정지
php artisan octane:stop

# 서버 상태 확인
php artisan octane:status

의존성 주입의 주의점

Octane에서는 애플리케이션이 메모리에 보관되기 때문에, 서비스 프로바이더의 registerboot는 서버 시작 시 한 번만 실행됩니다. 같은 애플리케이션 인스턴스가 요청 간에 재사용되므로 컨테이너나 리퀘스트를 객체 생성자에 주입할 때는 주의가 필요합니다.

컨테이너 주입

싱글턴 생성자에 컨테이너를 직접 주입하면 오래된 컨테이너가 재사용됩니다.
// ❌ 문제가 있는 예 — 오래된 컨테이너가 재사용됨
$this->app->singleton(Service::class, function (Application $app) {
    return new Service($app);
});

// ✅ 안전한 예 — 클로저로 매번 최신 컨테이너를 취득
$this->app->singleton(Service::class, function () {
    return new Service(fn () => Container::getInstance());
});
전역 헬퍼 app()Container::getInstance()는 항상 최신 컨테이너를 반환하므로 안전합니다.

요청 주입

// ❌ 문제가 있는 예 — 오래된 요청이 재사용됨
$this->app->singleton(Service::class, function (Application $app) {
    return new Service($app['request']);
});

// ✅ 안전한 예 — 클로저로 매번 최신 요청을 취득
$this->app->singleton(Service::class, function (Application $app) {
    return new Service(fn () => $app['request']);
});

// ✅ 가장 권장 — 필요한 값만 메서드에 전달
$service->method($request->input('name'));
컨트롤러 메서드나 라우트 클로저에서 Illuminate\Http\Request를 타입힌트하는 것은 안전합니다. 전역 헬퍼 request()도 항상 현재 요청을 반환합니다.

설정 리포지토리 주입

// ❌ 문제가 있는 예 — 설정 값이 바뀌어도 오래된 리포지토리가 사용됨
$this->app->singleton(Service::class, function (Application $app) {
    return new Service($app->make('config'));
});

// ✅ 안전한 예
$this->app->singleton(Service::class, function () {
    return new Service(fn () => Container::getInstance()->make('config'));
});
전역 헬퍼 config()는 항상 최신 설정 리포지토리를 반환하므로 안전합니다.

메모리 누수 대책

Octane은 애플리케이션을 메모리에 보관하므로 정적 프로퍼티 등에 데이터를 축적하면 메모리 누수가 발생합니다.
// ❌ 메모리 누수 예 — 요청마다 $data가 계속 증가
class Service
{
    public static array $data = [];
}

public function index(Request $request): array
{
    Service::$data[] = Str::random(10);
    return [];
}

max-requests로 워커 재활용

워커가 일정 수의 요청을 처리하면 자동으로 재시작하도록 해서 메모리 누수를 완화할 수 있습니다. 기본값은 500 요청입니다.
php artisan octane:start --max-requests=250

최대 실행 시간 설정

config/octane.php에서 요청의 최대 실행 시간을 설정할 수 있습니다. 기본값은 30초입니다.
'max_execution_time' => 30,
max_execution_time을 변경한 경우 Octane 서버를 재시작하세요.

동시 태스크(Swoole 전용)

Swoole을 사용하는 경우 Octane::concurrently()로 여러 처리를 동시에 실행할 수 있습니다.
use App\Models\User;
use App\Models\Server;
use Laravel\Octane\Facades\Octane;

[$users, $servers] = Octane::concurrently([
    fn () => User::all(),
    fn () => Server::all(),
]);
동시 태스크는 Swoole의 “태스크 워커”로서 별도 프로세스에서 실행됩니다. 태스크 워커 수는 --task-workers로 지정합니다.
php artisan octane:start --workers=4 --task-workers=6
concurrently에 전달할 수 있는 태스크는 최대 1024개입니다(Swoole 제한).

Tick과 Interval(Swoole 전용)

Swoole에서는 지정한 간격으로 정기 실행하는 처리를 등록할 수 있습니다. 서비스 프로바이더의 boot 메서드에서 등록합니다.
use Laravel\Octane\Facades\Octane;

// 10초마다 실행
Octane::tick('delayed-ticker', fn () => ray('Ticking...'))
    ->seconds(10);

// 서버 시작 직후에도 즉시 실행
Octane::tick('immediate-ticker', fn () => ray('Ticking...'))
    ->seconds(10)
    ->immediate();

Octane 캐시(Swoole 전용)

Swoole의 Swoole 테이블을 사용한 초고속 인메모리 캐시입니다. 초당 최대 200만 회의 읽기·쓰기가 가능합니다.
use Illuminate\Support\Facades\Cache;

Cache::store('octane')->put('framework', 'Laravel', 30);

인터벌 캐시

지정한 간격으로 자동 갱신되는 캐시입니다.
use Illuminate\Support\Str;

Cache::store('octane')->interval('random', function () {
    return Str::random(10);
}, seconds: 5);
Octane 캐시의 데이터는 서버를 재시작하면 모두 사라집니다.

Swoole 테이블(Swoole 전용)

모든 워커에서 접근 가능한 임의의 인메모리 테이블을 정의할 수 있습니다. config/octane.phptables에서 설정합니다.
'tables' => [
    'example:1000' => [
        'name' => 'string:1000',
        'votes' => 'int',
    ],
],
테이블에 접근하려면 Octane::table() 메서드를 사용합니다.
use Laravel\Octane\Facades\Octane;

Octane::table('example')->set('uuid', [
    'name' => 'Nuno Maduro',
    'votes' => 1000,
]);

$row = Octane::table('example')->get('uuid');
Swoole 테이블에서 사용할 수 있는 컬럼 타입은 string, int, float뿐입니다. 데이터는 서버 재시작으로 사라집니다.

프로덕션 환경에서의 운영

Nginx + Octane 구성

프로덕션 환경에서는 Nginx 뒤에서 Octane을 구동하는 것이 일반적입니다. Nginx가 정적 파일 전송과 SSL 종단을 담당하고, 동적 요청을 Octane에 프록시합니다.
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server {
    listen 80;
    server_name example.com;
    root /home/forge/example.com/public;

    location /index.php {
        try_files /not_exists @octane;
    }

    location / {
        try_files $uri $uri/ @octane;
    }

    location @octane {
        set $suffix "";

        if ($uri = /index.php) {
            set $suffix ?$query_string;
        }

        proxy_http_version 1.1;
        proxy_set_header Host $http_host;
        proxy_set_header Scheme $scheme;
        proxy_set_header SERVER_PORT $server_port;
        proxy_set_header REMOTE_ADDR $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_pass http://127.0.0.1:8000$suffix;
    }
}

Supervisor로 상주시키기

프로덕션 환경에서는 Supervisor를 사용해 Octane을 상시 실행 상태로 둡니다.
[program:octane]
process_name=%(program_name)s_%(process_num)02d
command=php /home/forge/example.com/artisan octane:start --server=frankenphp --host=127.0.0.1 --port=8000
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/example.com/storage/logs/octane.log
stopwaitsecs=3600

HTTPS 활성화

Octane 경유로 HTTPS 링크를 생성하려면 .env에 다음을 설정합니다.
OCTANE_HTTPS=true

Laravel Cloud와의 연동

Laravel Cloud에서는 FrankenPHP를 사용한 Octane을 완전 관리형으로 지원합니다. Nginx나 Supervisor 설정은 불필요하며, 단 2단계로 Octane을 활성화할 수 있습니다.
1

패키지 설치

Octane을 설치합니다. octane:install 명령은 실행해도 상관없지만 필수는 아닙니다.
composer require laravel/octane
2

Laravel Cloud에서 Octane 활성화

환경의 App 컴퓨트 클러스터 설정을 열고, “Use Octane as runtime” 를 켠 뒤 저장·배포합니다. Laravel Cloud가 자동으로 FrankenPHP + Octane으로 애플리케이션을 빌드·기동합니다.
자세한 내용은 Laravel Cloud 문서를 참고하세요.

배포 후 워커 리로드

배포 후에는 새 코드를 메모리에 읽어들이기 위해 워커를 리로드합니다.
php artisan octane:reload
마지막 수정일 2026년 7월 13일