라라벨 코리아 페이스북 그룹에 질문이 하나 올라왔습니다.
https://www.facebook.com/groups/laravelkorea/permalink/1862353923927678
처음부터 제대로 배우는 라라벨의 예제 코드 처럼 라우트 그룹을 작성하면 에러가 나는데, 책에 나온 코드 처럼 사용하는 방법은 없느냐 하는 것 입니다.
질문해주신 분이 언급한 예제는 79 페이지의 예제 3-10 이며 내용은 아래와 같습니다.
Route::group(function () {
Route::get('hello', function () {
return 'Hello';
});
Route::get('world', function () {
return 'World';
});
});
위의 코드를 실행하면 질문자분께서 말씀하신 것 처럼 에러가 납니다.
“Illuminate\Routing\Router::group(): Argument #1 ($attributes) must be of type array, Closure given, called in …”
group() 메서드의 첫번째 인자로 배열이 들어와야하는데 클로저가 들어왔다는 내용입니다.
결론부터 말씀드리면 책의 예제 코드가 잘못된 게 맞습니다. ㅠ
Illuminate\Routing\Router::group() 메서드의 시그너처가 아래와 같기 때문에 첫번째 인자로 반드시 배열을 넘겨줘야 합니다.
public function group(array $attributes, $routes)
따라서 예제 코드는 아래와 같이 바뀌어야 정상 동작합니다.
Route::group([], function () {
Route::get('hello', function () {
return 'Hello';
});
Route::get('world', function () {
return 'World';
});
});
클로저만 넘기는 경우도 있던데요?
Route::middleware(['throttle:uploads'])->group(function () {
Route::post('/photos', function() {
//
});
});
위 코드는 81 페이지의 예제 3-12 입니다.
group() 메서드에 클로저 하나만 넘겨주고 있습니다. 어떻게 된거죠?
group(), 동명이인
이유는 Route::group() 과 Route::middleware()->group() 에 쓰인 group()이 서로 다른 클래스의 메서드이기 때문입니다.
Route::middleware()는 Illuminate\Routing\Router가 아닌 Illuminate\Routing\RouteRegistrar를 반환합니다. 따라서 middleware() 메서드에 체이닝된 group() 메서드는 Illuminate\Routing\Router의 group() 메서드가 아닌 Illuminate\Routing\RouteRegistrar의 group() 메서드인 것이죠.
public function group($callback)
Illuminate\Routing\RouteRegistrar의 group() 메서드 시그너처가 위와 같기 때문에 클로저만 넘겨주면 됩니다.
권장사항
위의 내용을 종합해보면 라우트 그룹을 사용하는 방법이 두 가지인 셈입니다.
- Route 퍼사드에서 group() 메서드를 바로 호출하는 방법
- Route 퍼사드에서 middleware(), domain(), prefix(), name() 등의 메서드에 체이닝하여 group() 메서드를 호출하는 방법
저는 2번 방식을 권장합니다. 첫째, 1번은 메뉴얼에 안내되지 않는 사용법입니다. 둘째, 그룹을 묶는다는 것은 언제나 목적이 있을 것입니다. 따라서 위에 수정된 예제 3-10의 코드 처럼 빈 배열을 이용해서 그룹을 만드는 건 의미가 없습니다. 그룹을 묶는 목적에 따른 메서드를 모두 제공하고 있으니, 각 메서드를 활용해서 그룹을 만드는게 보기에도, 관리하기에도 더 나을 겁니다.