본문으로 건너뛰기

플러그인 시스템 개요

📝 초안 (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');

관련 문서