확장 모델
필요한 contribution을 골라 App에 선언하고, Core가 발견해 사용할 수 있게 만드는 과정을 설명합니다.
확장 모델
필요한 기능부터 고르기
플랫폼 기능을 추가하려면 App의 contribution 디렉터리에 해당 SDK 인터페이스를 구현합니다. Core는 manifest를 만들 때 구현 클래스를 찾고, 각 런타임에 선언을 전달합니다.
| 추가할 기능 | 구현 문서 |
|---|---|
| Resource와 권한 | Resource 만들기 |
| App 메뉴 목적지 | App Menu 목적지 추가 |
| 설정 화면 | 설정 페이지 추가 |
| Dashboard·Slot 위젯 | Dashboard Widget 추가, Slot Widget 추가 |
| 다른 App에서 레코드 참조 | Resource Reference |
| 프로세스·결재·서명 | 업무 프로세스, 전자 결재, 전자 서명 |
정확한 인터페이스와 반환 타입, descriptor 인자는 Contribution 계약에서 찾습니다. 기능 하나를 구현하기 전에 모든 contribution 종류를 공부할 필요는 없습니다.
선언이 전달되는 과정
Manifest 위치 선언 → SDK 인터페이스 구현 클래스 → 생성된 contribution 색인 → 런타임 catalog → 테넌트·행위자 검사 → App 동작 호출
Manifest는 namespace와 디렉터리를 한 쌍으로 선언합니다.
아래는 Workshop 생성기가 만드는 src/WorkshopAppManifest.php의 메서드 예시입니다.
클래스 기준 상대 경로를 쓰므로 Core의 checkout 위치에 의존하지 않습니다.
public function contributionLocations(): array
{
return [
['namespace' => 'Amuzcorp\Nexia\Workshop\Contribution', 'directory' => __DIR__.'/Contribution'],
['namespace' => 'Amuzcorp\Nexia\Workshop\Descriptors', 'directory' => __DIR__.'/Descriptors'],
];
}클래스에는 implements로 인터페이스를 명시해야 합니다. 메서드를 제공하는
trait만 붙여서는 발견되지 않습니다. 선언한 디렉터리의 하위 경로도 검색합니다.
선언 메서드는 정적 메타데이터를 반환하며 테넌트 데이터 조회, 현재 행위자 접근,
쓰기를 수행하지 않습니다. 실행 시 필요한 컨텍스트는 Core가 해당 계약에 따라
provider를 호출할 때 전달합니다.
Contribution 클래스를 바꾼 뒤에는 런타임 manifest를 갱신합니다.
task artisan -- nexia-runtime:refresh-runtime-caches
task artisan -- nexia-apps:doctor-package-app workshopDoctor에서 기대한 인터페이스가 발견되고 실패가 없어야 합니다. 이는 연결 확인이며 사용자 권한을 증명하지는 않습니다. 오래 실행 중인 프로세스의 재시작이 필요할 수 있으므로 Contribution 발견 문제 해결을 참고하세요.
같은 Resource의 선언 모으기
생성된 Resource Module에는 Resource 하나의 식별자, 모델 연결, 권한 모델, permission, 내비게이션, 공개 descriptor가 함께 있습니다. 모든 App 기능을 담는 거대한 등록부로 만들지 않습니다. Resource에 속하지 않는 기능은 사용하는 런타임별로 별도 클래스에 둘 수 있습니다.
Contributor는 발견 대상 클래스, descriptor는 그 클래스가 공개하는 타입 있는
값입니다. AppDescriptorContribution::appDescriptors()는 AppDescriptorSet을
반환하고 호스트는 지원하는 descriptor 종류를 선택합니다. 일부 인터페이스는
실행 시 호출할 App provider도 함께 제공합니다.
Resource catalog 항목은 Resource 유형의 정의입니다. 테넌트가 편집하는 기준 정보 레코드는 모델과 API에 둡니다. Catalog key는 permission·번역·설정에서 참조하므로 공개 전에 정하고, 표시 이름을 바꾸듯 변경하지 않습니다.
결과를 누가 소유하는지 결정하기
| 종류 | 만들어지는 결과 | 다음 릴리스의 영향 |
|---|---|---|
| Catalog | 코드 소유 기능 정의 | 동기화·캐시 갱신 후 정의 변경 |
| Descriptor | 안정된 식별자를 가진 런타임 메타데이터 | 이후 해석에 반영하며 기존 참조와의 호환성 필요 |
| Role preset | 관리자가 권한을 선택할 때 쓸 출발점 | 이후 선택에만 반영. 기존 grant는 변경하지 않음 |
| Copyable template | 명시적 적용으로 만든 테넌트 소유 콘텐츠 | 이후 복사본에만 반영. 기존 편집 내용은 유지 |
| 필수 설치 데이터 | App 동작에 필요한 최소 테넌트 레코드 | 명시적인 안전한 마이그레이션이나 지원되는 복구 경로로 변경 |
Process Template descriptor는 편집기의 시작 구성을 제공합니다. 저장·게시한 프로세스는 테넌트 정의가 됩니다. 레코드를 만들고 적용 이력을 남기는 copyable template과는 적용 시점과 방식이 다릅니다.
각 절차는 Role Preset, Copyable Template, 필수 설치 콘텐츠에서 확인하세요. 어느 방식도 그 자체로 사용자에게 권한을 부여하지 않습니다.
Descriptor 수명과 버전
Descriptor 버전은 App 패키지 버전과 별개입니다. 실행에 필요한 식별자·버전의 저장 방식은 각 런타임이 정합니다. 모든 descriptor가 같은 방식으로 버전을 고정한다고 가정하면 안 됩니다.
| 상태 | 새 선택 | 기존 작업 |
|---|---|---|
Active | 런타임 조건을 통과하면 선택 가능 | 해석 가능 |
Deprecated | 새 작성 대상에서 제외 | 해당 런타임이 지원하는 기존 참조는 계속 해석 가능 |
Removed | 사용 불가 | 해석 거부 |
기능을 종료할 때는 먼저 deprecated로 전환하고, 기존 참조가 끝나거나 명시적으로 이관된 뒤 제거합니다. 소스를 먼저 지우면 실행 중인 작업이 중단될 수 있습니다. Process 외부 태스크·게시 정의·결재 binding·template 복사본의 저장 규칙은 서로 다르므로 업무 프로세스 계약, 전자 결재 계약에서 해당 동작을 확인하세요.
Resource lifecycle event는 상위 Resource descriptor에 속하며 payload 버전인
정수 schemaVersion을 가집니다. 독립 공개 통합 이벤트는 별도의 선언을 사용합니다.
어느 버전도 Composer 패키지 태그를 대신하지 않습니다.
App 릴리스하기에서 함께 검토할 항목을 확인하세요.
발견과 접근 권한 구분하기
| 확인 단계 | 질문 |
|---|---|
| 발견 | 필요한 인터페이스로 클래스가 색인되었는가? |
| App 가용성 | 이 테넌트에서 소유 App이 operational 상태인가? |
| 권한 | 이 기능에 권한이 필요한가? 행위자가 보유했는가? |
| 수명·호환성 | 해당 런타임이 이번 동작에 이 descriptor를 사용할 수 있는가? |
권한이 선택 사항인 메뉴와 이미 실행 중인 프로세스 태스크는 조건이 다릅니다. 최종 App handler는 입력·레코드 권한·업무 상태를 계속 검사해야 합니다. 기능이 보이지 않으면 Contribution 발견 문제 해결에서 이 단계들을 나누어 확인하세요.