Skip to main content
패키지에서 Blade 문법을 제공하려면 템플릿을 PHP로 변환하는 처리와 생성된 PHP를 실행하는 처리를 분리합니다. 현재 설정값을 컴파일 시점에 포함시키면, 캐시된 뷰에서 오래된 값이 계속 표시될 수 있습니다. 이 페이지에서는 Laravel 공식 문서의 13.x와 Framework v13.37.0의 구현을 참조하여 패키지 개발의 기초를 더 깊이 살펴봅니다. 일반적인 템플릿 문법은 Blade를, 뷰의 네임스페이스와 배포는 패키지 뷰의 덮어쓰기와 업데이트를 참조하세요.

등록·컴파일·실행을 구분한다

Blade::directive()에 전달하는 콜백은 표시할 값이 아니라 생성할 PHP 코드 문자열을 반환합니다. 인수인 $expression도 평가된 값이 아니라 템플릿에 작성된 PHP 표현식입니다. view:cache에서도 컴파일이 수행됩니다. 디렉티브의 생성용 콜백에서는 현재 사용자 조회, DB 쓰기, 외부 API 호출 등을 수행하지 않도록 설계합니다.

패키지 고유의 이름으로 등록한다

예로서, 배송 코드 앞에 설정된 라벨을 표시하는 @acmeCourierLabel($code)를 제공합니다. Composer의 PSR-4 설정에서 Acme\Courier\를 src/에 대응시키고, 프로바이더를 자동 검출 또는 수동으로 등록하는 것을 전제로 합니다.
src/CourierServiceProvider.php
이 예에서는 courier.label은 문자열, courier.enabled는 boolean이라는 설정 계약을 둡니다. 설정 파일의 배포와 병합은 패키지 설정 병합과 캐시를 참조하세요. 등록은 일반적인 프로바이더의 boot()에서 수행하며, runningInConsole() 조건으로 감싸지 않습니다. HTTP에서의 렌더링과 Artisan의 view:cache 양쪽에서 같은 확장이 필요합니다. Blade 확장만 등록하는 프로바이더를, 다른 서비스가 해석될 때까지 기동하지 않는 지연 프로바이더로 만드는 것도 피합니다.

인수는 값이 아니라 표현식으로 받는다

이 템플릿에서 콜백이 받는 것은 문자열 $code입니다. 생성되는 PHP는 다음과 같은 형태가 됩니다.
config()와 $code가 평가되는 것은 이 PHP를 실행하는 시점입니다. 콜백 자체가 config()를 읽어 고정된 문자열을 반환하는 구현과는 다릅니다. 확인한 callCustomDirective()는 바깥쪽 괄호를 제거하고 표현식을 trim하여 콜백에 전달합니다. 인수를 PHP 값으로 변환하거나 개별 인수로 분할하지는 않습니다. 이 예는 필수 표현식 하나를 전달하는 문법으로 공개합니다. 여러 인수를 다루는 경우, 단순히 쉼표로 explode()하지 마세요. 배열, 메서드 호출, 문자열 리터럴 안에도 쉼표가 포함됩니다. 속성이나 복잡한 HTML을 다루고 싶다면 Blade 컴포넌트로 제공하는 편이 책임을 분리하기 쉽습니다.
템플릿의 표현식은 신뢰할 수 있는 개발자가 작성하는 PHP입니다. 사용자 입력을 템플릿 소스로 조립하지 마세요. 또한 커스텀 디렉티브의 echo에는 일반적인 {{ }}의 이스케이프가 자동으로 적용되지 않습니다. 이 예에서는 생성하는 PHP가 명시적으로 e()를 호출합니다.

이름 충돌도 호환성 문제가 된다

directive()는 이름을 키로 하여 핸들러를 배열에 저장합니다. 같은 이름이면 이전 등록을 덮어쓰고, compileStatement()는 내장 변환 메서드보다 커스텀 디렉티브를 먼저 선택합니다. 공식 테스트에도 커스텀 등록으로 foreach를 덮어쓰는 케이스가 있습니다. label이나 enabled 같은 일반적인 이름이나 내장 이름을 피하고, 패키지 고유의 접두사를 붙입니다. 사용자가 템플릿에서 사용하는 이름과 인수는 공개 API로 취급하며, 변경 시에는 마이그레이션 절차를 제공합니다.

조건 분기는 Blade::if로 실행 시점에 판정한다

위의 프로바이더에서 등록한 조건은 다음과 같이 사용할 수 있습니다.
Blade::if()는 조건 콜백을 저장한 뒤, 시작·unless·else·종료용 디렉티브를 등록합니다. 이 예의 시작 부분은 다음 PHP로 변환됩니다.
설정을 확인하는 조건 콜백은 check()에서 실행 시점에 호출됩니다. 컴파일 시점에 true·false 결과를 고정하는 처리가 아닙니다. 컴파일된 뷰를 사용하는 HTTP 프로세스에서도 조건 콜백의 등록이 필요합니다. 이 문법은 표시 전환일 뿐, 배송 작업에 대한 인가가 아닙니다. 접근 제어는 라우트나 작업 측에서도 수행합니다.

패키지 업데이트로 뷰가 자동 재생성된다고는 할 수 없다

확인한 Compiler::isExpired()는 캐시의 존재 여부와, 설정에 따라 원본 뷰와 컴파일된 파일의 갱신 시각을 조사합니다. 프로바이더에 작성된 디렉티브의 변경을 의존 파일로 추적하는 처리가 아닙니다. 공식 문서도 디렉티브 로직을 변경한 후에는 view:clear로 캐시를 삭제하도록 안내합니다. 사용하는 애플리케이션의 배포 공정에서, 업데이트한 패키지와 사용자의 뷰를 맞춘 후에 실행합니다.
view:cache는 프로덕션에서 사전 컴파일하는 경우에 실행합니다. 패키지의 boot()에서 매번 캐시를 삭제하거나, 설치 시 사용하는 애플리케이션의 배포 공정을 임의로 변경하지 마세요. 설정 캐시 갱신이나 상주 프로세스 재로드도 사용 환경의 일반적인 배포 절차를 따릅니다.

컴파일 결과와 렌더링 결과를 따로 검증한다

먼저 위 프로바이더가 등록된 테스트용 Laravel 애플리케이션에서, 생성되는 PHP를 검증합니다. 다음은 Tests\TestCase를 상속하는 Feature 테스트에 추가하는 메서드입니다.
이 테스트로 PHP를 생성하는 계약은 확인할 수 있지만, 실행 시점의 이스케이프나 조건 분기까지는 검증할 수 없습니다. 실제 패키지에는 뷰 렌더링과 업데이트 시의 검증도 추가합니다.

관련 페이지

패키지 뷰의 덮어쓰기와 업데이트

네임스페이스의 검색 순서와, 배포된 템플릿을 유지보수하는 방법을 확인합니다.

패키지 캐시와 optimize 통합

자체 캐시의 생성·삭제를 배포 공정에 통합하는 방법을 확인합니다.

참고한 1차 자료

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