Skip to main content

커스텀 피벗 모델이란

belongsToMany(다대다)의 중간 테이블은 기본적으로 원시 Illuminate\Database\Eloquent\Relations\Pivot 인스턴스로 다뤄집니다. 중간 테이블에 추가 컬럼(승인 일시, 역할 종류 등)을 갖게 하거나, 액세서·뮤테이터·독자 메서드를 추가하고 싶은 경우에는 Pivot을 상속한 커스텀 모델을 만듭니다.
belongsToMany의 정의에서 using()을 호출해, 이 커스텀 모델을 사용하도록 관계에 전달합니다.
커스텀 피벗 모델을 저장할 때는, 모델 이름을 반드시 알파벳 순의 단수형으로 명명해 주세요(RoleUser이지 UserRole이 아닙니다). 다만 이는 표시 이름의 관례이며, 실제 클래스 이름은 자유롭게 결정할 수 있습니다.

as()로 취득하고 싶은 속성을 지정하기

기본적으로 중간 테이블의 값은 pivot 프로퍼티 경유로 접근합니다. as() 메서드를 사용하면, 이 이름을 변경할 수 있습니다.

추가 컬럼과 타임스탬프

중간 테이블에 approved와 같은 추가 컬럼이 있는 경우에는 withPivot()으로 명시적으로 취득 대상에 포함시킵니다. created_at / updated_at을 관리하는 경우에는 withTimestamps()를 호출합니다.
Eloquent가 중간 테이블의 updated_at을 자동 갱신하는 것은, 그 피벗 모델이 using()으로 명시적으로 지정되어 있는 경우뿐입니다. 기본 Pivot 클래스를 그대로 사용하는 경우에도 withTimestamps()는 동작하지만, using()으로 커스텀 모델을 지정하면 커스텀 이벤트·커스텀 캐스트 등을 이용할 수 있게 됩니다.

피벗 모델로부터의 역참조

커스텀 피벗 모델에는, 선언 원본 모델·관련 대상 모델로의 belongsTo 관계를 자유롭게 정의할 수 있습니다.
이로써, 피벗 모델 단체를 취득한 경우에도 $roleUser->role이나 $roleUser->user로 관련 모델에 접근할 수 있습니다. 다만, 이러한 관계를 부모 쿼리 실행 시에 자동적으로 Eager 로드하고 싶은 경우에는, 이하의 chaperone()을 사용하는 방법이 있습니다.

chaperone()에 의한 자동 Eager 로딩(Laravel 13)

Laravel 13에서, 피벗 모델에 정의한 role() / user()와 같은 belongsTo 관계를, belongsToMany 쿼리의 실행 시에 자동으로 하이드레이트(Eager 로드 상당의 연결)할 수 있는 chaperone() 메서드가 추가되었습니다.
chaperone()을 호출하면, Eloquent는 피벗 모델(RoleUser)이 갖는 belongsTo 관계의 이름을 자동적으로 추측하여, Role::with('users')처럼 컬렉션을 취득한 시점에, 각 피벗에 연결된 선언 원본 모델·관련 대상 모델로의 참조를 추가 쿼리 없이 설정합니다.

비표준 관계명을 사용하는 경우

피벗 모델의 belongsTo 관계의 메서드명이 표준적인 명명(선언 원본·관련 대상 모델명의 캐멀 케이스 단수형)과 다른 경우에는, chaperone()의 인수로 명시적으로 지정합니다.
chaperone()은 “N+1 문제”를 중간 테이블 경유의 참조에 대해서도 해소해 주는 구조입니다. 피벗 모델로부터 부모 모델의 정보(승인 일시와 사용자명을 함께 표시하는 등)를 빈번하게 참조하는 애플리케이션에서는, 통상의 with()에 의한 Eager 로딩과 조합해 활용하면 효과적입니다.

다음 단계

관계

belongsToMany를 포함한 기본적인 관계의 정의 방법으로 돌아가 복습합니다.

Eloquent Observers와 모델 이벤트

모델 이벤트를 사용해 피벗 모델의 저장·갱신을 훅하는 방법을 배웁니다.
마지막 수정일 2026년 9월 11일