라우팅은 외부의 URL 요청을 애플리케이션의 특정 기능(컨트롤러)에 연결해주는 역할을 한다.
라우팅 코드는 routes/ 폴더 안에 작성하며, 주로 두 파일을 사용한다.
routes/web.php:
일반적인 웹 페이지를 위한 라우트이다.
로그인 세션, 쿠키 등 브라우저의 상태를 기억하는 기능들이 기본적으로 적용된다.
routes/api.php:
API를 위한 라우트이다.
상태를 기억하지 않는(stateless) 방식이 기본이며, 모든 주소 앞에 자동으로 /api/가 붙는다. (예: /tasks라고 적으면 실제 주소는 /api/tasks가 된다.)
백엔드를 만들면 주로 routes/api.php 파일을 사용하게 된다.
가장 기본적인 라우트 정의는 Route::메서드('주소', '실행할 행동'); 형태로 이루어진다.
// routes/api.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TaskController;
// Route::[HTTP 메서드]('[URI]', [액션]);
HTTP 메서드:
요청의 종류를 의미한다.
CRUD(생성, 조회, 수정, 삭제) 작업에 따라 주로 다음을 사용한다.
- GET:
데이터 조회 (예: 할 일 목록 보기)
- POST:
데이터 생성 (예: 새 할 일 등록)
- PUT / PATCH:
데이터 수정 (예: 할 일 내용 변경)
- DELETE:
데이터 삭제 (예: 할 일 지우기)
- URI (주소):
도메인 뒤에 오는 주소 경로이다. (예:/tasks,/tasks/1)
{task}처럼 중괄호를 사용하면 변수(파라미터)를 받을 수 있다.
/tasks/1,/tasks/2등의 요청을 모두 처리할 수 있다.
- 액션 (실행할 행동):
해당 주소로 요청이 왔을 때 무엇을 할지 정의한다.
- 클로저(Closure):
간단한 로직은 함수로 바로 처리할 수 있다.
Route::get('/', function () { return 'Welcome!'; });
- 컨트롤러:
대부분의 경우, 컨트롤러의 특정 메서드를 지정한다.
코드를 체계적으로 관리할 수 있어 가장 권장되는 방식이다.
Route::get('/tasks', [TaskController::class, 'index']);
// routes/api.php
use App\Http\Controllers\TaskController;
// 1. 모든 할 일 목록 조회 (GET /api/tasks)
Route::get('/tasks', [TaskController::class, 'index']);
// 2. 새로운 할 일 생성 (POST /api/tasks)
Route::post('/tasks', [TaskController::class, 'store']);
// 3. 특정 할 일 상세 조회 (GET /api/tasks/{task})
Route::get('/tasks/{task}', [TaskController::class, 'show']);
// 4. 특정 할 일 수정 (PUT /api/tasks/{task})
Route::put('/tasks/{task}', [TaskController::class, 'update']);
// 5. 특정 할 일 삭제 (DELETE /api/tasks/{task})
Route::delete('/tasks/{task}', [TaskController::class, 'destroy']);
위처럼 CRUD를 위한 라우트를 하나씩 모두 작성하는 방법도 있으나 라라벨은 이를 단 한 줄로 처리할 수 있는 기능을 제공한다.
// routes/api.php
use App\Http\Controllers\TaskController;
// 위의 5줄 코드를 이 한 줄이 모두 대체한다.
Route::apiResource('tasks', TaskController::class);
apiResource는 API의 CRUD에 필요한 모든 라우트(index, store, show, update, destroy)를 자동으로 생성해주는 기능이다.
결론적으로, 라우팅은 우리 애플리케이션의 전체 지도를 그리는 작업이며, 어떤 주소로 접속했을 때 어떤 기능이 실행될지를 정의한다.
// URI: /tasks/1
public function show($id) // 1. id(숫자 1)를 받아서
{
$task = Task::findOrFail($id); // 2. 직접 데이터를 찾고
return $task; // 3. 반환한다.
}
// URI: /tasks/1
public function show(Task $task) // 1. Task 모델을 직접 받으면
{
// 라라벨이 이미 id가 1인 Task를 찾아서 $task 변수에 넣음.
return $task; // 2. 그냥 바로 사용하면 된다.
}
만약 ID에 해당하는 데이터가 없으면, 라라벨이 404 Not Found 에러를 반환해준다.
라우트에 고유한 이름(별명)을 붙여서 관리하는 기능이다.
URL 주소가 바뀌더라도 코드 전체를 수정할 필요가 없어져 유지보수가 매우 편리해진다.
왜 필요한가?
만약 나중에 /tasks/{task}라는 주소를 /todos/{task}로 바꾸고 싶다면 프로젝트 곳곳에 하드코딩된 /tasks/... 주소를 전부 찾아 바꿔야 할 것이다.
하지만 라우트에 이름을 붙여두면 그럴 필요가 없다.
어떻게 사용하는가?
라우트 정의 뒤에 ->name() 메서드를 붙여준다.
// 'tasks.show' 라는 이름을 붙여준다.
Route::get('/tasks/{task}', [TaskController::class, 'show'])->name('tasks.show');
이제 코드 다른 곳에서 이 주소가 필요할 때, URL을 직접 쓰는 대신 route() 헬퍼 함수를 사용해 이름으로 주소를 생성할 수 있다.
// '/tasks/1' 이라는 URL을 생성해준다.
$url = route('tasks.show', ['task' => 1]);
나중에 routes/api.php 파일에서 URL을 /todos/{task}로 바꿔도, 이름은 tasks.show 그대로이므로 route() 함수를 사용한 코드는 전혀 수정할 필요가 없다.
여러 라우트에 공통된 속성(예: 공통된 URL 접두사, 공통된 미들웨어)을 적용하고 싶을 때, 그룹으로 묶어 코드를 중복 없이 깔끔하게 관리할 수 있다.
/admin/...으로 시작해야 할 때 유용하다.Route::prefix('admin')->group(function () {
Route::get('/users', ...); // 실제 주소: /admin/users
Route::get('/settings', ...); // 실제 주소: /admin/settings
});
Route::middleware('auth')->group(function () {
Route::get('/profile', ...); // 로그인해야 접근 가능
Route::get('/orders', ...); // 로그인해야 접근 가능
});
미들웨어는 요청이 컨트롤러에 도달하기 전에 거치는 중간 검문소이다.
특정 조건을 통과한 요청만 컨트롤러로 보내주는 '문지기' 역할을 한다.
가장 대표적인 사용 사례:
인증(Authentication). "로그인한 사용자인가?"를 검사해서, 로그인하지 않은 사용자는 로그인 페이지로 보내버리는 역할을 한다.
어떻게 사용하는가?
라우트 그룹이나 개별 라우트에 middleware() 메서드를 적용한다.
라라벨에는 auth라는 이름의 인증 미들웨어가 기본적으로 내장되어 있다.
// 이 라우트는 'auth' 미들웨어 검문소를 통과해야만 실행된다.
Route::get('/my-tasks', [TaskController::class, 'myTasks'])->middleware('auth:sanctum');
이제 로그인하지 않은 사용자가 /api/my-tasks에 접근하면, "인증되지 않았습니다(Unauthenticated)"라는 에러 메시지를 받게 된다.
라우팅의 핵심 철학은 "애플리케이션의 명확하고 읽기 쉬운 지도를 만드는 것"이다.
사용자가 어떤 주소로 찾아왔을 때 어디로 안내할지, 그리고 그 과정에서 어떤 검문을 거치게 할지를 정의하는 작업이다.