본문으로 건너뛰기

플러그인 시스템 개요

📝 초안 (Draft)

이 문서는 검토 중입니다. 내용이 변경될 수 있습니다.

Multi-SaaS Kit의 플러그인 아키텍처를 소개합니다.

개요​

플러그인 시스템은 Core 기능을 확장하여 추가 기능을 제공하는 모듈화된 아키텍처입니다. 각 플러그인은 독립적으로 설치, 활성화, 비활성화할 수 있습니다.

Core vs Extensions vs Plugins​

구분역할예시
Core (Base)필수 기능Permission, Tenant, Auth, Audit
Extensions선택적 Core 확장Guardian, Impersonate
Plugins독립 기능 모듈TwoFactorAuth, PasswordPolicy, Subscription

플러그인의 특징​

  • 독립성: 다른 플러그인 없이 단독 동작 가능 (L0)
  • 수익화: Plugin Store를 통한 판매 가능
  • 버전 관리: 의존성 버전 관리
  • 동적 로딩: 런타임에 활성화/비활성화

플러그인 티어​

플러그인은 4개 티어로 분류됩니다.

티어 구조​

티어설명의존성
L0독립 플러그인Core만 의존
L1복합 플러그인Core + Extensions 의존
Business비즈니스 플러그인수익화 핵심 기능
Enterprise엔터프라이즈대기업 특화 기능

L0 플러그인 (독립)​

Core에만 의존하며 가장 간단한 구조입니다.

플러그인설명
TwoFactorAuth2단계 인증
PasswordPolicyNIST 기반 비밀번호 정책
MenuPermissionSync메뉴-권한 동기화
Honeypot스팸 방지
CodeIntegrity코드 무결성 검사
TSVectorSearchPostgreSQL 전문 검색

L1 플러그인 (복합)​

Extensions에 의존하는 고급 플러그인입니다.

플러그인의존 Extension
GuardianExtensionGuardian
Analytics분석 기반
Notification알림 시스템
AdvancedSecurity보안 확장

Business 플러그인​

비즈니스 기능을 제공합니다.

플러그인설명
I18n다국어 지원
ApiWebhooksAPI Webhook
Subscription구독 결제
PGVectorSearchAI 벡터 검색

Enterprise 플러그인​

대기업 고객을 위한 특화 기능입니다.

플러그인설명
SaasCustomizationSaaS별 커스터마이징
WhiteLabel화이트 라벨링
MultiDatabase멀티 데이터베이스

가격 모델​

플러그인은 3가지 가격 모델을 지원합니다.

// PriceModel Enum
enum PriceModel: string
{
case FREE = 'free'; // 무료
case ONE_TIME = 'one_time'; // 일회성 구매
case SUBSCRIPTION = 'subscription'; // 구독
}
모델설명예시
Free무료 제공PasswordPolicy, Honeypot
One-time일회성 구매기본 기능 플러그인
Subscription월/연 구독Enterprise, Premium 기능

플러그인 구조​

폴더 구조​

packages/plugins/{PluginName}/
├── plugin.json # 플러그인 메타데이터
├── src/
│ ├── {PluginName}Plugin.php # 메인 플러그인 클래스
│ ├── {PluginName}ServiceProvider.php
│ ├── Contracts/ # 인터페이스
│ ├── Services/ # 서비스 로직
│ ├── Config/ # 설정 파일
│ └── ...
├── database/migrations/ # 마이그레이션
├── tests/ # 테스트
└── README.md

plugin.json 스키마​

{
"slug": "password-policy",
"name": "Password Policy",
"description": "NIST compliant password policy",
"version": "1.0.0",
"author": "multi-saas-kit",
"license": "MIT",
"tier": "L0",
"price": {
"model": "free",
"amount": 0
},
"dependencies": {
"core": ">=1.1.0",
"extensions": []
},
"providers": [
"PasswordPolicyServiceProvider"
]
}

BasePlugin 클래스​

모든 플러그인은 BasePlugin 추상 클래스를 상속합니다.

namespace App\Plugins\MyPlugin;

use App\Core\Base\Plugin\BasePlugin;
use App\Core\Base\Plugin\Enums\PluginTier;
use App\Core\Base\Plugin\Enums\PriceModel;

class MyPlugin extends BasePlugin
{
protected string $slug = 'my-plugin';
protected string $name = 'My Plugin';
protected string $description = 'My custom plugin';
protected string $version = '1.0.0';

public function boot(): void
{
// 플러그인 부팅 시 실행
}

public function register(): void
{
// 서비스 등록
}

public function getTier(): PluginTier
{
return PluginTier::L0;
}

public function getPriceModel(): PriceModel
{
return PriceModel::FREE;
}

public function getDependencies(): array
{
return [
'core' => '>=1.1.0',
];
}
}

필수 구현 메서드​

메서드설명
getSlug()플러그인 고유 식별자
getName()플러그인 이름
boot()부팅 시 실행 로직
register()서비스 등록 로직

선택 구현 메서드​

메서드기본값설명
getVersion()'1.0.0'버전
getDescription()''설명
getTier()PluginTier::L0티어
getPriceModel()PriceModel::FREE가격 모델
getDependencies()[]의존성 목록
install()-설치 로직
uninstall()-제거 로직

PluginManager​

플러그인의 생명주기를 관리하는 서비스입니다.

주요 기능​

// 플러그인 매니저 주입
use App\Core\Base\Plugin\Services\PluginManager;

class MyService
{
public function __construct(
private PluginManager $pluginManager
) {}

public function example(): void
{
// 모든 플러그인 조회
$all = $this->pluginManager->all();

// 활성화된 플러그인만
$enabled = $this->pluginManager->enabled();

// 특정 플러그인 조회
$plugin = $this->pluginManager->get('password-policy');

// 플러그인 존재 확인
if ($this->pluginManager->has('password-policy')) {
// ...
}

// 활성화 여부 확인
if ($this->pluginManager->isEnabled('password-policy')) {
// ...
}

// 티어별 조회
$l0Plugins = $this->pluginManager->getByTier('L0');
}
}

생명주기 관리​

// 플러그인 활성화
$pluginManager->enable('my-plugin');

// 플러그인 비활성화
$pluginManager->disable('my-plugin');

// 플러그인 설치
$pluginManager->install('my-plugin');

// 플러그인 제거
$pluginManager->uninstall('my-plugin');

// 의존성 확인
$missing = $pluginManager->checkDependencies('my-plugin');

자동 발견​

// plugins 디렉토리에서 플러그인 자동 발견
$discovered = $pluginManager->discover();
// Returns: ['password-policy', 'two-factor-auth', ...]

설치 및 활성화​

1. 플러그인 설치​

# Plugin Store에서 다운로드
# 또는 packages/plugins/ 디렉토리에 복사

# Composer 오토로드 갱신
composer dump-autoload

2. 플러그인 발견​

// AppServiceProvider에서
public function boot(): void
{
app(PluginManager::class)->discover();
}

3. 플러그인 활성화​

// 코드에서
$pluginManager->enable('password-policy');

// 또는 config/core.php에서
'plugins' => [
'enabled' => [
'password-policy',
'two-factor-auth',
],
],

4. 마이그레이션 실행​

php artisan migrate

테이블 프리픽스 규칙​

플러그인 테이블은 명명 규칙을 따릅니다.

영역프리픽스예시
Corecore_core_plugins
Extensionsext_ext_impersonate_logs
Pluginsplg_{name}_plg_pwd_history

예시: PasswordPolicy 테이블​

Schema::create('plg_pwd_history', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->string('password_hash');
$table->timestamp('created_at');
});

조건부 기능 사용​

플러그인 활성화 여부에 따라 기능을 조건부로 사용합니다.

use App\Core\Base\Plugin\Services\PluginManager;

class AuthService
{
public function __construct(
private PluginManager $pluginManager
) {}

public function authenticate(array $credentials): bool
{
// 기본 인증
$authenticated = Auth::attempt($credentials);

// 2FA 플러그인 활성화 시
if ($authenticated && $this->pluginManager->isEnabled('two-factor-auth')) {
return $this->verify2FA();
}

return $authenticated;
}
}

Blade에서 조건부 표시​

@if(app(PluginManager::class)->isEnabled('analytics'))
<x-analytics-dashboard />
@endif

플러그인 설정​

각 플러그인은 자체 설정 파일을 가집니다.

// packages/plugins/PasswordPolicy/src/Config/password-policy.php
return [
'min_length' => 12,
'max_length' => 128,
'history_count' => 5,
'breached_check' => true,
];

설정 접근​

// 플러그인 설정 접근
$minLength = config('password-policy.min_length');

관련 문서​