Laravel Folio
번역일: 2026년 6월 20일
Laravel Folio
소개
Laravel Folio는 파일 기반 라우팅을 통해 Laravel 애플리케이션의 라우트 설정을 단순화하는 패키지입니다. Folio를 사용하면 resources/views/pages 디렉토리에 Blade 템플릿 파일을 생성하는 것만으로 라우트가 자동으로 만들어집니다.
예를 들어, /greeting URL로 접근 가능한 페이지를 만들고 싶다면 resources/views/pages/greeting.blade.php 파일을 생성하면 됩니다:
<div>
안녕하세요!
</div>NOTE
별도의 routes/web.php 등록 없이 파일만 만들면 라우트가 동작합니다. 파일 이름이 곧 URL 경로가 됩니다.
설치
Composer를 통해 Folio를 프로젝트에 설치합니다:
composer require laravel/folio설치 후, folio:install Artisan 명령을 실행하면 Folio의 서비스 프로바이더가 애플리케이션에 등록됩니다. 이 서비스 프로바이더는 Folio가 페이지(라우트)를 탐색할 디렉토리를 설정합니다:
php artisan folio:install페이지 경로 / URI
기본적으로 Folio는 resources/views/pages 디렉토리의 파일을 페이지로 인식합니다. 하지만 Folio 서비스 프로바이더의 boot 메서드에서 이 경로를 자유롭게 변경하거나 여러 경로를 추가할 수 있습니다.
예를 들어, 관리자 페이지와 일반 페이지를 별도 디렉토리로 분리하고 싶을 때는 Folio::path와 Folio::uri 메서드를 활용합니다. path는 Folio가 탐색할 디렉토리를, uri는 해당 디렉토리의 기본 URL 경로를 지정합니다:
use Laravel\Folio\Folio;
Folio::path(resource_path('views/pages/guest'))->uri('/');
Folio::path(resource_path('views/pages/admin'))
->uri('/admin')
->middleware([
'*' => [
'auth',
'verified',
// ...
],
]);서브도메인 라우팅
요청의 서브도메인에 따라 다른 페이지 디렉토리로 라우팅할 수도 있습니다. 예를 들어 admin.example.com으로 들어오는 요청을 별도의 디렉토리에서 처리하려면 domain 메서드를 사용합니다:
use Laravel\Folio\Folio;
Folio::domain('admin.example.com')
->path(resource_path('views/pages/admin'));domain 메서드는 도메인이나 서브도메인의 일부를 파라미터로 캡처하는 것도 지원합니다. 캡처된 값은 페이지 템플릿 안에서 변수로 사용할 수 있습니다:
use Laravel\Folio\Folio;
Folio::domain('{account}.example.com')
->path(resource_path('views/pages/admin'));라우트 생성
Folio가 마운트된 디렉토리에 Blade 템플릿을 배치하면 즉시 라우트로 동작합니다. 기본 마운트 디렉토리는 resources/views/pages이며, 서비스 프로바이더의 boot 메서드에서 변경할 수 있습니다.
예를 들어 pages/schedule.blade.php 파일을 생성하면 브라우저에서 http://example.com/schedule로 바로 접근할 수 있습니다.
현재 등록된 모든 Folio 페이지와 라우트 목록은 다음 명령으로 확인할 수 있습니다:
php artisan folio:list중첩 라우트
Folio 디렉토리 안에 하위 디렉토리를 만들면 중첩 라우트를 구성할 수 있습니다. 예를 들어 /user/profile로 접근 가능한 페이지를 만들려면 pages/user/profile.blade.php 파일을 생성합니다:
php artisan folio:page user/profile# pages/user/profile.blade.php → /user/profile인덱스 라우트
특정 디렉토리의 루트 URL을 처리하는 기본 페이지를 만들고 싶을 때는 해당 디렉토리에 index.blade.php 파일을 배치합니다:
php artisan folio:page index# pages/index.blade.php → /php artisan folio:page users/index# pages/users/index.blade.php → /users라우트 파라미터
URL의 특정 세그먼트를 파라미터로 캡처하려면 파일 이름에서 해당 부분을 대괄호([])로 감쌉니다. 예를 들어 사용자 ID를 URL에서 받아오려면 다음처럼 파일을 만듭니다:
php artisan folio:page "users/[id]"# pages/users/[id].blade.php → /users/1캡처된 값은 Blade 템플릿 안에서 변수로 바로 사용할 수 있습니다:
<div>
사용자 ID: {{ $id }}
</div>여러 세그먼트를 한꺼번에 캡처하려면 ...(전개 연산자)를 앞에 붙입니다:
php artisan folio:page "users/[...ids]"# pages/users/[...ids].blade.php → /users/1/2/3이 경우 캡처된 값들은 배열 형태로 주입됩니다:
<ul>
@foreach ($ids as $id)
<li>사용자 ID: {{ $id }}</li>
@endforeach
</ul>라우트 모델 바인딩
파일 이름의 와일드카드 세그먼트가 Eloquent 모델 클래스명과 일치하면, Folio는 Laravel의 라우트 모델 바인딩을 자동으로 활용하여 해당 모델 인스턴스를 페이지에 주입합니다:
php artisan folio:page "users/[User]"# pages/users/[User].blade.php → /users/1캡처된 모델은 카멜 케이스로 변환된 변수명으로 Blade 템플릿에서 사용할 수 있습니다:
<div>
사용자 ID: {{ $user->id }}
</div>바인딩 키 커스터마이즈
기본적으로 모델은 id 컬럼을 기준으로 조회됩니다. id 대신 다른 컬럼을 사용하려면 파일 이름에 컬럼명을 명시합니다. 예를 들어 [Post:slug].blade.php라고 지정하면 slug 컬럼으로 모델을 조회합니다.
NOTE
Windows 환경에서는 모델명과 키를 구분할 때 -를 사용합니다: [Post-slug].blade.php
모델 위치 지정
Folio는 기본적으로 app/Models 디렉토리에서 모델을 탐색합니다. 다른 위치의 모델을 사용하려면 파일 이름에 완전한 클래스명을 점(.)으로 구분하여 지정합니다:
php artisan folio:page "users/[.App.Models.User]"# pages/users/[.App.Models.User].blade.php → /users/1소프트 삭제된 모델
라우트 모델 바인딩은 기본적으로 소프트 삭제된 모델을 조회하지 않습니다. 소프트 삭제된 모델도 함께 조회하려면 페이지 템플릿에서 withTrashed 함수를 호출합니다:
<?php
use function Laravel\Folio\{withTrashed};
withTrashed();
?>
<div>
사용자 ID: {{ $user->id }}
</div>렌더 훅
Folio는 기본적으로 Blade 템플릿의 내용을 그대로 응답으로 반환합니다. 하지만 render 함수를 사용하면 응답을 자유롭게 커스터마이즈할 수 있습니다.
render 함수는 클로저를 인자로 받으며, 클로저에는 Folio가 렌더링할 View 인스턴스가 전달됩니다. 이를 통해 뷰에 추가 데이터를 넘기거나 응답 자체를 직접 구성할 수 있습니다. 라우트 파라미터나 모델 바인딩 값도 클로저 인자로 함께 주입됩니다:
<?php
use App\Models\Post;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;
use function Laravel\Folio\render;
render(function (View $view, Post $post) {
if (! Auth::user()->can('view', $post)) {
return response('권한이 없습니다.', 403);
}
return $view->with('photos', $post->author->photos);
}); ?>
<div>
{{ $post->content }}
</div>
<div>
이 작성자의 사진 {{ count($photos) }}장도 확인해보세요.
</div>이름 있는 라우트
페이지 템플릿에서 name 함수를 사용하면 해당 라우트에 이름을 부여할 수 있습니다:
<?php
use function Laravel\Folio\name;
name('users.index');Laravel의 이름 있는 라우트와 동일하게, route 헬퍼 함수를 통해 URL을 생성할 수 있습니다:
<a href="{{ route('users.index') }}">
전체 사용자 목록
</a>페이지에 파라미터가 있는 경우에는 route 함수에 값을 배열로 전달합니다:
route('users.show', ['user' => $user]);미들웨어
특정 페이지에만 미들웨어를 적용하려면 해당 페이지 템플릿에서 middleware 함수를 호출합니다:
<?php
use function Laravel\Folio\{middleware};
middleware(['auth', 'verified']);
?>
<div>
대시보드
</div>여러 페이지에 일괄 적용하려면 Folio::path 이후에 middleware 메서드를 체이닝합니다. 미들웨어 배열의 키로 URL 패턴을 지정하며, * 와일드카드를 사용할 수 있습니다:
use Laravel\Folio\Folio;
Folio::path(resource_path('views/pages'))->middleware([
'admin/*' => [
'auth',
'verified',
// ...
],
]);클로저를 사용해 인라인 익명 미들웨어를 정의하는 것도 가능합니다:
use Closure;
use Illuminate\Http\Request;
use Laravel\Folio\Folio;
Folio::path(resource_path('views/pages'))->middleware([
'admin/*' => [
'auth',
'verified',
function (Request $request, Closure $next) {
// ...
return $next($request);
},
],
]);라우트 캐싱
Folio를 사용할 때도 Laravel의 라우트 캐싱을 적극 활용하는 것을 권장합니다. Folio는 route:cache Artisan 명령을 감지하여 페이지 정의와 라우트 이름을 캐시에 저장하므로, 프로덕션 환경에서 최적의 성능을 얻을 수 있습니다.