이 글은 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` |

## 형식

():

```

작업 순서#

  1. git diff --staged 실행하여 변경사항 확인
  2. 변경 내용 분석
  3. 적절한 타입과 scope 선택
  4. 명확한 subject 작성 (50자 이내, 명령형)
  5. 필요시 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. 정리#

이번 파트에서 배운 것#

  1. Plugin 구조: .claude-plugin/plugin.json + skills/ + commands/ + agents/
  2. Marketplace 구조: marketplace.json으로 여러 Plugin 묶기
  3. GitHub 배포: repo 생성 → marketplace.json 작성 → push
  4. Enterprise 배포: Managed Settings를 통한 조직 전체 배포
  5. 유지보수: 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