# 플러그인 확장하기
Clinic-OS의 플러그인은 **본관(코어)을 건드리지 않고 기능을 확장**하는 방법입니다.
마치 아파트 옆에 컨테이너 별채를 붙이는 것처럼, 본관은 그대로 두고 원하는 기능을 추가할 수 있습니다.
---
## 왜 플러그인을 사용하나요?
### 1. 안전한 커스터마이징
```
┌─────────────────────────────────────────────────┐
│ src/pages/index.astro (코어) │ ← 수정하면 업데이트 시 충돌!
└─────────────────────────────────────────────────┘
↓ 업데이트 시 덮어쓰기
↓ 내 수정 사항 사라짐
┌─────────────────────────────────────────────────┐
│ src/plugins/local/custom-homepage/ (플러그인) │ ← 여기서 수정하면 안전!
└─────────────────────────────────────────────────┘
↓ 업데이트와 무관
↓ 내 코드 그대로 유지
```
**핵심 원리**: 코어 파일은 업데이트 시 새 버전으로 교체되지만, 플러그인 폴더는 건드리지 않습니다.
### 2. 쉬운 on/off 전환
문제가 생겼을 때:
- **코어 수정**: 어디서 뭘 잘못 건드렸는지 찾기 어려움
- **플러그인**: 관리자 화면에서 토글 하나로 비활성화
### 3. 독립적인 개발
각 플러그인은 독립된 폴더에서 관리됩니다:
- VIP 관리 기능 → `src/plugins/local/vip-management/`
- 리뷰 수집 기능 → `src/plugins/local/review-request/`
- 커스텀 홈페이지 → `src/plugins/local/custom-homepage/`
하나의 플러그인에 문제가 생겨도 다른 플러그인과 코어는 영향 없음!
---
## 플러그인과 스킨의 차이
둘 다 에이전트가 다루는 재사용 단위지만 목적이 다릅니다.
- **플러그인**: 기능, 경로, API, 관리자 탭을 확장
- **스킨**: 퍼블릭 페이지의 분위기, 상세 템플릿, Hero override를 조정
즉, 새 기능이 필요하면 플러그인, 디자인 시스템 단위로 퍼블릭을 바꾸고 싶으면 스킨 경로를 쓰는 편이 맞습니다.
스킨 쪽은 [스킨 라이브러리](/skins) 와 [에이전트 드리븐 스킨 작업](/guide#vibe-skins)에서 따로 다룹니다.
---
## 플러그인 종류
### 코어 플러그인 (Core)
Clinic-OS 팀에서 제공하는 공식 플러그인. 기본 설치되어 있거나 스토어에서 무료로 설치 가능.
| 플러그인 | 설명 | 기본 설치 |
|---------|------|----------|
| 커스텀 홈페이지 | 메인 페이지 자유 커스터마이징 | O |
### 검증된 플러그인 (Verified)
커뮤니티 개발자가 만들고, Clinic-OS 팀에서 검증한 플러그인.
### 커뮤니티 플러그인 (Community)
커뮤니티 개발자가 자유롭게 공유하는 플러그인.
---
## 플러그인 구조
플러그인 폴더는 이런 구조로 되어 있습니다:
```
src/plugins/local/my-plugin/
├── manifest.json ← 플러그인 정보 (필수)
├── README.md ← 사용 설명서
├── pages/ ← 페이지 컴포넌트
│ └── index.astro ← 홈페이지 오버라이드
├── components/ ← 재사용 컴포넌트
├── lib/ ← 헬퍼 함수
│ └── hooks.ts ← 이벤트 핸들러
└── migration.sql ← DB 마이그레이션 (선택)
```
### manifest.json 예시
```json
{
"id": "custom-homepage",
"name": "커스텀 홈페이지",
"description": "메인 홈페이지를 자유롭게 커스터마이징",
"version": "1.0.0",
"author": "Clinic-OS",
"category": "customization",
"documentation": {
"summary": "코어 코드를 건드리지 않고...",
"features": ["홈페이지 오버라이드", "..."],
"howToEdit": "pages/index.astro 수정"
},
"overrides": [
{ "path": "/", "file": "pages/index.astro", "priority": 10 }
]
}
```
---
## 플러그인 관리
### 설치된 플러그인 확인
관리자 > 기능 허브에서 설치된 모든 플러그인을 확인할 수 있습니다.
### 플러그인 활성화/비활성화
각 플러그인 상세 페이지에서 토글 버튼으로 on/off 가능.
(super_admin 권한 필요)
### 새 플러그인 설치
AI에게 요청하세요:
`로컬 설치본을 열고 /admin/plugins/store 에서 VIP 관리 플러그인을 설치해줘`
또는 스토어에서 원하는 플러그인을 찾아 설치를 요청:
`이 플러그인을 로컬 관리자 스토어에서 설치해줘: https://clinic-os-hq.pages.dev/plugins/vip-management`
### 새 플러그인 생성
사람이 구조를 외우기보다 에이전트에게 이렇게 요청하는 편이 맞습니다.
```
vip-management 플러그인 뼈대를 만들어줘.
관리 탭과 API도 같이 필요해.
```
에이전트는 내부적으로 `npm run plugin:create` 를 사용해 구조를 만들고, 그 다음 세부 구현을 이어갑니다.
### 플러그인 삭제
```
VIP 관리 플러그인을 삭제해줘
```
---
## 커스텀 홈페이지 사용법
### 왜 홈페이지가 플러그인인가요?
각 한의원마다 홈페이지 디자인이 다릅니다:
- A 한의원: 사진 갤러리 중심
- B 한의원: 의료진 소개 중심
- C 한의원: 프로모션 배너 중심
**코어에 고정하면**: 모든 한의원이 같은 홈페이지를 써야 함
**플러그인이면**: 각자 원하는 대로 커스터마이징 가능
### 홈페이지 수정하기
1. 파일 열기:
`src/plugins/local/custom-homepage/pages/index.astro`
2. 에이전트에게 요청:
```
홈페이지에 진료 시간 안내 섹션을 추가해줘.
월-금 09:00-18:00, 토 09:00-13:00, 일 휴진
```
3. 결과 확인 후 배포:
```
수정 내용 확인했어. 배포해줘
```
### 원본 홈페이지로 돌아가기
1. 관리자 > 기능 허브 > 커스텀 홈페이지
2. 토글 버튼 클릭 → 비활성화
3. 코어의 기본 홈페이지가 표시됨
---
## 페이지 오버라이드 시스템
### 작동 원리
```
사용자가 "/" 요청
↓
플러그인에 "/" 오버라이드가 있나?
↓
YES → 플러그인 페이지 렌더링
NO → 코어 페이지 렌더링
```
### 우선순위
여러 플러그인이 같은 경로를 오버라이드하면 `priority` 값이 높은 것이 적용됩니다.
```json
// manifest.json
{
"overrides": [
{ "path": "/", "file": "pages/index.astro", "priority": 10 }
]
}
```
---
## 훅(Hook) 시스템
플러그인은 코어의 이벤트에 반응할 수 있습니다.
### 사용 가능한 훅
| 이벤트 | 발생 시점 | 활용 예 |
|--------|----------|--------|
| onPaymentCompleted | 결제 완료 시 | VIP 포인트 적립 |
| onPatientCreated | 환자 등록 시 | 웰컴 메시지 발송 |
| onVisitCheckin | 내원 체크인 시 | 리뷰 요청 예약 |
| onReservationCreated | 예약 생성 시 | 알림 발송 |
### 훅 핸들러 예시
```typescript
// src/plugins/local/vip-management/lib/hooks.ts
export async function addPoints(context: HookContext) {
const { db, data } = context;
const { patientId, amount } = data;
// VIP 포인트 적립 로직
await db.prepare(`
INSERT INTO custom_vip_point_history (patient_id, amount, type)
VALUES (?, ?, 'earn')
`).bind(patientId, Math.floor(amount * 0.01)).run();
}
```
---
## 플러그인 개발 규칙
### 테이블 명명 규칙
```sql
-- 올바른 예: custom_ 접두사 사용
CREATE TABLE custom_vip_members (...);
CREATE TABLE custom_reviews (...);
-- 잘못된 예: 접두사 없음
CREATE TABLE vip_members (...);
ALTER TABLE patients ADD COLUMN ...; -- 코어 테이블 수정 금지!
```
### API 경로 규칙
```
/api/hub/{plugin-id}/... ← 플러그인 전용 경로
/api/patients/... ← 코어 API 경로 (사용 금지)
```
### 페이지 경로 규칙
```
/admin/hub/{plugin-id}/... ← 플러그인 관리 페이지
오버라이드 시스템 사용 ← 퍼블릭 페이지 교체
코어 페이지 직접 수정 금지
```
---
## 실전 예제: 리뷰 요청 플러그인
고객이 시술을 받고 나면 자동으로 리뷰 요청 문자를 보내는 플러그인을 만들어봅시다.
### 에이전트에게 한 번에 요청
AI에게 이렇게 요청하면 됩니다:
```
리뷰 요청 플러그인을 만들어줘.
기능:
- 환자가 체크인하면 24시간 후에 리뷰 요청 문자 발송
- custom_review_requests 테이블에 예약 정보 저장
- 관리자 페이지에서 발송 내역 확인 가능
훅:
- onVisitCheckin 이벤트에 연결
```
AI가 자동으로:
1. `src/plugins/review-request/` 폴더 생성
2. `manifest.json` 작성
3. 훅 핸들러 코드 작성
4. 마이그레이션 SQL 생성
5. `installed.json` 업데이트
### 결과물 구조
```
src/plugins/review-request/
├── manifest.json ← 플러그인 메타데이터
├── lib/
│ └── hooks.ts ← onVisitCheckin 핸들러
├── pages/
│ └── admin.astro ← 발송 내역 페이지
└── migration.sql ← 테이블 생성 SQL
```
---
## 플러그인 스토어
### HQ 플러그인 스토어
[clinic-os-hq.pages.dev/plugins](https://clinic-os-hq.pages.dev/plugins)에서:
- 공개된 플러그인 검색
- 플러그인 상세 정보 확인
- 설치 방법 안내
스토어에서 마음에 드는 플러그인을 찾으면:
```
이 플러그인 설치해줘: [플러그인 URL]
```
### 내 플러그인 공유하기
AI에게 요청하세요:
```
이 플러그인을 HQ 스토어에 제출해줘
```
AI가 자동으로:
1. 개발자 등록 상태 확인
2. 플러그인 규약 검증
3. HQ에 제출
개발자 등록이 안 되어 있다면 [개발자 신청](/plugins/developer-apply) 페이지에서 먼저 등록하세요.
---
## 요약
| 항목 | 코어 수정 | 플러그인 |
|-----|----------|---------|
| 업데이트 영향 | 덮어쓰기 위험 | 안전 |
| 롤백 | 어려움 | 토글로 간편 |
| 다른 기능 영향 | 있을 수 있음 | 격리됨 |
| 권장 상황 | 불가피할 때만 | 모든 커스터마이징 |
**기억하세요**: 뭔가 커스터마이징하고 싶다면, 먼저 플러그인으로 할 수 있는지 생각하세요!
---
## 관련 콘텐츠
- 🎯 **직원 투어**: 관리자 패널에서 **플러그인** 투어를 시작하세요