Skip to content

2.5장: API 라우트

학습 시간: 45분


1. 라우트(Route)란 무엇인가요? 쉽게 설명하기

컨트롤러(PlanetController)를 큰 오피스 센터라고 상상해 보세요. 각 메소드(index, store, show)는 자신의 업무를 수행하는 부서입니다.

라우트(Route)는 건물 입구에 붙어 있는 주소판과 같습니다. 이것은 다음과 같이 말합니다:

  • "누군가 /planets 주소로 GET 메소드를 통해 왔다면 — index 부서(모두 보여주기)로 보내세요."
  • "누군가 /planets 주소로 POST 메소드를 통해 (데이터와 함께) 왔다면 — store 부서(새로운 것 생성)로 보내세요."

라우트 없이는 외부의 어떤 요청도 코드 내에서 필요한 부서를 찾지 못할 것입니다. API에서 이러한 "주소판"의 주요 파일은 routes/api.php입니다.

Laravel 11+에서는 기본적으로 "API 주소록"이 없습니다. 우리는 php artisan install:api 명령을 실행하여 직접 만들었습니다. 이제 routes/api.php 파일이 생겼고, 이것은 우리 API의 모든 라우트를 관리하는 주요 제어 센터입니다.

api.php와 web.php의 주요 차이점:

  • /api 접두사: Laravel은 이 파일의 모든 URL 주소에 자동으로 /api를 추가합니다. /planets 라우트는 /api/planets로 바뀝니다.
  • "무상태(Stateless)": 일반적인 웹처럼 세션과 쿠키 파일이 없습니다. 각 요청은 독립적이며 인증에 필요한 모든 정보(일반적으로 헤더의 API 토큰)를 포함해야 합니다.

2. 초보자의 길: 라우트 수동 생성

원리를 이해하기 위해 직접 단 하나의 라우트를 만들어 봅시다. 우리의 목표는 /api/planets URL이 모든 행성 목록을 표시하도록 하는 것입니다.

routes/api.php를 열고 다음을 작성하세요:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PlanetController; // 컨트롤러의 위치를 지정합니다.

//                    (1)           (2)                     (3)
Route::get(      '/planets',    [PlanetController::class, 'index']     );
//   ^               ^                       ^
// (HTTP 메소드)   (URL 주소)          (호출할 컨트롤러 및 메소드)

이 줄을 부분별로 분석해 봅시다:

  1. Route::get(...) — 우리는 "이 라우트는 GET 요청에만 작동합니다"라고 말합니다.
  2. '/planets' — 이것은 Laravel이 수신할 URL입니다. /api 접두사를 고려하면 전체 주소는 http://space-api.test/api/planets가 됩니다.
  3. [PlanetController::class, 'index'] — 이것은 "목적지"입니다. 우리는 "요청이 오면 PlanetController 클래스를 찾아 그 안에 있는 index() 메소드를 호출하세요"라고 말합니다.

이제 모든 것이 연결됩니다! 요청 -> 라우트 -> 컨트롤러 -> 메소드.

그럼 만약 ID로 하나의 행성을 가져와야 한다면 어떨까요? 예를 들어, /api/planets/5와 같이요.

// 특정 행성을 가져오는 라우트
Route::get('/planets/{planet}', [PlanetController::class, 'show']);

여기서 {planet}은 "템플릿" 또는 변수입니다. Laravel은 이 위치에 무엇이든 올 수 있다는 것을 이해합니다 (ID, 슬러그). 그런 다음 이 값을 show(Planet $planet) 메소드로 전달합니다. Laravel이 ID를 통해 행성을 스스로 찾는 이러한 "마법"을 라우트 모델 바인딩(Route Model Binding)이라고 합니다.


3. 마스터의 길: apiResource — 모든 것을 지배하는 한 줄

각 라우트를 수동으로 생성하는 것(index, show, store, update, destroy에 대해)은 지루한 일입니다. Laravel 개발자들은 이 점을 이해하고 강력한 도우미인 apiResource를 만들었습니다.

우리가 작성했던 모든 것을 지우고 한 줄로 대체하세요:

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\PlanetController;

Route::apiResource('planets', PlanetController::class);

이 한 줄은 내부적으로 무엇을 할까요? 이 한 줄은 우리가 컨트롤러에서 이미 구현한 표준 CRUD 작업을 위한 전체 라우트 세트를 자동으로 생성합니다.

메소드 URL 연결되는 메소드 목적
GET /api/planets index() 모든 행성 목록 가져오기
POST /api/planets store() 새 행성 생성
GET /api/planets/{planet} show() 특정 행성 하나 보여주기
PUT/PATCH /api/planets/{planet} update() 기존 행성 업데이트
DELETE /api/planets/{planet} destroy() 행성 삭제

직접 확인해 볼 수 있습니다. 터미널에서 다음 명령어를 실행하세요:

php artisan route:list --path=api

생성된 모든 라우트가 포함된 테이블을 보게 될 것입니다. apiResource는 표준 API를 생성할 때 시간을 절약해 주는 가장 좋은 친구입니다.


4. 특별 미션 및 라우트 순서

만약 apiResource에 없는 비표준 라우트가 필요하다면 어떨까요? 예를 들어, /api/planets/random 주소로 무작위 행성을 가져오는 경우요.

추가해 봅시다. 하지만 여기에는 초보자 10명 중 9명이 빠지는 치명적인 함정이 있습니다.

잘못된 순서 (작동 안함!):

Route::apiResource('planets', PlanetController::class);
Route::get('/planets/random', [PlanetController::class, 'random']); // <-- 작동하지 않습니다.
왜요? Laravel은 라우트를 위에서 아래로 읽습니다. GET /planets/{planet} 라우트를 생성한 Route::apiResource를 먼저 보게 됩니다. /planets/random을 요청하면 Laravel은 "random"을 행성 ID라고 생각하여 데이터베이스에서 ID가 "random"인 행성을 찾으려고 시도할 것이고, 그러면 오류가 발생할 것입니다.

올바른 순서 (작동함!):

<?php
use App\Http\Controllers\PlanetController;
use Illuminate\Support\Facades\Route;

// 1. 먼저 구체적인 라우트를 선언합니다.
Route::get('/planets/random', [PlanetController::class, 'random']);

// 2. 그 다음에만 변수가 있는 일반 라우트를 선언합니다.
Route::apiResource('planets', PlanetController::class);

⚠️ 중요!

api/planets/random 라우트를 테스트하려면 PlanetController에 새 핸들러를 추가해야 합니다:

<?php
public function random(Request $request)
{
   $planet = Planet::inRandomOrder()->first();
   return response()->json($planet);
}

규칙: 항상 더 구체적인 라우트(/random과 같은)를 더 일반적이고 템플릿화된 라우트(/{planet}과 같은) 앞에 선언하세요.


5. 그룹화: 정리하기

라우트가 많아지면 그룹화할 수 있으며, 그렇게 해야 합니다.

A. API 버전 관리 미래에 기존 API를 사용하는 오래된 애플리케이션이 손상되지 않도록, URL에 /api/v1/...과 같이 버전을 추가하는 것이 일반적입니다.

<?php
Route::prefix('v1')->group(function () {
    // 이 그룹 내부의 모든 라우트는 /v1 접두사를 갖게 됩니다.
    // 최종 URL: /api/v1/planets
    Route::get('/planets/random', [PlanetController::class, 'random']);
    Route::apiResource('planets', PlanetController::class);
});

B. 라우트 보호 (미들웨어) 행성을 보는 것은 누구나 할 수 있지만, 생성, 업데이트, 삭제는 인증된 사용자만 가능하다고 가정해 봅시다.

<?php
// 모두에게 공개된 라우트
Route::get('/planets', [PlanetController::class, 'index']);
Route::get('/planets/{planet}', [PlanetController::class, 'show']);

// "패스"(인증)를 요구하는 라우트 그룹
Route::middleware('auth:sanctum')->group(function () {
    Route::post('/planets', [PlanetController::class, 'store']);
    Route::put('/planets/{planet}', [PlanetController::class, 'update']);
    Route::delete('/planets/{planet}', [PlanetController::class, 'destroy']);
});

여기서 middleware('auth:sanctum')는 그룹 내 라우트에 접근하려는 모든 사람의 "패스"를 확인하는 경비원과 같습니다.


6. Postman을 통한 테스트

이제 모든 라우트가 설정되었으니, 테스트해 볼 시간입니다.

  1. Herd를 사용한다면: 귀하의 웹사이트는 이미 http://space-api.test와 같은 주소로 작동 중입니다.
  2. 그렇지 않다면: php artisan serve 명령으로 로컬 서버를 실행하세요. 주소는 http://localhost:8000이 될 것입니다.

Postman을 열고 요청을 보내세요:

  • GET http://space-api.test/api/planets
  • GET http://space-api.test/api/planets/random
  • POST http://space-api.test/api/planets (Body 탭 -> raw -> JSON에서 JSON 요청 본문을 추가하는 것을 잊지 마세요).

POST 요청 예시:

{
    "name": "Kepler-186f",
    "description": "Первая планета земного размера в обитаемой зоне",
    "size_km": 15000,
    "solar_system": "Kepler-186",
    "is_habitable": true
}


8. 자주 발생하는 라우팅 오류

  1. 404 Not Found
  2. 잘못된 URL (/api/planets 대신 /api/planet)
  3. php artisan serve를 잊음
  4. 405 Method Not Allowed
  5. 잘못된 HTTP 메소드 (예: POST 대신 GET)
  6. Missing Controller
  7. 컨트롤러 이름 오타 (PlanetControler)
  8. Route Name Collision
  9. 라우트 이름 중복

복습 퀴즈

1. Laravel에서 API 경로를 위한 파일:

2. API 라우트의 자동 접두사:

3. 5개의 CRUD 경로를 생성하는 메서드:

4. Route::prefix('v1')는 다음 용도로 사용됩니다:

5. 모든 경로 보기:


🚀 장 요약:

우주 API를 위한 "하이퍼스페이스 경로"를 구축했습니다! 이제:

  • 🗺️ 모든 엔드포인트는 /api/...로 접근 가능합니다.
  • 🔗 리소스 경로는 컨트롤러에 연결됩니다.
  • 🛡️ 특별한 작업을 위한 사용자 정의 경로가 추가되었습니다.
  • ✅ 경로는 Postman을 통해 테스트되었습니다.

우주가 요청을 위해 열렸습니다! 다음으로 "우주 쓰레기"로부터 보호하는 — 데이터 유효성 검사를 추가할 것입니다.

📌 확인:

  1. php artisan route:list를 실행합니다.
  2. planets에 대한 5개 이상의 경로가 보이는지 확인합니다.
  3. 브라우저/Postman에서 GET /api/planets의 작동을 확인합니다.

⚠️ 404 오류가 발생하면:

  • routes/api.phpRoute::apiResource가 있는지 확인합니다.
  • 서버가 실행 중인지 (php artisan serve) 확인합니다.
  • Windows의 경우: 방화벽에서 포트 8000을 허용합니다.