라라벨, 댓글 기능을 위한 준비 (feat. nullOnDelete)

포스트 썸네일 이미지

이번 포스트에서는 라라벨 애플리케이션에 댓글 및 대댓글 기능을 도입하기 위한 첫 단계로, Comment 모델과 마이그레이션 파일 생성, DB 컬럼 설계, 그리고 모델 간 릴레이션 설정 과정을 다뤄보겠다.

새로운 내용은 마이그레이션 파일에서 사용할 nullOnDelete() 메서드뿐이고, 거의 이전에 공부했던 내용의 복습이라고 볼 수 있다.




이전 포스트




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




Comment의 모델・마이그레이션 파일 생성


make bash #컨테이너 안으로 들어간다.
php artisan make:model Comment -m

ubuntu 혹은 VSCode의 터미널에서 이 명령어들을 실행해서 Comment 모델을 생성한다.

-m 옵션을 꼭 붙여서 마이그레이션 파일도 같이 생성한다.




위의 명령어에 대한 설명은 이 포스트를 참고하자.


이전에 Category와 Article 모델을 생성했을 때와 마찬가지로 컨트롤러는 생성할 필요가 없다.

Livewire를 사용하고 있기 때문에 😎





comments 테이블에 추가할 컬럼


create_comments_table.php

public function up(): void
{
    Schema::create('comments', function (Blueprint $table) {
        $table->id();
        $table->foreignId('article_id')->constrained()->cascadeOnDelete();
        $table->foreignId('user_id')->constrained()->cascadeOnDelete();
        $table->foreignId('parent_id')->nullable()->constrained('comments')->cascadeOnDelete();
        $table->foreignId('mentioned_user_id')->nullable()->constrained('users')->nullOnDelete();
        $table->string('body', 2000);
        $table->string('ip_address', 45)->nullable();
        $table->timestamps();
        $table->softDeletes();
    });
}

먼저 comments 테이블에 추가할 컬럼들에 대해서 간단히 설명하겠다.


  • article_id: 어떤 게시글의 댓글인지 저장하는 컬럼이다.
  • user_id: 댓글 작성자의 ID를 저장하는 컬럼이다.
  • parent_id: 대댓글인 경우, 부모 댓글 ID를 저장하는 컬럼이다. 최상위 댓글은 null이 된다.
  • mentioned_user_id: 멘션된 사용자의 ID를 저장하는 컬럼이다. 처음 사용되는 nullOnDelete() 메서드에 대해서는 아래에서 따로 설명하겠다.
  • body: 댓글 내용을 저장한다. 데이터 타입을 string으로 하고 글자수는 2000자로 제한을 두었다.
  • ip_address: articles 테이블을 만들었을 때와 같다. 작성자의 IP를 저장하는 컬럼이다.




라라벨Laravel의 마이그레이션 파일에서 사용하는 nullOnDelete() 메서드는 데이터베이스의 외래키 제약조건(Foreign Key Constraint) 옵션 중 하나로, 참조하고 있는 부모 데이터가 삭제될 때, 자식 데이터의 외래키 컬럼 값을 NULL로 변경한다.


예를 들어, 사용자 B의 대댓글에 사용자 A가 댓글을 남겼다. (사용자 A가 대댓글을 달면서 사용자 B를 멘션했다.)

그런데 사용자 B가 웹사이트에서 탈퇴(계정 삭제)를 했다.

그러면 users 테이블에서 사용자 B의 데이터가 완전히 사라질 것이다.

그때, 사용자 B의 계정이 삭제되어도, 사용자 A가 작성한 댓글 자체는 삭제되지 않고 그대로 유지된다.

다만, 그 댓글에 기록되어 있던 mentioned_user_id 컬럼의 값만 자동으로 NULL로 변경되는 것이다.





constrained()와 cascadeOnDelete()와 nullable() 메서드에 대한 설명은 이 포스트를 참고하자.




$table->softDeletes();에 대해서는 이 포스트에서 설명했었다.




Comment 모델에 SoftDeletes를 임포트


app/Models/Comment.php에 추가할 코드

use Illuminate\Database\Eloquent\SoftDeletes;

class Comment extends Model
{
    use SoftDeletes;
}

Soft Delete 기능을 활성화하기 위해서는 Comment 모델에 use SoftDeletes;를 추가하고 Import 해야 한다.





Article 모델과 Comment 모델과 User 모델의 릴레이션 설정


app/Models/User.php

public function comments(): HasMany
{
    return $this->hasMany(Comment::class);
}

한 명의 회원은 여러 개의 댓글을 남길 수 있다는 관계 설정을 해두었다.




app/Models/Article.php

public function comments(): HasMany
{
    return $this->hasMany(Comment::class);
}

하나의 Article에는 여러 개의 댓글이 달릴 수 있다는 설정을 해두었다.




app/Models/Comment.php

public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

public function article(): BelongsTo
{
    return $this->belongsTo(Article::class);
}

하나의 Comment에는 한 명의 작성자만 존재할 수 있고, 하나의 Article에만 달릴 수 있다는 설정을 해두었다.




이 릴레이션 설정에 대해서는 이전에 작성했던 이 포스트에서 더 자세히 설명했었으니 참고하도록 하자.




Comment 모델의 릴레이션 설정 코드 캡처

이번 포스트는 딱히 올릴만한 썸네일 이미지가 없어서 그냥 릴레이션 설정 코드를 캡처해 보았다.




이것으로 댓글 기능을 위한 DB 구조와 모델 관계 설정이 모두 완료되었다.

다음 포스트부터 댓글 기능을 구현하는 과정을 천천히 다뤄보겠다.

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

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

댓글 쓰기

0 Comments

문의하기 양식