라우팅

기본적인 라우팅

가장 기본적인 라라벨 라우트는 URI 와 클로저를 전달 받아, 라우팅을 정의하는 간단하고 쉽게 이해할 수 있는 방법을 제공합니다:

Route::get('foo', function () {
    return 'Hello World';
});

기본 라우트 파일

모든 라라벨의 라우트는 route 디렉토리 안에 들어 있는 라우트 파일에 정의되어 있습니다. 이 파일들은 프레임워크에 의해서 자동으로 로드됩니다. routes/web.php 파일은 웹 인터페이스를 위한 라우트들을 정의합니다. 이 라우트들에는 세션 상태와 CSRF 보호와 같은 기능을 제공하는 web 미들웨어 그룹이 할당되어 있습니다. routes/api.php 안에 들어 있는 라우트들은 stateless 하고 api 미들웨어 그룹이 할당되어 있습니다.

대부분의 애플리케이션에서, 여러분은 routes/web.php 파일에 라우트를 정의하여 시작할 수 있습니다. routes/web.php 에 정의된 라우트는 브라우저를 통해서 유입되는 라우트 URL을 정의하는데 사용됩니다. 예를 들어 브라우저에서 http://your-app.dev/user와 같이 접속하기 위해서 다음의 라우트를 정의할 수 있습니다:

Route::get('/user', 'UserController@index');

routes/api.php 파일은 RouteServiceProvider의 라우트 그룹안에 중첩되어 정의되어 있습니다. 이 그룹을에 의해서 /api URI가 자동으로 앞에 붙게 되므로, 이 파일에 정의한 모든 라우트에 일일이 적용하지 않아도 됩니다. RouteServiceProvider 파일의 라우트 그룹 옵션을 수정하면, 다른 prefix를 붙일 수도 있습니다.

가능한 라우터 메소드

라우터는 다음의 HTTP 메소드에 해당하는 응답을 위한 라우트를 등록할 수 있습니다:

Route::get($uri, $callback);
Route::post($uri, $callback);
Route::put($uri, $callback);
Route::patch($uri, $callback);
Route::delete($uri, $callback);
Route::options($uri, $callback);

때로는 여러개의 HTTP 메소드에 응답하는 라우트를 등록해야 할 수도 있습니다. 이경우 match 메소드를 사용하면 됩니다. 또는 any 메소드를 사용하여 모든 HTTP 메소드에 응답하는 라우트를 등록할 수도 있습니다:

Route::match(['get', 'post'], '/', function () {
    //
});

Route::any('foo', function () {
    //
});

CSRF 보호하기

web 라우트 파일 안에 정의된 POST, PUT 또는 DELETE 를 가리키는 라우트들은 모두 CSRF 토큰 필드를 포함해야합니다. 그렇지 않으면, 이 request들은 거부될 것입니다. CSRF 보호에 대해서 더 알아보려면 CSRF 문서를 읽어보십시오:

<form method="POST" action="/profile">
    {{ csrf_field() }}
    ...
</form>

리다이렉트 라우트

다른 URI로 리다이렉트 시키는 라우트를 정의하려면, Route::redirect 메소드를 사용할 수 있습니다. 이 메소드는 간단한 리다이렉트를 위해서 복잡한 라우트나 컨트롤러 전체를 정의하지 않아도 되는 편리한 방법을 제공합니다.

Route::redirect('/here', '/there', 301);

뷰-View 라우트

단지 뷰를 반환하기만 하는 라우트가 필요하다면, Route::view 메소드를 사용할 수 있습니다. redirect 메소드와 같이 이 메소드는 간단한 리다이렉트를 위해서 복잡한 라우트나 컨트롤러 전체를 정의하지 않아도 되는 편리한 방법을 제공합니다. view 메소드는 첫번째 인자로 URI를, 두번째 인자로 뷰 파일의 이름을 전달 받습니다. 또한 이에 더해, 세번째 인자로 view 에 제공할 데이터들의 배열을 제공할 수도 있습니다:

Route::view('/welcome', 'welcome');

Route::view('/welcome', 'welcome', ['name' => 'Taylor']);

라우트 파라미터

필수 파라미터

라우트중에 URI 세그먼트를 필요로 할 수도 있습니다. 다음과 같이 URL 에서 사용자의 ID를 확인하고자 하는 경우 입니다. 이 경우 라우트 파라미터를 정의할 수 있습니다:

Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});

라우트에서는 여러개의 라우트 파라미터를 정의할 수도 있습니다:

Route::get('posts/{post}/comments/{comment}', function ($postId, $commentId) {
    //
});

라우트 파라미터는 항상 "{}"(중괄호)로 싸여져 있고, - 문자를 포함하지 않은 알파벳 문자로 구성되어 있어야합니다. - 문자를 사용하기 보다는 언더스코어 (_) 를 사용하십시오. 라우트 파라미터는 라우트 콜백 / 컨트롤러에 주입되는데 이때 사용되는 콜백 / 컨트롤러 인자에서 문제가 되지 않는 이름이어야 합니다.

선택적 파라미터

때로는, 라우트 파라미터를 지정하긴 하지만, 파라미터가 선택적으로 존재하기를 원할수도 있습니다. 이 경우 파라미터 이름뒤에 ? 를 표시하면 됩니다. 라우트 파라미터와 일치하는 변수가 기본값을 가지는지 확인하십시오:

Route::get('user/{name?}', function ($name = null) {
    return $name;
});

Route::get('user/{name?}', function ($name = 'John') {
    return $name;
});

정규표현식 제약

라우트 인스턴스에 where 메소드를 사용하여 라우트 파라미터들의 포맷을 제한할 수 있습니다. where 메소드는 파라미터의 이름과 파라미터가 어떻게 규정되어야 하는지 나타내는 정규표현식을 인자로 전달 받습니다:

Route::get('user/{name}', function ($name) {
    //
})->where('name', '[A-Za-z]+');

Route::get('user/{id}', function ($id) {
    //
})->where('id', '[0-9]+');

Route::get('user/{id}/{name}', function ($id, $name) {
    //
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);

글로벌 제약

라우트 파라미터가 항상 주어진 정규표현식으로 제약을 가지게 된다면, pattern 메소드를 사용할 수 있습니다. 이 패턴들은 RouteServiceProviderboot 메소드 안에서 사용해야 합니다:

/**
 * Define your route model bindings, pattern filters, etc.
 *
 * @return void
 */
public function boot()
{
    Route::pattern('id', '[0-9]+');

    parent::boot();
}

패턴을 한번 정의하고나면, 해당 파라미터 이름을 사용하는 모든 라우트들에 자동으로 적용됩니다:

Route::get('user/{id}', function ($id) {
    // Only executed if {id} is numeric...
});

이름이 지정된 라우트

이름이 지정된 라우트는 URL 이나 지정된 라우트로의 리다이렉션을 손쉽게 생성하기 편리하게 해줍니다. 라우트 정의에 name 메소드를 체이닝 하여 라우트에 이름을 지정할 수 있습니다:

Route::get('user/profile', function () {
    //
})->name('profile');

컨트롤러의 액션에도 라우트 이름을 지정할 수 있습니다:

Route::get('user/profile', 'UserController@showProfile')->name('profile');

이름이 지정된 라우트들에 대한 URL 생성하기

주어진 라우트에 대한 이름이 할당되면, 전역 route 함수를 통해서 URL 또는 리다이렉션을 생성할 때 라우트 이름을 사용할 수 있습니다:

// Generating URLs...
$url = route('profile');

// Generating Redirects...
return redirect()->route('profile');

이름이 지정된 라우트에 파라미터를 정의하였다면, route 메소드의 두번째 인자로 파라미터를 전달할 수 있습니다. 주어진 파라미터는 자동으로 올바른 위치에 있는 URL 에 삽입될 것입니다:

Route::get('user/{id}/profile', function ($id) {
    //
})->name('profile');

$url = route('profile', ['id' => 1]);

현재의 라우트 검사하기

현재의 request 가 주어진 이름의 라우트가 맞는지 확인하고자 한다면, Route 인스턴스의 named 메소드를 사용하면 됩니다. 예를 들어 라우트 미들웨어에서 현재 라우트의 이름을 확인할 수 있습니다:

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    if ($request->route()->named('profile')) {
        //
    }

    return $next($request);
}

라우트 그룹

라우트 그룹을 사용하면 미들웨어나, 네임스페이스와 같은 라우트 속성을 공유할 수 있어, 많은 수의 라우트를 등록할 때 각각의 개별 라우트에 매번 속성들을 정의하지 않아도 되게 해줍니다. 공유하려는 속성은 배열 형식으로 지정되어 Route::group 메소드의 첫번째 인자로 전달됩니다.

미들웨어

그룹 안의 모든 라우트에 미들웨어를 할당하기 위해서는, 그룹을 정의하기 전에 middleware 메소드를 사용하면 됩니다. 미들웨어는 배열에 나열된 순서대로 실행될 것입니다:

Route::middleware(['first', 'second'])->group(function () {
    Route::get('/', function () {
        // Uses first & second Middleware
    });

    Route::get('user/profile', function () {
        // Uses first & second Middleware
    });
});

네임스페이스

라우트 그룹을 사용하는 또 다른 사용 예로는 namespace 메소드를 사용하는 컨트롤러들에 동일한 PHP 네임스페이스를 할당하는 경우 입니다:

Route::namespace('Admin')->group(function () {
    // Controllers Within The "App\Http\Controllers\Admin" Namespace
});

주의할점은, 기본적으로 RouteServiceProviderApp\Http\Controllers 네임스페이스를 접두사로 굳이 지정하지 않아도 컨트롤러가 등록되도록, 네임스페이스 그룹 안에서 라우트 파일을 로드한다는 것입니다. 따라서 여러분들이 네임스페이스에서 필요한 부분은 App\Http\Controllers 네임스페이스 뒷부분만 지정하면 됩니다.

서브 도메인 라우팅

라우트 그룹은 또한 카드형태의 서브 도메인을 처리하는데 사용할 수도 있습니다. 서브 도메인은 라우트 URI와 같이 서브 도메인의 일부를 추출하여, 라우트 파라미터로 할당할 수 있습니다. 서브 도메인은 그룹을 정의하기 전에 domain 메소드를 호출하여 지정할 수 있습니다:

Route::domain('{account}.myapp.com')->group(function () {
    Route::get('user/{id}', function ($account, $id) {
        //
    });
});

라우트 Prefix

prefix 메소드는 그룹안의 라우트에 특정 URI을 접두어로 지정할 때 사용합니다. 그룹의 모든 라우트 URI 앞에 admin 을 붙이고 싶다면 다음과 같이 지정하면 됩니다:

Route::prefix('admin')->group(function () {
    Route::get('users', function () {
        // Matches The "/admin/users" URL
    });
});

라우트 이름 접두사

name 메소드는 그룹 안에서 각각의 라우트에 이름을 prefix로 붙이는데 사용할 수 있습니다. 예를 들어, 그룹으로 지정된 모든 라우트들의 이름앞에 admin 이라는 문자를 붙이려고 한다고 생각해 보겠습니다. 지정된 문자열은 라우트의 이름의 바로 앞에 붙기 때문에, . 문자를 덧붙이도록 해야합니다:

Route::name('admin.')->group(function () {
    Route::get('users', function () {
        // Route assigned name "admin.users"...
    });
});

라우트 모델 바인딩

모델 ID 를 라우트나 컨트롤러 액션에 주입한 경우, 여러분은 곧잘 ID와 일치하는 모델을 조회하기 위해서 쿼리를 수행할 것입니다. 라라벨 라우트 모델 바인딩은 여러분의 라우트에 자동으로 모델 인스턴스를 직접 주입하는 편리한 방법을 제공합니다. 예를 들어 사용자의 ID를 주입하는 대신 주어진 ID와 매칭되는 전체 User 모델 인스턴스를 주입할 수 있습니다.

묵시적 바인딩

라라벨은 자동으로 라우트나 컨트롤러 액션에서 정의되어 있는 라우트 세그먼트 이름과 일치하는 타입힌트된 변수에 해당하는 Eloquent 모델을 의존성 해결합니다. 예를 들어:

Route::get('api/users/{user}', function (App\User $user) {
    return $user->email;
});

App\User Eloquent 모델로 타입힌트된 $user 변수와 {user} 세그먼트가 일치하기 때문에, 라라벨은 자동으로 request URI 로 부터 일치하는 ID 값을 가진 모델 인스턴스를 주입할것입니다. 만약 데이터베이스에서 매칭되는 모델 인스턴스를 찾을 수 없으면, 자동으로 404 HTTP response 가 생성됩니다.

키의 이름을 변경하기

주어진 모델의 클래스를 찾을 때 id 와는 다른 데이터베이스 컬럼을 사용하는 모델 바인딩을 하고자 한다면, Eloquent 모델의 getRouteKeyName 메소드를 재지정하면 됩니다:

/**
 * Get the route key for the model.
 *
 * @return string
 */
public function getRouteKeyName()
{
    return 'slug';
}

명시적 바인딩

명시적 바인딩을 등록하기 위해서, 주어진 파라미터에 대한 클래스를 지정하려면 라우터의 model 메소드를 사용하십시오. 여러분은 RouteServiceProvider 클래스의 boot 메소드 안에서 명시적 모델 바인딩을 정의해야 합니다:

public function boot()
{
    parent::boot();

    Route::model('user', App\User::class);
}

다음으로, {user} 파라미터를 포함한 라우트를 정의합니다:

Route::get('profile/{user}', function ($user) {
    //
});

{user} 파라미터와 App\User 모델이 바인딩되어 있기 때문에 라우트에는 User 인스턴스가 주입 될것입니다. 예를 들어 profile/1으로 요청이 들어오면 데이터베이스로 부터 ID가 1User의 인스턴스가 주입됩니다.

만약 데이터베이스에서 일치하는 모델 인스턴스를 찾지 못하는 경우, 404 응답이 자동으로 생성될 것입니다.

의존성 해결 로직 커스터마이징하기

만약 여러분의 고유한 의존성 해결 로직을 사용하려면 Route::bind 메소드를 사용할 수 있습니다. bind 메소드에 전달되는 클로저에는 URI 세그먼트에 해당하는 값이 전달되고 라우트에 주입되어야 하는 클래스의 인스턴스를 반환해야 합니다:

public function boot()
{
    parent::boot();

    Route::bind('user', function ($value) {
        return App\User::where('name', $value)->first() ?? abort(404);
    });
}

Form-폼 메소드 Spoofing-속이기

HTML form은 PUT, PATCHDELETE 액션을 지원하지 않습니다. 따라서 PUT, PATCHDELETE 로 지정된 라우트를 호출하는 HTML form을 정의한다면 _method 의 숨겨진 필드를 지정해야합니다. _method 필드로 보내진 값은 HTTP request 메소드를 판별하는데 사용됩니다:

<form action="/foo/bar" method="POST">
    <input type="hidden" name="_method" value="PUT">
    <input type="hidden" name="_token" value="{{ csrf_token() }}">
</form>

_method 입력을 생성하기 위해서 method_filed 헬퍼 함수를 사용할 수 있습니다:

{{ method_field('PUT') }}

현재 라우트에 엑세스하기

Route 파사드의 current, currentRouteName 그리고 currentRouteAction 메소드를 사용하여, 유입된 request-요청을 처리하는 라우트에 대한 정보에 엑세스 할 수 있습니다:

$route = Route::current();

$name = Route::currentRouteName();

$action = Route::currentRouteAction();

모든 메소드를 확인하고자 한다면 Route 파사드 뒤에서 동작하는 클래스Route 인스턴스 API 문서를 참고하십시오.