본문으로 건너뛰기
버전: 11.x

라라벨 폴리오 (Laravel Folio)

소개

Laravel Folio는 라라벨 애플리케이션에서 라우팅을 더욱 쉽게 만들어주는 강력한 페이지 기반 라우터입니다. Laravel Folio를 사용하면, 단순히 애플리케이션의 resources/views/pages 디렉터리에 Blade 템플릿을 생성하는 것만으로도 쉽고 빠르게 라우트를 추가할 수 있습니다.

예를 들어, /greeting 경로에서 접근할 수 있는 페이지를 만들고 싶다면, resources/views/pages 디렉터리에 greeting.blade.php 파일을 만들어 주세요.

<div>
Hello World
</div>

설치

우선, Composer 패키지 관리자를 이용해 Folio를 프로젝트에 설치합니다.

composer require laravel/folio

Folio 설치 후, folio:install 아티즌 명령어를 실행하면 Folio의 서비스 프로바이더가 애플리케이션에 등록됩니다. 이 서비스 프로바이더는 Folio가 라우트/페이지를 탐색할 디렉터리를 설정합니다.

php artisan folio:install

페이지 경로 / URI

기본적으로 Folio는 애플리케이션의 resources/views/pages 디렉터리에서 페이지를 제공합니다. 하지만 이 디렉터리는 Folio의 서비스 프로바이더 boot 메서드에서 자유롭게 커스터마이즈할 수 있습니다.

예를 들어, 하나의 라라벨 애플리케이션에서 여러 Folio 경로를 지정하고 싶을 때가 있습니다. 예를 들어, 애플리케이션의 "admin" 영역을 위한 별도의 Folio 페이지 디렉터리를 만들고, 나머지 페이지용 디렉터리와 분리할 수 있습니다.

이럴 때는 Folio::pathFolio::uri 메서드를 활용합니다. path 메서드는 Folio가 HTTP 요청을 라우팅할 때 페이지를 탐색하는 디렉터리를 등록하며, uri 메서드는 해당 페이지 디렉터리가 사용할 "기본 URI"를 지정합니다.

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에서 오는 요청은 다른 Folio 페이지 디렉터리로 라우팅하고 싶을 때가 있습니다. 이 경우에는 Folio::path 메서드 뒤에 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 라우트는 Folio가 마운트한 디렉터리 중 하나에 Blade 템플릿을 추가하는 것만으로 생성할 수 있습니다. 기본적으로 Folio는 resources/views/pages 디렉터리를 마운트하지만, 앞서 말한 것처럼 서비스 프로바이더의 boot 메서드에서 자유롭게 바꿀 수 있습니다.

이렇게 Folio 디렉터리에 Blade 템플릿을 추가하면 곧바로 브라우저에서 해당 경로로 접근할 수 있습니다. 예를 들어, pages/schedule.blade.php 파일을 만들면 브라우저에서 http://example.com/schedule로 접근할 수 있습니다.

모든 Folio 페이지/라우트 목록을 빠르게 확인하려면, 다음과 같이 folio:list 아티즌 명령어를 실행하면 됩니다.

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

인덱스 라우트

특정 디렉터리의 "인덱스" 페이지 역할을 하는 페이지를 만들고 싶을 때가 있습니다. 이 경우, 해당 Folio 디렉터리에 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" 값을 받아와야 할 수 있습니다. 이를 위해, 페이지 파일명 일부를 대괄호로 감싸면 Folio가 해당 부분을 파라미터로 캡쳐하여 전달해 줍니다.

php artisan folio:page "users/[id]"

# pages/users/[id].blade.php → /users/1

캡쳐된 파라미터는 Blade 템플릿 내에서 변수로 바로 사용할 수 있습니다.

<div>
User {{ $id }}
</div>

여러 개의 경로 세그먼트를 한 번에 캡쳐하려면, 대괄호 앞에 점 세 개(...)를 추가합니다.

php artisan folio:page "users/[...ids]"

# pages/users/[...ids].blade.php → /users/1/2/3

여러 세그먼트를 캡쳐하면, 해당 변수는 배열로 페이지에 전달됩니다.

<ul>
@foreach ($ids as $id)
<li>User {{ $id }}</li>
@endforeach
</ul>

라우트 모델 바인딩

페이지 템플릿 파일명에서 일부를 와일드카드로 사용하고, 그 이름이 애플리케이션의 Eloquent 모델과 일치한다면, Folio는 라라벨의 라우트 모델 바인딩 기능을 활용해 해당 Eloquent 인스턴스를 자동으로 주입해줍니다.

php artisan folio:page "users/[User]"

# pages/users/[User].blade.php → /users/1

바인딩된 모델은 Blade 템플릿 내에서 변수로 사용할 수 있습니다. 이때 모델의 변수명은 "카멜 케이스(camel case)"로 변환됩니다.

<div>
User {{ $user->id }}
</div>

키 값 커스터마이즈

경우에 따라, id가 아닌 다른 컬럼 값으로 Eloquent 모델을 조회하고 싶을 수 있습니다. 이런 경우에는 파일명에 모델명 다음에 사용할 컬럼을 :로 구분하여 지정하면 됩니다. 예를 들어, [Post:slug].blade.php 파일은 id 대신 slug 컬럼 값을 사용하여 모델을 바인딩합니다.

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>
User {{ $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('Unauthorized', 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');

라라벨의 네임드 라우트와 마찬가지로, route 함수를 사용해 이름이 지정된 Folio 페이지로의 URL을 손쉽게 생성할 수 있습니다.

<a href="{{ route('users.index') }}">
All Users
</a>

페이지에 파라미터가 필요하다면, route 함수에 그 값을 넘기면 됩니다.

route('users.show', ['user' => $user]);

미들웨어

특정 페이지에만 미들웨어를 적용하려면, 해당 페이지의 템플릿 내부에서 middleware 함수를 호출하세요.

<?php

use function Laravel\Folio\{middleware};

middleware(['auth', 'verified']);

?>

<div>
Dashboard
</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를 사용할 때는 라라벨의 라우트 캐싱 기능을 꼭 활용해야 합니다. Folio는 route:cache 아티즌 명령어를 감지하여, Folio 페이지 정의와 라우트 이름이 최대한 빠르게 동작할 수 있도록 제대로 캐싱됩니다.