이 글은 Claude Opus 4.5 을 이용해 초안이 작성되었으며, 이후 퇴고를 거쳤습니다.
예상 소요 시간 : 1시간 30분
난이도 : ⭐⭐⭐⭐
사전 요구사항 : Part 1-4 완료, Git/GitHub 기본 지식
Claude Code 버전 : 2.1.x
1. Plugin 구조 이해#
1.1 Plugin 디렉토리 구조#
💡 주의 : 2026년 기준, marketplace.json에서 Skills를 로드하려면 skills 필드가 필수 입니다. 이 필드가 없으면 Skills가 로드되지 않습니다.
my-plugin/
├── .claude-plugin/
│ └── plugin.json # 필수: 플러그인 메타데이터
├── skills/ # 선택: Skills
│ └── my-skill/
│ └── SKILL.md
├── commands/ # 선택: Slash Commands
│ └── my-command.md
├── agents/ # 선택: Subagents
│ └── my-agent.md
├── hooks/ # 선택: Hooks 설정
│ └── hooks.json
├── .mcp.json # 선택: MCP 서버 설정
└── README.md # 권장: 문서화
1.2 plugin.json 필수 필드#
{
"name" : "my-awesome-plugin" ,
"version" : "1.0.0" ,
"description" : "플러그인 설명" ,
"author" : "Your Name" ,
"homepage" : "https://github.com/you/my-plugin"
}
1.3 plugin.json 전체 스키마#
{
"name" : "my-awesome-plugin" ,
"version" : "1.0.0" ,
"description" : "이 플러그인이 무엇을 하는지 간단히 설명" ,
"author" : "Your Name <you@example.com>" ,
"homepage" : "https://github.com/you/my-plugin" ,
"repository" : {
"type" : "git" ,
"url" : "https://github.com/you/my-plugin.git"
},
"license" : "MIT" ,
"keywords" : [ "go" , "testing" , "conventions" ],
"engines" : {
"claude-code" : ">=2.0.0"
},
"dependencies" : {
"plugins" : [ "other-plugin@marketplace" ]
}
}
2. 첫 번째 Plugin 만들기#
2.1 시나리오#
Java/Kotlin 개발팀을 위한 Plugin을 만들어봅시다. 다음을 포함합니다:
코딩 컨벤션 Skill
테스트 작성 Skill
커밋 메시지 형식 Command
2.2 디렉토리 구조 생성#
mkdir -p jvm-team-plugin/.claude-plugin
mkdir -p jvm-team-plugin/skills/kotlin-conventions
mkdir -p jvm-team-plugin/skills/test-patterns
mkdir -p jvm-team-plugin/commands
2.3 plugin.json 작성#
jvm-team-plugin/.claude-plugin/plugin.json :
{
"name" : "jvm-team-plugin" ,
"version" : "1.0.0" ,
"description" : "JVM(Java/Kotlin) 개발팀을 위한 코딩 컨벤션, 테스트 패턴, Git 워크플로우" ,
"author" : "Your Team" ,
"homepage" : "https://github.com/your-org/jvm-team-plugin" ,
"license" : "MIT" ,
"keywords" : [ "java" , "kotlin" , "spring-boot" , "testing" , "conventions" ]
}
2.4 Skills 작성#
skills/kotlin-conventions/SKILL.md :
---
name: kotlin-conventions
description: Kotlin 코딩 컨벤션. Kotlin 코드 작성, 리뷰 시 자동 적용.
"Kotlin", "코틀린", "kt 파일" 작업 시 활성화.
---
# Kotlin Coding Conventions
## 파일 구조
```kotlin
// 1. 패키지 선언
package com.example.feature
// 2. Import (알파벳 순, 와일드카드 금지)
import com.example.other.SomeClass
import org.springframework.stereotype.Service
// 3. 클래스/함수 정의
네이밍 규칙#
대상
규칙
예시
클래스
PascalCase
UserService, PaymentGateway
함수
camelCase, 동사로 시작
createUser, findById
변수
camelCase
userId, isActive
상수
SCREAMING_SNAKE_CASE
MAX_RETRY_COUNT
패키지
lowercase
com.example.userservice
함수 작성 규칙#
// ✅ 좋은 예: 단일 표현식 함수
fun isValid ( email : String ): Boolean = email . contains ( "@" )
// ✅ 좋은 예: 명확한 반환 타입
fun findUser ( id : Long ): User ? {
return userRepository . findById ( id ). orElse ( null )
}
// ❌ 나쁜 예: 불필요한 Unit 반환
fun saveUser ( user : User ): Unit { // Unit 생략
userRepository . save ( user )
}
Null 처리#
// ✅ Safe call + Elvis
val name = user ?. name ?: "Unknown"
// ✅ let으로 null 체크
user ?. let {
sendEmail ( it . email )
}
// ❌ 강제 unwrap 금지 (테스트 제외)
val name = user !! . name // 프로덕션 코드에서 금지
Data Class 규칙#
// ✅ DTO는 data class
data class UserResponse (
val id : Long ,
val name : String ,
val email : String
)
// ✅ Entity는 일반 class (JPA 프록시 호환)
@Entity
class User (
@Id @GeneratedValue
val id : Long = 0 ,
var name : String ,
var email : String
)
Extension Function#
// 유틸리티성 확장 함수는 Extensions.kt에 모아두기
// com/example/common/Extensions.kt
fun String . toSlug (): String =
this . lowercase (). replace ( " " , "-" )
fun < T > List < T >. secondOrNull (): T ? =
this . getOrNull ( 1 )
**skills/test-patterns/SKILL.md**:
```markdown
---
name: test-patterns
description: JVM 테스트 작성 패턴. JUnit 5, MockK 기반.
"테스트 작성", "단위 테스트", "통합 테스트" 요청 시 활성화.
---
# JVM Test Patterns
## 테스트 클래스 구조
```kotlin
@ExtendWith(MockKExtension::class)
internal class UserServiceTest {
@MockK
private lateinit var userRepository: UserRepository
@MockK
private lateinit var eventPublisher: EventPublisher
@InjectMockKs
private lateinit var sut: UserService // System Under Test
@BeforeEach
fun setUp() {
// 공통 Mock 설정
}
@Nested
@DisplayName("createUser")
inner class CreateUser {
@Test
fun `should create user when valid input`() {
// Given
val request = CreateUserRequest(name = "John", email = "john@test.com")
val savedUser = User(id = 1L, name = "John", email = "john@test.com")
every { userRepository.save(any()) } returns savedUser
every { eventPublisher.publish(any()) } just Runs
// When
val result = sut.createUser(request)
// Then
assertThat(result.id).isEqualTo(1L)
verify(exactly = 1) { userRepository.save(any()) }
verify(exactly = 1) { eventPublisher.publish(match { it is UserCreatedEvent }) }
}
@Test
fun `should throw exception when email already exists`() {
// Given
val request = CreateUserRequest(name = "John", email = "existing@test.com")
every { userRepository.existsByEmail(request.email) } returns true
// When & Then
assertThrows<DuplicateEmailException> {
sut.createUser(request)
}
}
}
}
네이밍 규칙#
// 백틱 사용, should_결과_when_조건 패턴
` should return user when valid id provided `
` should throw exception when user not found `
` should send email when user created `
MockK 사용법#
// Stubbing
every { repository . findById ( 1L ) } returns user
every { repository . findById ( any ()) } returns null
every { service . process ( any ()) } throws SomeException ()
// Relaxed mock (모든 메서드 기본값 반환)
@MockK ( relaxed = true )
private lateinit var logger : Logger
// Verification
verify { repository . save ( user ) }
verify ( exactly = 2 ) { service . notify ( any ()) }
verify ( ordering = Ordering . SEQUENCE ) {
service . start ()
service . process ()
service . end ()
}
통합 테스트#
@SpringBootTest
@AutoConfigureMockMvc
@Transactional
class UserApiIntegrationTest {
@Autowired
private lateinit var mockMvc : MockMvc
@Autowired
private lateinit var userRepository : UserRepository
@Test
fun `POST users should create user and return 201` () {
// Given
val request = """
{
"name": "John",
"email": "john@test.com"
}
""" . trimIndent ()
// When & Then
mockMvc . post ( "/api/v1/users" ) {
contentType = MediaType . APPLICATION_JSON
content = request
}. andExpect {
status { isCreated () }
jsonPath ( "$.data.name" ) { value ( "John" ) }
}
// DB 검증
val saved = userRepository . findByEmail ( "john@test.com" )
assertThat ( saved ). isNotNull
}
}
테스트 데이터 빌더#
// test/fixtures/UserFixtures.kt
object UserFixtures {
fun aUser (
id : Long = 1L ,
name : String = "Test User" ,
email : String = "test@example.com"
) = User ( id = id , name = name , email = email )
fun aCreateUserRequest (
name : String = "Test User" ,
email : String = "test@example.com"
) = CreateUserRequest ( name = name , email = email )
}
// 사용
val user = UserFixtures . aUser ( name = "Custom Name" )
### 2.5 Command 작성
**commands/conventional-commit.md**:
```markdown
---
name: conventional-commit
description: Conventional Commits 형식으로 커밋 메시지를 생성합니다.
---
# Conventional Commit Generator
현재 staged 변경사항을 분석하여 Conventional Commits 형식의 커밋 메시지를 생성합니다.
## 커밋 타입
| 타입 | 설명 | 예시 |
|------|------|------|
| feat | 새 기능 | `feat: add user registration` |
| fix | 버그 수정 | `fix: resolve null pointer in UserService` |
| refactor | 리팩토링 | `refactor: extract validation logic` |
| test | 테스트 | `test: add unit tests for PaymentService` |
| docs | 문서 | `docs: update API documentation` |
| chore | 빌드/설정 | `chore: update gradle dependencies` |
| perf | 성능 | `perf: optimize database query` |
## 형식
():
```
작업 순서#
git diff --staged 실행하여 변경사항 확인
변경 내용 분석
적절한 타입과 scope 선택
명확한 subject 작성 (50자 이내, 명령형)
필요시 body에 상세 설명 추가
feat(user): add email verification flow
- Add EmailVerificationService
- Create verification token entity
- Implement verification endpoint
Closes #123
### 2.6 README.md 작성
```markdown
# JVM Team Plugin
Java/Kotlin 개발팀을 위한 Claude Code 플러그인입니다.
## 설치
```bash
/plugin marketplace add your-org/jvm-team-plugin
/plugin install jvm-team-plugin@your-org
포함된 기능#
Skills (자동 활성화)#
Skill
설명
트리거
kotlin-conventions
Kotlin 코딩 컨벤션
Kotlin 코드 작성 시
test-patterns
테스트 작성 패턴
테스트 작성 요청 시
Commands (수동 호출)#
Command
설명
/conventional-commit
커밋 메시지 생성
사용 예시#
# Kotlin 코드 작성 시 자동으로 컨벤션 적용
"UserService 클래스 만들어줘"
# 테스트 작성
"UserService에 대한 단위 테스트 작성해줘"
# 커밋 메시지 생성
/conventional-commit
이슈와 PR을 환영합니다!
라이선스#
MIT
---
## 3. Plugin을 Marketplace로 배포하기
### 3.1 marketplace.json 작성
Marketplace는 여러 Plugin을 묶어서 배포하는 카탈로그입니다.
**저장소 구조**:
my-marketplace/
├── .claude-plugin/
│ └── marketplace.json # Marketplace 정의
├── plugins/
│ ├── jvm-team-plugin/ # Plugin 1
│ │ ├── .claude-plugin/
│ │ │ └── plugin.json
│ │ ├── skills/
│ │ └── commands/
│ └── go-team-plugin/ # Plugin 2
│ ├── .claude-plugin/
│ │ └── plugin.json
│ └── skills/
└── README.md
**.claude-plugin/marketplace.json**:
```json
{
"name": "my-org-marketplace",
"version": "1.0.0",
"description": "우리 조직의 Claude Code 플러그인 모음",
"plugins": [
{
"name": "jvm-team-plugin",
"path": "plugins/jvm-team-plugin",
"description": "Java/Kotlin 개발팀용 플러그인",
"skills": ["./skills"]
},
{
"name": "go-team-plugin",
"path": "plugins/go-team-plugin",
"description": "Go 개발팀용 플러그인",
"skills": ["./skills"]
}
]
}
⚠️ 중요 : skills 필드를 반드시 포함해야 합니다. 이 필드가 Claude Code에게 SKILL.md 파일이 있는 디렉토리를 알려줍니다.
3.2 GitHub Repository 구성#
# 1. GitHub repo 생성
# https://github.com/your-org/claude-plugins
# 2. 로컬에서 초기화
git init my-marketplace
cd my-marketplace
# 3. 파일 구조 생성 (위의 구조 참조)
# 4. 커밋 및 푸시
git add .
git commit -m "chore: initial marketplace setup"
git remote add origin https://github.com/your-org/claude-plugins.git
git push -u origin main
3.3 배포 후 설치 테스트#
# Claude Code에서
# 1. Marketplace 추가
/plugin marketplace add your-org/claude-plugins
# 2. 플러그인 목록 확인
/plugin
# → Discover 탭에서 jvm-team-plugin, go-team-plugin 확인
# 3. 설치
/plugin install jvm-team-plugin@my-org-marketplace
# 4. 동작 확인
"Kotlin으로 UserService 만들어줘"
# → kotlin-conventions Skill이 자동 활성화되어야 함
4. 실전: Java/Go 개발팀을 위한 Custom Marketplace 구축#
4.1 Marketplace 전체 구조#
company-claude-plugins/
├── .claude-plugin/
│ └── marketplace.json
├── plugins/
│ ├── jvm-standards/
│ │ ├── .claude-plugin/
│ │ │ └── plugin.json
│ │ ├── skills/
│ │ │ ├── kotlin-style/
│ │ │ │ └── SKILL.md
│ │ │ ├── spring-patterns/
│ │ │ │ └── SKILL.md
│ │ │ └── jvm-testing/
│ │ │ └── SKILL.md
│ │ └── commands/
│ │ └── gradle-build.md
│ │
│ ├── go-standards/
│ │ ├── .claude-plugin/
│ │ │ └── plugin.json
│ │ ├── skills/
│ │ │ ├── go-style/
│ │ │ │ └── SKILL.md
│ │ │ ├── go-errors/
│ │ │ │ └── SKILL.md
│ │ │ └── go-testing/
│ │ │ └── SKILL.md
│ │ └── commands/
│ │ └── go-build.md
│ │
│ └── shared-workflows/
│ ├── .claude-plugin/
│ │ └── plugin.json
│ ├── commands/
│ │ ├── pr-create.md
│ │ └── release-prepare.md
│ └── agents/
│ └── code-reviewer.md
│
└── README.md
4.2 marketplace.json#
{
"name" : "company-standards" ,
"version" : "2.0.0" ,
"description" : "회사 표준 개발 가이드라인 및 워크플로우" ,
"author" : "Platform Team" ,
"plugins" : [
{
"name" : "jvm-standards" ,
"path" : "plugins/jvm-standards" ,
"description" : "Java/Kotlin 개발 표준 (Spring Boot, Gradle)" ,
"tags" : [ "java" , "kotlin" , "spring-boot" ]
},
{
"name" : "go-standards" ,
"path" : "plugins/go-standards" ,
"description" : "Go 개발 표준 (Gin, sqlx)" ,
"tags" : [ "go" , "golang" ]
},
{
"name" : "shared-workflows" ,
"path" : "plugins/shared-workflows" ,
"description" : "공통 Git 워크플로우 및 코드 리뷰" ,
"tags" : [ "git" , "workflow" , "review" ]
}
]
}
4.3 팀 코딩 컨벤션 Skill 예제#
plugins/jvm-standards/skills/spring-patterns/SKILL.md :
---
name: spring-patterns
description: Spring Boot 패턴 가이드. Controller, Service, Repository 작성 시 활성화.
"API 만들어줘", "서비스 작성", "레포지토리" 요청 시 사용.
---
# Spring Boot Patterns (회사 표준)
## 레이어 구조
com.company.{service}/
├── api/ # Presentation Layer
│ ├── controller/ # REST Controllers
│ ├── dto/ # Request/Response DTOs
│ └── advice/ # Exception Handlers
├── application/ # Application Layer
│ └── service/ # Use Cases
├── domain/ # Domain Layer
│ ├── model/ # Entities
│ ├── repository/ # Repository Interfaces
│ └── event/ # Domain Events
└── infrastructure/ # Infrastructure Layer
├── persistence/ # Repository Implementations
├── client/ # External API Clients
└── config/ # Configurations
## Controller 패턴
```kotlin
@RestController
@RequestMapping("/api/v1/users")
class UserController(
private val userService: UserService
) {
@GetMapping("/{id}")
fun getUser(@PathVariable id: Long): ApiResponse<UserResponse> {
return ApiResponse.success(userService.getUser(id))
}
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun createUser(
@Valid @RequestBody request: CreateUserRequest
): ApiResponse<UserResponse> {
return ApiResponse.success(userService.createUser(request))
}
@PutMapping("/{id}")
fun updateUser(
@PathVariable id: Long,
@Valid @RequestBody request: UpdateUserRequest
): ApiResponse<UserResponse> {
return ApiResponse.success(userService.updateUser(id, request))
}
@DeleteMapping("/{id}")
@ResponseStatus(HttpStatus.NO_CONTENT)
fun deleteUser(@PathVariable id: Long) {
userService.deleteUser(id)
}
}
Service 패턴#
@Service
@Transactional ( readOnly = true )
class UserService (
private val userRepository : UserRepository ,
private val eventPublisher : ApplicationEventPublisher
) {
fun getUser ( id : Long ): UserResponse {
val user = userRepository . findById ( id )
. orElseThrow { UserNotFoundException ( id ) }
return UserResponse . from ( user )
}
@Transactional
fun createUser ( request : CreateUserRequest ): UserResponse {
// 검증
require (! userRepository . existsByEmail ( request . email )) {
throw DuplicateEmailException ( request . email )
}
// 생성
val user = User (
name = request . name ,
email = request . email
)
val savedUser = userRepository . save ( user )
// 이벤트 발행
eventPublisher . publishEvent ( UserCreatedEvent ( savedUser . id ))
return UserResponse . from ( savedUser )
}
}
공통 응답 형식#
data class ApiResponse < T >(
val success : Boolean ,
val data : T ? = null ,
val error : ErrorInfo ? = null ,
val meta : MetaInfo = MetaInfo ()
) {
companion object {
fun < T > success ( data : T ): ApiResponse < T > =
ApiResponse ( success = true , data = data )
fun < T > error ( error : ErrorInfo ): ApiResponse < T > =
ApiResponse ( success = false , error = error )
}
}
data class ErrorInfo (
val code : String ,
val message : String ,
val details : List < FieldError >? = null
)
data class MetaInfo (
val requestId : String = UUID . randomUUID (). toString (),
val timestamp : Instant = Instant . now ()
)
예외 처리#
// 비즈니스 예외 기본 클래스
sealed class BusinessException (
val errorCode : String ,
override val message : String ,
val status : HttpStatus = HttpStatus . BAD_REQUEST
) : RuntimeException ( message )
// 구체적인 예외들
class UserNotFoundException ( id : Long ) :
BusinessException ( "USER_NOT_FOUND" , "User not found: $id " , HttpStatus . NOT_FOUND )
class DuplicateEmailException ( email : String ) :
BusinessException ( "DUPLICATE_EMAIL" , "Email already exists: $email " , HttpStatus . CONFLICT )
// GlobalExceptionHandler
@RestControllerAdvice
class GlobalExceptionHandler {
@ExceptionHandler ( BusinessException :: class )
fun handleBusinessException ( e : BusinessException ): ResponseEntity < ApiResponse < Nothing >> {
return ResponseEntity
. status ( e . status )
. body ( ApiResponse . error ( ErrorInfo ( e . errorCode , e . message )))
}
}
### 4.4 배포 파이프라인 자동화 Command
**plugins/shared-workflows/commands/pr-create.md**:
```markdown
---
name: pr-create
description: 현재 브랜치의 변경사항으로 Pull Request를 생성합니다.
GitHub CLI(gh)를 사용합니다.
---
# PR Create Command
## 사전 조건 확인
1. `gh auth status`로 GitHub 인증 확인
2. 현재 브랜치가 main/master가 아닌지 확인
3. 커밋되지 않은 변경사항이 없는지 확인
## 작업 순서
1. 현재 브랜치명 확인
2. `git log main..HEAD --oneline`으로 커밋 목록 확인
3. 변경된 파일 목록 확인
4. PR 제목 생성 (브랜치명 기반)
5. PR 본문 생성:
- 변경 사항 요약
- 관련 이슈 링크
- 테스트 방법
- 체크리스트
6. `gh pr create` 실행
## PR 본문 템플릿
```markdown
## 📋 Summary
<!-- 변경 사항 요약 -->
## 🔗 Related Issues
<!-- 관련 이슈: closes #123 -->
## 🧪 Test Plan
<!-- 테스트 방법 -->
## ✅ Checklist
- [ ] 테스트 코드 작성/수정
- [ ] 문서 업데이트
- [ ] 린트 통과
- [ ] 빌드 성공
명령어 예시#
gh pr create \
--title "feat(user): add email verification" \
--body " $( cat pr-body.md) " \
--base main \
--reviewer "@team/backend"
---
## 5. 조직 전체 배포 (Enterprise)
### 5.1 Managed Settings를 통한 배포
Enterprise 환경에서는 관리자가 조직 전체에 Skills와 Plugins를 배포할 수 있습니다.
┌─────────────────────────────────────────────────────────────────┐
│ Enterprise 배포 구조 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Organization Admin │ │
│ │ │ │
│ │ Managed Settings에서 필수 플러그인 지정 │ │
│ │ - company-standards@our-marketplace │ │
│ │ - security-guidelines@our-marketplace │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ 자동 배포 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 개발자 A │ │ 개발자 B │ │ 개발자 C │ │
│ │ │ │ │ │ │ │
│ │ Claude Code │ │ Claude Code │ │ Claude Code │ │
│ │ 시작 시 │ │ 시작 시 │ │ 시작 시 │ │
│ │ 자동 설치됨 │ │ 자동 설치됨 │ │ 자동 설치됨 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
### 5.2 보안 고려사항
┌─────────────────────────────────────────────────────────────────┐
│ 보안 체크리스트 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ □ 모든 플러그인은 내부 검토를 거쳤는가? │
│ □ Skills에 민감한 정보(API 키, 비밀번호)가 포함되지 않았는가? │
│ □ 스크립트는 필요한 최소 권한만 요청하는가? │
│ □ 외부 의존성의 보안을 검토했는가? │
│ □ 정기적인 보안 업데이트 프로세스가 있는가? │
│ │
└─────────────────────────────────────────────────────────────────┘
⚠️ **주의**: Skills와 Plugins는 사용자 머신에서 코드를 실행할 수 있습니다. 신뢰할 수 있는 소스의 플러그인만 사용하세요.
---
## 6. Marketplace 유지보수
### 6.1 버전 관리 전략
**Semantic Versioning 적용**:
MAJOR.MINOR.PATCH
MAJOR: 호환성이 깨지는 변경 (Skills 제거, 이름 변경)
MINOR: 새 기능 추가 (새 Skill, 새 Command)
PATCH: 버그 수정, 문서 업데이트
**CHANGELOG.md 유지**:
```markdown
# Changelog
## [2.1.0] - 2025-01-23
### Added
- `spring-security` skill 추가
### Changed
- `kotlin-conventions` skill에 coroutine 패턴 추가
### Fixed
- `test-patterns` skill의 MockK 예제 오류 수정
## [2.0.0] - 2025-01-15
### Breaking Changes
- `java-style` skill을 `kotlin-conventions`로 통합
- 기존 `java-style` 사용자는 마이그레이션 필요
6.2 플러그인 품질 검증#
배포 전 체크리스트:
┌─────────────────────────────────────────────────────────────────┐
│ 배포 전 품질 검증 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ □ plugin.json이 올바른 형식인가? │
│ □ 모든 SKILL.md에 name과 description이 있는가? │
│ □ description이 명확하고 트리거 조건을 설명하는가? │
│ □ 실제 프로젝트에서 테스트했는가? │
│ □ README.md가 최신 상태인가? │
│ □ 버전 번호를 올렸는가? │
│ □ CHANGELOG.md를 업데이트했는가? │
│ │
└─────────────────────────────────────────────────────────────────┘
6.3 커뮤니티 기여 받기#
오픈소스 Marketplace 운영 시:
# CONTRIBUTING.md
## 기여 가이드
### 새 Skill 제안
1. Issue를 먼저 열어 논의
2. Fork 후 브랜치 생성
3. Skill 작성 (템플릿 참조)
4. 테스트
5. PR 생성
### Skill 작성 규칙
- [ ] SKILL.md는 skills/{skill-name}/SKILL.md에 위치
- [ ] YAML frontmatter에 name, description 필수
- [ ] description은 트리거 조건을 명확히 설명
- [ ] 예제 코드 포함
- [ ] 금지/권장 패턴 구분
### PR 리뷰 기준
- 기존 Skill과 중복되지 않는가?
- description이 명확한가?
- 예제가 실용적인가?
- 회사 표준과 충돌하지 않는가?
7. 정리#
이번 파트에서 배운 것#
Plugin 구조 : .claude-plugin/plugin.json + skills/ + commands/ + agents/
Marketplace 구조 : marketplace.json으로 여러 Plugin 묶기
GitHub 배포 : repo 생성 → marketplace.json 작성 → push
Enterprise 배포 : Managed Settings를 통한 조직 전체 배포
유지보수 : Semantic Versioning, CHANGELOG, 품질 검증
핵심 명령어#
# Marketplace 추가
/plugin marketplace add { org} /{ repo}
# 플러그인 설치
/plugin install { plugin} @{ marketplace}
# 플러그인 관리
/plugin # 인터랙티브 UI
다음 파트 예고#
이제 모든 도구를 배웠습니다. Part 6 에서는 이들을 조합한 고급 패턴 과 프로덕션 환경에서의 Best Practices 를 다룹니다.
참고 자료#
이전 : Part 4: Plugins & Marketplace
다음 : Part 6: 고급 패턴과 Best Practices