Laravel Seeder 활용법: 초기 역할(Role) 및 관리자 계정 생성 가이드

포스트 썸네일 이미지

오늘은 라라벨의 시더Seeder팩토리Factory를 활용해 프로젝트 초기 필수 역할과 관리자 계정을 자동으로 데이터베이스에 주입하는 방법, 그리고 이를 서비스 패널과 연동하는 과정을 정리해 보겠다.


이전에 filament를 설치한 후에 http://localhost/admin으로 가도 에러가 발생하면서 접속이 안 됐었다.

이번 포스트에서는 그 문제가 해결되면서 http://localhost/admin에 접속할 수 있을 거다.




이전 포스트




전체적인 코드 수정은 이 깃허브 링크를 통해서 확인할 수 있다.




시더(Seeder)란?


라라벨Laravel에서 시더Seeder는 데이터베이스(DB)에 테스트용 가짜 데이터나 초기 필수 데이터를 자동으로 채워주는 기능이다.


새로 프로젝트를 만들거나 데이터베이스를 리셋할 때마다 매번 수작업으로 회원가입을 하거나 카테고리 데이터를 넣는 것은 정말 번거로운 일이다.

하지만 Seeder를 사용하면 명령어 한 줄로 수십, 수백 개의 데이터를 순식간에 DB에 저장할 수 있다.


Seeder를 사용하는 일반적인 경우는 다음과 같다.


  1. 테스트 데이터 생성: 테스트 환경에서 어플리케이션의 동작을 테스트할 때 Seeder를 사용하여 가짜 데이터를 생성한다.
  2. 개발 환경 데이터 삽입: 애플리케이션을 개발할 때, 초기 데이터를 데이터베이스에 삽입해야 할 경우 Seeder를 사용한다.
  3. 프로덕션 환경에서 초기 데이터 설정: 어플리케이션을 배포할 때, 초기 데이터를 데이터베이스에 설정하는 데 Seeder를 사용할 수 있다. 이렇게 하면 배포 후에도 초기 데이터가 존재하게 된다.


이번에는 Seeder를 이용해서 웹사이트의 관리자 메뉴를 위한 데이터를 만들 거다.





RoleSeeder.php 파일 생성 및 수정


make bash #컨테이너 안으로 들어간다.
php artisan make:seeder RoleSeeder

ubuntu 혹은 VSCode의 터미널에서 이 명령어들을 실행한다.

이 명령어로 생성된 RoleSeeder.php 파일은 database/seeders/ 폴더에 위치하게 된다.




public function run(): void
{
    Role::create(['name' => 'admin']);
    Role::create(['name' => 'moderator']);
    Role::create(['name' => 'user']);
    Role::create(['name' => 'banned']);
}

'admin', 'moderator', 'user', 'banned' 이렇게 네 가지 역할(role)을 생성했다.

Role 클래스를 임포트Import 하는 것도 잊지 말자.





DatabaseSeeder.php 파일 수정


public function run(): void
{
    $this->call(RoleSeeder::class);

    User::factory()->create([
        'userid' => 'admin',
        'email' => 'admin@admin.com',
        'remember_token' => null,
    ])->assignRole('admin');
}

run 메서드를 다음과 같이 수정한다.


  • $this->call(RoleSeeder::class);: DatabaseSeeder 파일의 run 메서드로 RoleSeeder를 호출하면, RoleSeeder가 실행되어 'admin', 'moderator', 'user', 'banned' 역할이 데이터베이스에 삽입된다.
  • User::factory()->create([ ... ]): User 팩토리를 사용하여 userid가 'admin'이고, email이 'admin@admin.com'인 사용자 레코드를 생성한다. nickname은 일부러 설정하지 않았다.
  • 'remember_token' => null,: remember_token을 생성하지 않도록 하자.
  • ->assignRole('admin');: assignRole 메서드를 사용하여 해당 사용자에게 방금 전에 생성된 'admin' 역할을 부여한다.


이렇게 생성된 계정의 초기 패스워드는 UserFactory.php의 definition 메서드를 확인하자.




참고로 여기서는 RoleSeeder를 Import 하지 않아도 에러가 나지 않는다.

Laravel에서는 클래스를 자동으로 로드하고 실행할 수 있도록 서비스 프로바이더와 Composer의 클래스 맵을 사용 한다.

이를 통해 RoleSeeder 클래스를 Import 하지 않고도 DatabaseSeeder에서 이를 호출할 수 있다.

Laravel은 클래스를 자동으로 로드하여 실행하므로 파일이 같은 디렉터리에 있거나, Composer의 클래스 맵에 등록되어 있는 경우에도 문제없이 작동한다.


이런 기능은 Laravel의 자동으로 로드되는 서비스 프로바이더와 Composer의 클래스 맵 등의 기능에 의해 가능하며, 개발자가 클래스를 Import 하지 않아도 필요한 클래스를 사용할 수 있도록 한다.





factories/UserFactory.php 파일 수정


UserFactory는 User 모델 인스턴스를 생성하고 속성값을 설정하는 데 사용되는 Eloquent Factory 파일이다.

즉, 사용자 정보를 생성하는 데 사용되는 파일이라고 생각하면 된다.


DatabaseSeeder.php 파일에서 계정을 생성할 때, 따로 설정하지 않은 컬럼들(nickname이나 password 등)은 여기의 설정을 따르게 된다.




삭제할 코드

'name' => fake()->name(),

이 코드를 삭제하고 아래의 코드를 추가하자.




추가할 코드

'userid' => substr(fake()->unique()->userName(), 0, 15),
'nickname' => substr(fake()->unique()->name(), 0, 24),

php의 substr() 함수를 사용해서 각 컬럼의 문자열을 15글자와 24글자로 제한했다.

DB에서 테이블을 생성할 때 userid와 nickname 컬럼의 글자수 제한을 그렇게 했었기 때문이다.

이 설정을 해두지 않으면 랜덤으로 생성되는 문자열이 글자수 제한을 넘어갈 경우, 에러가 나서 계정이 생성되지 않는다.





데이터 주입


php artisan db:seed

세 파일의 수정이 끝났다면 저장이 되었는지 확인하고 이 명령어를 실행한다.

그리고 데이터베이스를 확인해 보면 roles 테이블에 'admin', 'moderator', 'user', 'banned'가 생성되어 있고, users 테이블에는 admin 계정이 생성된 것을 확인할 수 있다.

생성된 계정에 admin 역할이 제대로 부여되어 있는지 확인하려면 model_has_roles 테이블을 확인하자.


이런 식으로 Laravel에서 Seeder를 만들려면 php artisan make:seeder 명령어를 사용하고, 생성된 Seeder 클래스의 run 메서드에 데이터베이스에 삽입할 코드를 작성한다.

그런 다음, php artisan db:seed 명령어를 사용하여 Seeder를 실행해서 데이터를 DB에 주입할 수 있다.


예를 들어, php artisan make:seeder UserSeeder 명령어를 사용하여 UserSeeder 클래스를 생성하고, 이후에 UserSeeder 클래스의 run 메서드에 사용자 데이터를 생성하는 코드를 추가한 후, php artisan db:seed --class=UserSeeder 명령어를 사용하여 데이터베이스에 주입할 수 있다.




User 모델(User.php) 수정


// 추가
use Filament\Models\Contracts\FilamentUser;
use Filament\Models\Contracts\HasName;
use Filament\Panel;

class User extends Authenticatable implements FilamentUser, HasName // 추가
{
    // 생략

    // 추가
    public function canAccessPanel(Panel $panel): bool
    {
        return $this->hasRole('admin');
    }

    public function getFilamentName(): string
    {
        return $this->nickname;
    }
}

여기서는 코드가 어떻게 수정된 건지 보기 불편하니, 위에 링크한 깃허브 링크를 참고하자.





implements FilamentUser

이 부분은 User 모델이 FilamentUser 인터페이스를 구현한다는 의미다.

즉, User 클래스는 Filament에서 제공하는 FilamentUser 인터페이스의 규약을 따라야 하며,이를 통해 Filament 패널 시스템과 상호작용할 수 있다.


Filament는 여러 패널(예: 관리 패널, 사용자 패널 등)을 만들 수 있는데,각 사용자가 해당 패널에 접근할 수 있는지 여부를 확인하기 위해 FilamentUser 인터페이스를 요구한다.

(HasName도 추가되었는데, 이것에 대한 설명은 아래에..)




public function canAccessPanel(Panel $panel): bool
{
    return $this->hasRole('admin');
}

이 메서드는 사용자가 특정 Filament 패널에 접근할 수 있는지를 결정한다.

canAccessPanel은 Filament에서 호출되며,사용자가 주어진 패널에 접근할 권한이 있는지를 확인하는 역할을 한다.


  • Panel $panel: Filament에서 전달되는 패널 객체다. 패널이 여러 개일 수 있으므로, 패널별로 접근 권한을 설정할 수 있다.
  • return $this->hasRole('admin'): hasRole 메서드는 사용자가 특정 역할(이 경우 'admin')을 가지고 있는지 확인한다. 이 코드에서는 'admin' 역할을 가진 사용자만 해당 패널에 접근할 수 있도록 제한하고 있다.


따라서, canAccessPanel 메서드는 사용자가 'admin' 역할을 가지고 있을 때만 Filament 패널에 접근할 수 있도록 하고, 그렇지 않으면 접근이 불가능하게 만든다.





implements HasName

HasName은 사용자 모델에서 이름을 어떻게 다룰지를 정의하는 인터페이스다.

이 인터페이스를 추가하면 Filament와 같은 도구들이 사용자의 이름을 가져올 때 HasName 인터페이스에 정의된 메서드를 통해 이름을 참조할 수 있게 된다.




public function getFilamentName(): string
{
    return $this->nickname;
}

이 메서드는 Filament가 사용자 이름을 표시할 때 호출된다.

기존에 name 필드를 사용하던 부분을 nickname으로 대체하는 역할을 한다.


이 메서드를 추가하지 않으면 filament 관리자 패널로 접속할 때, name 값이 null이라서 에러가 나게 된다.




filament 관리자 패널 로그인 폼

이제 비로그인 상태에서 http://localhost/admin으로 이동하면 이렇게 관리자 로그인 창이 나온다.

관리자가 아닌 ID로 로그인을 해놓은 경우에는 403 에러가 뜨게 된다.




다음 포스트

이 글이 도움이 됐거나 유익했다면 스크롤을 조금만 더 내려서 댓글을 남겨주세요. (비로그인도 가능합니다!)
응원이나 피드백이 담긴 댓글은 제가 계속 블로그를 해나갈 수 있는 원동력이 됩니다. 😊

지인에게 보여주고 싶은 글이었다면 URL을 복사해서 메신저나 소셜 미디어에 공유해 주세요.
이전 포스트 다음 포스트

댓글 쓰기

0 Comments

문의하기 양식