"Laravel 중급 태스크 목록"의 두 판 사이의 차이

230번째 줄: 230번째 줄:


===태스크 컨트롤러===
===태스크 컨트롤러===
태스크를 조회하고 저장할 필요가 있으므로, Artisan CLI를 사용하여 <code>TaskController</code>를 생성합시다. 그러면 컨트롤러가 <code>app/Http/Controllers</code> 디렉토리에 생성됩니다:
<syntaxhighlight lang='bash'>
php artisan make:controller TaskController
</syntaxhighlight>
컨트롤러가 생성되었으니, <code>app/Http/routes.php</code> 파일에 컨트롤러를 가리키는 몇 가지 라우트를 추가해 봅시다:
<syntaxhighlight lang='php'>
Route::get('/tasks', 'TaskController@index');
Route::post('/task', 'TaskController@store');
Route::delete('/task/{task}', 'TaskController@destroy');
</syntaxhighlight>
;모든 태스크 라우트 인증하기
이 애플리케이션에서는 모든 태스크 라우트가 인증된 사용자만 접근할 수 있도록 하고 싶습니다. 즉, 사용자가 태스크를 생성하려면 애플리케이션에 "로그인"해야 합니다. Laravel에서는 미들웨어를 사용하여 이러한 작업을 간단하게 할 수 있습니다.
컨트롤러의 모든 액션에 대해 인증된 사용자만 접근할 수 있도록 하려면, 컨트롤러 생성자에서 <code>middleware</code> 메소드를 호출하면 됩니다. 사용가능한 모든 라우트 미들웨어는 <code>app/Http/Kernel.php</code> 파일에 정의되어 있습니다. 이 경우에는, 모든 액션에 <code>auth</code> 미들웨어를 할당하고자 합니다:
<syntaxhighlight lang='php'>
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
class TaskController extends Controller
{
    /**
    * 새 컨트롤러 인스턴스를 생성합니다.
    *
    * @return void
    */
    public function __construct()
    {
        $this->middleware('auth');
    }
}
</syntaxhighlight>


==레이아웃 및 뷰 구축==
==레이아웃 및 뷰 구축==

2024년 6월 15일 (토) 23:24 판

1 개요

Intermediate Task List
중급 태스크 목록

https://laravel.com/docs/5.2/quickstart-intermediate

2 소개

이 빠른 시작 가이드는 Laravel 프레임워크에 대한 중급 소개를 제공하며, 데이터베이스 마이그레이션, Eloquent ORM, 라우팅, 인증, 인, 의존성 주입, 검증, 뷰, Blade 템플릿에 대한 내용을 포함하고 있습니다. Laravel 프레임워크나 PHP 프레임워크에 대한 기본 지식이 있는 경우, 이 가이드를 시작하기에 적합합니다.

Laravel의 기본 기능들을 샘플로 다루어 보기 위해, 태스크들을 다루는 태스크 목록 애플리케이션을 만들어 보겠습니다. 즉, 전형적인 "할 일" 목록 예제를 다루게 됩니다. "기본" 빠른 시작과 달리, 이 튜토리얼에서는 사용자가 계정을 만들고 애플리케이션에 인증할 수 있도록 할 것입니다. 이 프로젝트의 완성된 소스코드는 GitHub에서 확인할 수 있습니다.

3 설치

우선, Laravel 프레임워크을 새로 설치해야 합니다. Homestead 가상머신을 사용하거나 선택한 로컬 PHP 환경을 사용하여 프레임워크를 실행할 수 있습니다. 로컬 환경이 준비되면 Composer를 사용하여 Laravel 프레임워크를 설치할 수 있습니다:

composer create-project laravel/laravel quickstart --prefer-dist

4 데이터베이스 준비

4.1 데이터베이스 마이그레이션

먼저, 데이터베이스 테이블을 정의하기 위해 마이그레이션을 사용해 보겠습니다. Laravel의 데이터베이스 마이그레이션은 유창하고 표현적인 PHP 코드를 사용하여 데이터베이스 테이블 구조와 수정 사항을 쉽게 정의할 수 있는 방법을 제공합니다. 팀원들에게 데이터베이스의 로컬 복사본에 수동으로 열을 추가하라고 지시하는 대신, 소스 컨트롤에 푸시한 마이그레이션을 실행하기만 하면 됩니다.

users 테이블

애플리케이션 내에서 사용자가 계정을 생성할 수 있도록 할 예정이므로 모든 사용자를 저장할 테이블이 필요합니다. 다행히도 Laravel은 기본 users 테이블을 생성하기 위한 마이그레이션을 이미 제공하고 있으므로 직접 생성할 필요가 없습니다. 기본 마이그레이션은 database/migrations 디렉터리에 위치해 있습니다.

tasks 테이블

다음으로, 모든 태스크을 저장할 데이터베이스 테이블을 생성해 보겠습니다. Artisan CLI는 다양한 클래스를 생성하는 데 사용할 수 있으며, Laravel 프로젝트를 구축할 때 많은 타이핑을 절약해 줍니다. 이번에는 make:migration 명령어를 사용하여 tasks 테이블에 대한 새로운 데이터베이스 마이그레이션을 생성해 보겠습니다:

php artisan make:migration create_tasks_table --create=tasks

이 마이그레이션 파일은 프로젝트의 database/migrations 디렉토리에 생성됩니다. make:migration 명령어는 자동 증가 ID와 타임스탬프를 이미 마이그레이션 파일에 추가했습니다. 이 파일을 편집하여 태스크의 이름을 위한 name 문자열 컬럼과, tasks 테이블과 users 테이블을 연결할 user_id 컬럼을 추가해봅시다:

<?php
 
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateTasksTable extends Migration
{
    /**
     * 마이그레이션을 실행합니다.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('tasks', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('user_id')->unsigned()->index();
            $table->string('name');
            $table->timestamps();
        });
    }
 
    /**
     * 마이그레이션을 되돌립니다.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('tasks');
    }
}

마이그레이션을 실행하려면 migrate Artisan 명령어를 사용합니다. Homestead를 사용 중이라면, 호스트 머신이 데이터베이스에 직접 접근할 수 없으므로, 가상머신 내에서 이 명령어를 실행해야 합니다:

php artisan migrate

이 명령어는 모든 데이터베이스 테이블을 생성합니다. 사용 중인 데이터베이스 클라이언트를 통해 데이터베이스 테이블을 확인하면, 마이그레이션에서 정의한 컬럼이 포함된 새로운 tasksusers 테이블을 볼 수 있을 것입니다. 이제 Eloquent ORM 모델을 정의할 준비가 되었습니다!

4.2 Eloquent 모델

Eloquent는 Laravel의 기본 ORM(객체 관계 매퍼)입니다. Eloquent를 사용하면 명확하게 정의된 "모델"을 통해 데이터베이스에서 데이터를 쉽게 검색하고 저장할 수 있습니다. 일반적으로 각 Eloquent 모델은 단일 데이터베이스 테이블과 직접적으로 대응됩니다.

User 모델

먼저, users 데이터베이스 테이블에 대응하는 모델이 필요합니다. 그러나 프로젝트의 app 디렉토리를 살펴보면 Laravel에 이미 User 모델이 포함되어 있으므로 수동으로 생성할 필요가 없습니다.

Task 모델

이제 tasks 데이터베이스 테이블에 대응하는 Task 모델을 정의해봅시다. Artisan 명령어를 사용하여 이 모델을 생성할 수 있습니다. 이번에는 make:model 명령어를 사용합니다:

php artisan make:model Task

모델은 애플리케이션의 app 디렉토리에 배치됩니다. 기본적으로 모델 클래스는 비어 있습니다. Eloquent 모델에 어떤 테이블과 대응되는지 명시적으로 알릴 필요는 없습니다. 왜냐하면 Eloquent는 모델 이름의 복수형을 데이터베이스 테이블로 가정하기 때문입니다. 따라서, Task 모델은 tasks 데이터베이스 테이블과 대응되는 것으로 간주됩니다.

이제 이 모델에 몇 가지를 추가해봅시다. 먼저, name 속성이 "mass-assignable(대량 할당가능)"하도록 명시하겠습니다. 이를 통해 Eloquent의 create 메소드를 사용하여 name 속성을 채울 수 있습니다:

<?php
 
namespace App;
 
use Illuminate\Database\Eloquent\Model;
 
class Task extends Model
{
    /**
     * 대량 할당가능한 속성.
     *
     * @var array
     */
    protected $fillable = ['name'];
}

라우트를 애플리케이션에 추가하면서 Eloquent 모델을 사용하는 방법에 대해 더 알아볼 것입니다. 물론, 더 많은 정보를 원한다면 전체 Eloquent 문서를 참조해도 좋습니다.

4.3 Eloquent 관계

이제 모델이 정의되었으므로, 이들을 연결해야 합니다. 예를 들어, User는 여러 개의 Task 인스턴스를 가질 수 있으며, Task는 단일 User에게 할당됩니다. 관계를 정의하면 다음과 같이 관계를 통해 유연하게 조회할 수 있습니다:

$user = App\User::find(1);

foreach ($user->tasks as $task) {
    echo $task->name;
}
tasks 관계

먼저 User 모델에 tasks 관계를 정의해보겠습니다. Eloquent 관계는 모델의 메소드로 정의됩니다. Eloquent는 여러 가지 관계를 지원하므로 전체 Eloquent 문서를 참조하여 더 많은 정보를 확인하세요. 이 경우에는, User 모델에 hasMany 메소드를 호출하는 tasks 함수를 정의합니다:

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    // 기타 Eloquent 속성들...

    /**
     * 사용자의 모든 태스크를 가져옵니다.
     */
    public function tasks()
    {
        return $this->hasMany(Task::class);
    }
}
user 관계

다음으로, Task 모델에 user 관계를 정의해보겠습니다. 이번에도 모델에 메소드로 관계를 정의합니다. 이 경우에는, belongsTo 메소드를 사용하여 관계를 정의합니다:

<?php

namespace App;

use App\User;
use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    /**
     * 대량 할당 가능한 속성들.
     *
     * @var array
     */
    protected $fillable = ['name'];

    /**
     * 태스크를 소유한 사용자를 가져옵니다.
     */
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

훌륭합니다! 이제 관계가 정의되었으므로 컨트롤러를 만들기 시작할 수 있습니다!

5 라우팅

태스크 목록 애플리케이션의 기본 버전에서는 routes.php 파일 내에서 클로저를 사용하여 모든 로직을 정의했습니다. 여기서는 주로 컨트롤러를 사용하여 라우트를 조직할 것입니다. 컨트롤러를 사용하면 HTTP 요청 처리 로직을 여러 파일에 걸쳐 분산시켜 더 나은 조직화를 할 수 있습니다.

5.1 뷰 표시하기

단일 라우트를 사용하여 클로저를 구현할 것입니다. 이는 애플리케이션의 게스트를 위한 랜딩 페이지가 될 / 라우트입니다. 그럼, / 라우트를 작성해 봅시다. 이 라우트에서는 "welcome" 페이지를 포함하는 HTML 템플릿을 렌더링하고자 합니다.

Laravel에서는 모든 HTML 템플릿은 resources/views 디렉토리에 저장되며, view 헬퍼를 사용하여 이 템플릿 중 하나를 라우트에서 반환할 수 있습니다:

Route::get('/', function () {
    return view('welcome');
});

물론, 이 뷰를 실제로 정의해야 합니다. 이는 조금 있다가 할 것입니다!

5.2 인증

사용자가 계정을 만들고 애플리케이션에 로그인할 수 있도록 하는 것도 필요합니다. 일반적으로 웹 애플리케이션에 전체 인증 레이어를 구축하는 것은 번거로운 작업일 수 있습니다. 그러나 이는 매우 일반적인 요구사항이기 때문에, Laravel은 이 과정을 완전히 간단하게 만들려고 시도합니다.

먼저, Laravel 애플리케이션에 이미 포함된 app/Http/Controllers/Auth/AuthController가 있다는 점에 주목하세요. 이 컨트롤러는 사용자를 생성하고 인증하는 데 필요한 모든 로직을 포함하는 특별한 AuthenticatesAndRegistersUsers 트레이트를 사용합니다.

인증 라우트 및 뷰

그렇다면 우리가 해야 할 일은 무엇일까요? 등록 및 로그인 템플릿을 만들고 인증 컨트롤러를 가리키는 라우트를 정의해야 합니다. make:auth Artisan 명령어를 사용하여 이 모든 작업을 수행할 수 있습니다:

php artisan make:auth

참고: 이러한 뷰에 대한 전체 예제를 보려면, 애플리케이션의 전체 소스코드가 GitHub에 있다는 점을 기억하세요.

이제 해야 할 일은 인증 라우트를 라우트 파일에 추가하는 것입니다. 이는 Route 파사드에 있는 auth 메소드를 사용하여 등록, 로그인, 패스워드 재설정을 위한 모든 라우트를 등록하여 수행할 수 있습니다:

// 인증 라우트...
Route::auth();

인증 라우트가 등록되면, app/Http/Controllers/Auth/AuthController 컨트롤러의 $redirectTo 속성이 '/tasks'로 설정되어 있는지 확인합니다:

protected $redirectTo = '/tasks';

또한 app/Http/Middleware/RedirectIfAuthenticated.php 파일을 적절한 리다이렉트 경로로 업데이트해야 합니다:

return redirect('/tasks');

5.3 태스크 컨트롤러

태스크를 조회하고 저장할 필요가 있으므로, Artisan CLI를 사용하여 TaskController를 생성합시다. 그러면 컨트롤러가 app/Http/Controllers 디렉토리에 생성됩니다:

php artisan make:controller TaskController

컨트롤러가 생성되었으니, app/Http/routes.php 파일에 컨트롤러를 가리키는 몇 가지 라우트를 추가해 봅시다:

Route::get('/tasks', 'TaskController@index');
Route::post('/task', 'TaskController@store');
Route::delete('/task/{task}', 'TaskController@destroy');
모든 태스크 라우트 인증하기

이 애플리케이션에서는 모든 태스크 라우트가 인증된 사용자만 접근할 수 있도록 하고 싶습니다. 즉, 사용자가 태스크를 생성하려면 애플리케이션에 "로그인"해야 합니다. Laravel에서는 미들웨어를 사용하여 이러한 작업을 간단하게 할 수 있습니다.

컨트롤러의 모든 액션에 대해 인증된 사용자만 접근할 수 있도록 하려면, 컨트롤러 생성자에서 middleware 메소드를 호출하면 됩니다. 사용가능한 모든 라우트 미들웨어는 app/Http/Kernel.php 파일에 정의되어 있습니다. 이 경우에는, 모든 액션에 auth 미들웨어를 할당하고자 합니다:

<?php
 
namespace App\Http\Controllers;
 
use App\Http\Requests;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
 
class TaskController extends Controller
{
    /**
     * 새 컨트롤러 인스턴스를 생성합니다.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }
}

6 레이아웃 및 뷰 구축

6.1 레이아웃 정의

6.2 자식 뷰 정의

7 태스크 추가

7.1 유효성 검사

7.2 태스크 생성

8 기존 태스크 표시

8.1 의존성 주입

8.2 태스크 표시

9 태스크 삭제

9.1 삭제 버튼 추가

9.2 라우트 모델 바인딩

9.3 인가

이제 destroy 메소드에 Task 인스턴스가 주입되었지만, 인증된 사용자가 해당 태스크를 실제로 "소유"하고 있는지 확실하지 않습니다. 예를 들어, 악의적인 요청이 랜덤 태스크 ID를 /tasks/{task} URL에 전달되어 다른 사용자의 태스크를 삭제하려는 시도로 있을 수 있습니다. 따라서 Laravel의 인증 기능을 사용하여 인증된 사용자가 주입된 Task 인스턴스를 실제로 소유하고 있는지 확인해야 합니다.

정책 생성

Laravel은 "정책"을 사용하여 인증 로직을 간단하고 작은 클래스에 조직합니다. 일반적으로 각 정책은 모델에 대응됩니다. Artisan CLI를 사용하여 TaskPolicy를 생성해보겠습니다. 생성된 파일은 app/Policies/TaskPolicy.php에 배치됩니다:

php artisan make:policy TaskPolicy

다음으로, 정책에 destroy 메소드를 추가해보겠습니다. 이 메소드는 User 인스턴스와 Task 인스턴스를 받습니다. 메소드는 단순히 사용자의 ID가 태스크의 user_id와 일치하는지 확인합니다. 실제로 모든 정책 메소드는 true 또는 false를 반환해야 합니다:

<?php

namespace App\Policies;

use App\Models\User;
use App\Models\Task;
use Illuminate\Auth\Access\HandlesAuthorization;

class TaskPolicy
{
    use HandlesAuthorization;

    /**
     * 주어진 사용자가 주어진 태스크를 삭제할 수 있는지 결정합니다.
     *
     * @param  User  $user
     * @param  Task  $task
     * @return bool
     */
    public function destroy(User $user, Task $task)
    {
        return $user->id === $task->user_id;
    }
}

마지막으로, Task 모델을 TaskPolicy와 연계해야 합니다. 이는 app/Providers/AuthServiceProvider.php 파일의 $policies 속성에 한 줄을 추가하여 수행할 수 있습니다. 이를 통해 Laravel은 Task 인스턴스에서 태스크를 인증할 때 어떤 정책을 사용할지 알 수 있습니다:

/**
 * 애플리케이션의 정책 매핑.
 *
 * @var array
 */
protected $policies = [
    'App\Models\Task' => 'App\Policies\TaskPolicy',
];
액션 인가

정책이 작성되었으므로, 이를 destroy 메소드에서 사용해 보겠습니다. 모든 Laravel 컨트롤러는 AuthorizesRequest 트레이트를 통해 노출된 authorize 메소드를 호출할 수 있습니다:

/**
 * 주어진 태스크를 삭제합니다.
 *
 * @param  Request  $request
 * @param  Task  $task
 * @return Response
 */
public function destroy(Request $request, Task $task)
{
    $this->authorize('destroy', $task);

    // 태스크를 삭제합니다...
}

이 메소드 호출을 잠시 살펴보겠습니다. authorize 메소드에 전달된 첫 번째 인수는 호출하려는 정책 메소드의 이름입니다. 두 번째 인수는 현재 관심 있는 모델 인스턴스입니다. 조금 전에 Task 모델이 TaskPolicy에 대응된다고 Laravel에 알렸기 때문에, 프레임워크는 어떤 정책에서 destroy 메소드를 실행할지 알고 있습니다. 현재 사용자는 자동으로 정책 메소드에 전달되므로 이를 수동으로 전달할 필요가 없습니다.

액션이 인증되면 코드는 정상적으로 계속 실행됩니다. 그러나 액션이 인증되지 않은 경우(즉, 정책의 destroy 메소드가 false를 반환하는 경우) 403 예외가 발생하고 사용자에게 오류 페이지가 표시됩니다.

참고: Laravel이 제공하는 인가 서비스와 상호작용하는 방법은 여러 가지가 있습니다. 전체 인가 문서를 꼭 살펴보시기 바랍니다.

9.4 해당 태스크 삭제

마지막으로, 주어진 태스크를 실제로 삭제하는 로직을 destroy 메소드에 추가해 보겠습니다. Eloquent의 delete 메소드를 사용하여 데이터베이스에서 주어진 모델 인스턴스를 삭제할 수 있습니다. 레코드가 삭제된 후, 사용자를 /tasks URL로 리디렉션할 것입니다:

/**
 * 주어진 태스크를 삭제합니다.
 *
 * @param  Request  $request
 * @param  Task  $task
 * @return Response
 */
public function destroy(Request $request, Task $task)
{
    $this->authorize('destroy', $task);
 
    $task->delete();
 
    return redirect('/tasks');
}
문서 댓글 ({{ doc_comments.length }})
{{ comment.name }} {{ comment.created | snstime }}