메인 콘텐츠로 건너뛰기

Eloquent ORM이란

Laravel에는 Eloquent라는 객체 관계 매퍼(ORM)가 포함되어 있습니다. Eloquent는 데이터베이스와의 대화를 쉽게 하기 위한 것으로, ActiveRecord 패턴을 구현하고 있습니다. Eloquent를 사용하면 데이터베이스의 각 테이블에 대응하는 “모델” 클래스를 준비합니다. 모델을 통해 레코드의 조회·삽입·갱신·삭제를 할 수 있습니다.
Eloquent를 사용하기 전에 config/database.php에서 데이터베이스 접속을 설정해 주세요. 기본적으로 .env 파일의 DB_* 설정이 사용됩니다.

모델 생성

make:model Artisan 명령으로 새 모델을 생성합니다.
php artisan make:model Post
마이그레이션과 동시에 생성하는 경우에는 -m 옵션을 사용합니다.
php artisan make:model Post -m
모델은 app/Models 디렉터리에 생성됩니다.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    // ...
}

모델과 테이블의 대응 관계

Eloquent는 클래스명에서 테이블명을 자동으로 추측합니다. 클래스명을 스네이크케이스의 복수형으로 변환한 것이 테이블명이 됩니다.
모델명테이블명
Postposts
Userusers
AirTrafficControllerair_traffic_controllers
테이블명이 명명 규칙에 맞지 않는 경우, 모델에 $table 프로퍼티를 정의해 명시적으로 지정할 수 있습니다.
class Post extends Model
{
    protected $table = 'blog_posts';
}

타임스탬프

Eloquent는 기본적으로 created_atupdated_at 컬럼을 자동 관리합니다. 마이그레이션에서 $table->timestamps()를 추가해 두면 모델의 저장·갱신 시에 자동으로 값이 설정됩니다. 타임스탬프의 자동 관리를 무효화하려면 $timestampsfalse로 설정합니다.
class Post extends Model
{
    public $timestamps = false;
}

매스 어사인먼트 보호

Eloquent로 데이터를 일괄 저장할 때는 매스 어사인먼트 보호 설정이 필요합니다.

fillable

대입을 허용하는 컬럼을 $fillable 프로퍼티로 지정합니다.
class Post extends Model
{
    protected $fillable = [
        'user_id',
        'title',
        'body',
        'published',
    ];
}

guarded

반대로 대입을 금지하는 컬럼을 지정하려면 $guarded를 사용합니다.
class Post extends Model
{
    // 기본 키만 보호하고 나머지는 모두 허용한다
    protected $guarded = ['id'];
}
$guarded를 빈 배열로 하면 모든 컬럼에 대한 대입을 허용합니다. 사용자 입력을 그대로 전달하는 경우 의도하지 않은 컬럼이 변경될 위험이 있으므로, $fillable로 허용할 컬럼을 명시적으로 지정할 것을 권장합니다.

Eloquent 쿼리 실행 플로우

User::where()->get() 같은 쿼리가 어떻게 실행되는지, 내부 흐름을 보여 줍니다.

기본 CRUD 조작

레코드 가져오기(Read)

모든 레코드를 가져옵니다.
use App\Models\Post;

$posts = Post::all();
조건을 지정해서 가져옵니다.
// published가 true인 게시물을 가져오기
$publishedPosts = Post::where('published', true)->get();

// 첫 번째 1건만 가져오기
$post = Post::where('published', true)->first();

// ID로 1건 가져오기
$post = Post::find(1);

// 찾지 못하면 404 응답을 반환
$post = Post::findOrFail(1);

레코드 생성(Create)

create 메서드로 레코드를 하나 삽입합니다($fillable 설정이 필요합니다).
$post = Post::create([
    'title' => '첫 게시물',
    'body' => 'Laravel은 훌륭한 프레임워크입니다.',
    'published' => true,
]);
인스턴스를 생성해 개별적으로 대입할 수도 있습니다.
$post = new Post;
$post->title = '첫 게시물';
$post->body = 'Laravel은 훌륭한 프레임워크입니다.';
$post->save();

레코드 갱신(Update)

모델을 가져와 값을 변경한 후 save를 호출하면 갱신됩니다.
$post = Post::find(1);
$post->title = '갱신된 제목';
$post->save();
update 메서드를 사용하면 여러 컬럼을 한 번에 갱신할 수 있습니다.
Post::find(1)->update([
    'title' => '갱신된 제목',
    'published' => true,
]);
조건에 일치하는 여러 레코드를 일괄 갱신할 수도 있습니다.
Post::where('published', false)->update(['published' => true]);

레코드 삭제(Delete)

delete 메서드로 레코드를 삭제합니다.
$post = Post::find(1);
$post->delete();
ID를 지정해 직접 삭제할 수도 있습니다.
Post::destroy(1);

// 여러 ID를 일괄 삭제
Post::destroy([1, 2, 3]);

기본 쿼리 메서드

메서드설명
Post::all()모든 레코드를 가져오기
Post::find($id)ID로 1건 가져오기(찾지 못하면 null)
Post::findOrFail($id)ID로 1건 가져오기(찾지 못하면 404)
Post::where('column', 'value')->get()조건에 일치하는 레코드 가져오기
Post::where('column', 'value')->first()조건에 일치하는 첫 1건 가져오기
Post::where('column', 'value')->count()조건에 일치하는 건수 가져오기
Post::orderBy('created_at', 'desc')->get()정렬 순서를 지정해서 가져오기
Post::latest()->get()created_at 내림차순으로 가져오기
Post::limit(10)->get()건수를 제한해서 가져오기

실전 예시: Post 모델을 사용한 데이터 조작

마이그레이션으로 생성한 posts 테이블을 조작하는 컨트롤러 예시입니다.
<?php

namespace App\Http\Controllers;

use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\View\View;

class PostController extends Controller
{
    // 게시물 목록 표시
    public function index(): View
    {
        $posts = Post::where('published', true)
            ->latest()
            ->get();

        return view('posts.index', ['posts' => $posts]);
    }

    // 게시물 생성
    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
            'published' => ['boolean'],
        ]);

        Post::create([
            ...$validated,
            'user_id' => $request->user()->id,
        ]);

        return redirect('/posts');
    }

    // 게시물 갱신
    public function update(Request $request, Post $post): RedirectResponse
    {
        $validated = $request->validate([
            'title' => ['required', 'string', 'max:255'],
            'body' => ['required', 'string'],
        ]);

        $post->update($validated);

        return redirect('/posts');
    }

    // 게시물 삭제
    public function destroy(Post $post): RedirectResponse
    {
        $post->delete();

        return redirect('/posts');
    }
}
컨트롤러 메서드의 인수에 Post $post라고 쓰면 Laravel이 라우트 파라미터에서 모델을 자동으로 가져옵니다(라우트 모델 바인딩). Post::findOrFail($id)를 직접 작성할 필요가 없어집니다.

모델 이벤트의 라이프사이클

save()를 호출했을 때 발생하는 이벤트의 흐름을 보여줍니다. 신규 생성인지 갱신인지에 따라 다른 이벤트가 발생하지만, saving·saved는 양쪽 경우에 공통적으로 발생합니다.

다음 단계

마이그레이션

Eloquent가 이용하는 테이블을 마이그레이션으로 생성하는 방법을 되짚어 봅니다.
마지막 수정일 2026년 7월 13일