메인 콘텐츠로 건너뛰기
패키지가 제공하는 모델에 인가를 추가하면서도, 이용 애플리케이션에는 독자적인 규칙으로 교체할 여지를 남기고 싶을 때가 있습니다. 모델과 Policy의 대응을 명시하고 사용자 판정은 인가를 실행하는 시점에 수행하는 구조로 만들면, 등록 처리와 요청별 판단을 분리할 수 있습니다. 이 페이지는 Laravel 공식 문서의 기본 브랜치 13.x와, 2026년 11월 10일에 확인한 Framework 최신 릴리스 v13.42.0의 공식 구현·테스트를 참조하고 있습니다. 인가의 기본은 인가 가이드, 프로바이더 로딩은 패키지 자동 검출을 참조하세요.

이용 앱의 User 클래스에 의존하지 않기

예로서 패키지의 Acme\Reports\Models\Report에 update 인가를 추가합니다. acme_reports 테이블에는 소유자의 인증 식별자를 저장하는 owner_id 컬럼이 있다고 가정합니다. 마이그레이션 제공 방법은 패키지 마이그레이션에서 다루고 있습니다. src/Models/Report.php는 일반적인 Eloquent 모델입니다.
패키지 측 Policy가 App\Models\User를 타입 지정하면 이용 앱의 네임스페이스나 모델 구성에 의존하게 됩니다. 필요한 것이 사용자의 인증 식별자뿐이라면 Laravel의 Authenticatable 계약을 사용합니다. src/Policies/ReportPolicy.php에 다음을 둡니다.
식별자의 null을 먼저 제외하고, DB에서 가져온 정수와 문자열의 타입 차이는 문자열화해서 비교합니다. 이 예에서는 소유자에게만 갱신을 허용합니다. 여러 사용자 종류나 Guard를 다루는 앱에서는 식별자만으로 주체를 고유하게 특정할 수 있는지도 확인하고, 필요하면 사용자 종류나 테넌트 경계를 포함한 독자 Policy로 교체합니다.
Authenticatable은 인증 식별자 등의 계약이며, isAdministrator()나 역할 취득 메서드는 제공하지 않습니다. 패키지 고유의 권한 정보가 필요하다면 별도의 계약을 정의하고 이용 앱에서 구현을 주입하는 설계로 합니다.

서비스 프로바이더에서 대응 등록하기

src/ReportsServiceProvider.php의 boot()에서 패키지가 소유한 모델만 등록합니다.
Gate::policy()는 모델의 클래스명을 키로 Policy의 클래스명을 저장합니다. 이 등록 자체로는 Policy를 생성하지 않으며, DB 조회도 사용자 판정도 수행하지 않습니다. Gate::getPolicyFor() 등에서 Policy가 필요해졌을 때 컨테이너의 make()로 생성합니다. 그래서 Policy의 생성자에는 의존 서비스를 주입할 수 있습니다. Report와 ReportPolicy의 배치는 표준 자동 검출에도 맞지만, 여기서는 패키지가 제공하는 대응을 명확히 하기 위해 명시적으로 등록하고 있습니다. 등록만으로는 HTTP 엔드포인트에 인가가 적용되지 않습니다. 갱신 처리 전에 컨트롤러 등에서 다음을 호출합니다.
거부 시에는 AuthorizationException이 발생하고, 일반적인 HTTP 처리에서는 403 응답이 됩니다. 모델을 전달하는 update와 모델의 클래스명을 전달하는 create 등은 Policy 메서드의 인수가 다르므로, 인가 가이드의 호출 방법에 맞춥니다.

Policy 해결 우선순위 읽기

Gate::getPolicyFor()는 대상이 객체이면 클래스명으로 변환하고 다음 순서로 찾습니다. 이것은 Policy를 선택하는 순서이며, 인가 전체의 훅 실행 순서가 아닙니다. 따라서 같은 Report 클래스에 대한 명시 등록이 있는 상태에서는 #[UsePolicy]나 명명 규칙을 바꾸는 것만으로는 교체되지 않습니다. 반면 이용 앱이 Report를 상속한 모델을 사용하는 경우, 자식 클래스 자신의 속성이나 추측으로 발견되는 Policy가 부모에 대한 명시 등록보다 먼저입니다. 실제로 사용하는 모델 클래스에서도 확인합니다.
guessPolicyNamesUsing()은 추가 콜백 목록이 아니라 Gate가 가진 하나의 추측 콜백을 대체합니다. 독립적인 패키지가 자신의 모델만을 위해 설정하면 이용 앱이나 다른 패키지의 추측에도 영향을 줍니다. 패키지가 소유한 모델에 대한 policy() 등록을 기본으로 하세요.

이용 앱에서 명시적으로 재정의하기

같은 모델에 다시 policy()를 호출하면 대응은 나중의 등록으로 대체됩니다. 단순히 다른 프로바이더의 boot()에 두는 것만으로는 로딩 순서에 의존하므로, 이용 앱의 AppServiceProvider::boot()에서 앱의 부팅 완료 콜백을 등록하는 방법이 있습니다.
ApplicationReportPolicy는 이용 앱이 구현하는 Policy입니다. 패키지 측이 일반적인 boot()에서 등록하는 구성이라면 이 콜백은 그 후에 실행됩니다. 다른 부팅 완료 콜백에 의한 재등록이나 나중에 로딩되는 프로바이더까지 포함해 무조건 최우선이 되는 구조는 아닙니다. 패키지의 등록 프로바이더는 이 예에서는 지연 프로바이더로 만들지 않습니다. 다른 방법으로, 대응표를 바꾸지 않고 컨테이너에서 ReportPolicy::class의 해결 대상을 교체할 수도 있습니다. resolvePolicy()는 매번 컨테이너에 해결을 요청하지만, 실제로 새로운 인스턴스가 되는지는 그 Policy의 바인딩에 달려 있습니다. 사용자나 요청 정보를 생성자에서 가져와 singleton Policy에 보관하는 설계는 피합니다.

인가 전체에 영향을 주는 훅 분리하기

일반적인 Gate 체크에서는 글로벌 Gate::before()가 먼저 실행됩니다. 거기서 null 이외의 값이 반환되면 Policy에 의한 판정은 실행되지 않습니다. 이 그림은 Policy가 발견되고 대응하는 메서드를 호출할 수 있는 경로를 발췌한 것입니다. 이후의 글로벌 after 훅이나 Policy에 대상 메서드가 없는 경우의 Gate 정의로의 폴백은 생략하고 있습니다. 패키지 내 관리자 처리를 구현하기 위해 모든 능력을 허용하는 글로벌 Gate::before()를 등록하지 마세요. 다른 패키지나 이용 앱의 인가까지 허용해 버립니다. Policy 내의 before()라면 그 Policy의 범위이지만, 대응하는 능력의 메서드가 존재하지 않는 경우에는 호출되지 않습니다. 이어지는 메서드에 판단을 맡기는 경우에는 false가 아니라 null을 반환합니다. 또한 이 예의 update()는 nullable이 아닌 Authenticatable을 요구하므로 게스트에서는 Policy 메서드를 실행하지 않습니다. 글로벌 훅 등에 의한 결과 재정의가 없으면 거부됩니다. 공개 열람 등에서 게스트를 허용하는 설계는 nullable 사용자 인수와 명시적인 판정을 별도로 준비합니다.

등록과 판정을 따로 테스트하기

패키지 테스트에서 소개한 Testbench 기반 클래스를 사용하고, getPackageProviders()에서 ReportsServiceProvider::class를 로딩한다고 가정합니다. 다음은 tests/Feature/ReportPolicyTest.php의 예입니다. 사용자에는 Laravel의 범용 인증 모델을 사용하며, DB에 저장하지 않고 판정할 수 있습니다.
forUser()는 공유 Gate의 사용자를 다시 쓰는 것이 아니라, 그 시점의 대응표·능력·콜백을 전달해 별도의 Gate를 생성합니다. 따라서 이미 생성된 사용자별 Gate에는 이후 공유 Gate에 대한 Policy 등록 변경이 반영되지 않습니다. 부팅 시에 등록을 마치고, 사용자별 Gate를 수명이 긴 서비스에 저장하지 않도록 합니다. 이용 앱 측에서는 실제 Guard·사용자 모델로의 판정과 갱신 엔드포인트에 대한 HTTP 테스트도 필요합니다. 위의 테스트만으로는 라우트에 인가가 적용되어 있는지나 DB의 소유자 식별자 저장 형식까지는 검증할 수 없습니다.

업데이트 시 유지할 계약

  • 소유자·소유자 이외·게스트·소유자 미설정의 결과가 바뀌지 않았는가.
  • 공개하고 있는 능력명과 Policy 메서드의 인수가 일치하는가.
  • 이용 앱에 의한 Policy 교체가 계속 유효한가.
  • 자식 모델을 지원하는 경우, 자식 클래스에서 실제로 선택되는 Policy가 올바른가.
  • 앱의 글로벌 훅도 포함해 실제 갱신 요청이 기대대로 허용·거부되는가.
기존 능력을 삭제하거나 기본 허용·거부를 바꾸는 업데이트는 이용 앱의 동작에 영향을 줍니다. 버전 호환성 관리와 함께 인가 변경도 공개 계약으로 취급합니다.

참조한 1차 정보

마지막 수정일 2026년 11월 10일