diff --git a/CHANGELOG.ko.md b/CHANGELOG.ko.md
index 64e45d0..92cf346 100644
--- a/CHANGELOG.ko.md
+++ b/CHANGELOG.ko.md
@@ -11,6 +11,16 @@ English: [CHANGELOG.md](CHANGELOG.md)
## [Unreleased]
+## [0.2.1] — 2026-06-02
+
+### 변경됨 (Changed)
+- **OpenAPI / Swagger UI를 이제 스타터에 포함** — `0.2.0`은 springdoc을 `compileOnly`로
+ 배포해, 소비자가 직접 springdoc을 추가해야만 Swagger UI가 떴습니다. 이제 스타터가
+ `springdoc-openapi-starter-webmvc-ui`를 `api`로 의존하므로 스타터만으로
+ `/swagger-ui`와 `/v3/api-docs`가 올라옵니다 — "스타터만 추가하면 다 됨" 약속에 부합.
+ `devslab.kit.openapi.enabled=false`로 끄거나 `org.springdoc` 의존성을 `exclude`해
+ jar를 제거할 수 있습니다(설정 레퍼런스에 문서화).
+
## [0.2.0] — 2026-06-02
### 추가됨 (Added)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 75ee79e..27951c9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,17 @@ The library major aligns with the Spring Boot major: `4.x.y` targets Spring Boot
## [Unreleased]
+## [0.2.1] — 2026-06-02
+
+### Changed
+- **OpenAPI / Swagger UI is now bundled in the starter** — `0.2.0` shipped springdoc
+ as `compileOnly`, so Swagger UI only appeared if the consumer added springdoc
+ themselves. The starter now depends on `springdoc-openapi-starter-webmvc-ui`
+ (`api`), so `/swagger-ui` and `/v3/api-docs` come up from the starter alone —
+ matching the kit's "add the starter, nothing else" promise. Turn it off with
+ `devslab.kit.openapi.enabled=false`, or `exclude` the `org.springdoc` dependency to
+ drop the jar (both documented in the configuration reference).
+
## [0.2.0] — 2026-06-02
### Added
diff --git a/README.ko.md b/README.ko.md
index a2bf3b9..e0c438a 100644
--- a/README.ko.md
+++ b/README.ko.md
@@ -41,7 +41,7 @@
| **캐시** | 플러그형 캐시 — `in-memory` · `redis` · `none`. Redis 백엔드가 JSON 직렬화를 직접 책임지므로 `Serializable` 구현이나 직렬화기 배선이 필요 없습니다(ADR 0002). 사용자별 메뉴 캐시도 이 공유 매니저를 사용합니다. |
| **최초 관리자 부트스트랩** | 첫 부팅 시 테넌트, `PLATFORM_ADMIN` 역할, `admin.*` 권한, 관리자 사용자를 멱등하게 생성 — opt-in, 프로퍼티 기반(ADR 0001). |
| **관리자 REST API** | 위 모든 엔티티 + 진단 + 실시간 설정 뷰를 위한 `/admin/api/v1/**`. |
-| **OpenAPI / Swagger UI** | springdoc만 추가하면 `/swagger-ui`가 관리자 API 그룹과 함께 자동으로 뜸 — 설정 불필요. `openapi.enabled=false`로 끔. |
+| **OpenAPI / Swagger UI** | 스타터에 포함 — `/swagger-ui`가 관리자 API 그룹과 함께 자동으로 뜸, 설정 불필요. `openapi.enabled=false`로 끄거나, springdoc 의존성을 `exclude`해 jar 자체를 제거. |
| **Override 친화적** | 모든 기본 빈이 `@ConditionalOnMissingBean` — 직접 선언하면 어느 조각이든 교체 가능. |
| **GraalVM Native** | 리플렉션 중심 설계를 피하고, 샘플 앱이 `nativeCompile`을 검증. |
@@ -62,7 +62,7 @@
**Gradle (Kotlin DSL)**
```kotlin
-implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.0")
+implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.1")
```
**Maven**
@@ -71,7 +71,7 @@ implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.0")
kr.devslab
devslab-kit-spring-boot-starter
- 0.2.0
+ 0.2.1
```
@@ -146,7 +146,7 @@ Docker Compose(Postgres + Redis)와 Testcontainers 기반 테스트까지 갖춘
| `bootstrap.admin-login-id` | `admin` | 최초 관리자 로그인 id. |
| `bootstrap.admin-password` | — | 비우면 강력한 랜덤 비밀번호를 한 번 로깅. |
| `bootstrap.must-change-password` | `true` | 첫 로그인 시 변경 강제. |
-| `openapi.enabled` | `true` | springdoc이 classpath에 있으면 Swagger UI / OpenAPI 노출. `false`로 비활성화(예: 프로덕션). |
+| `openapi.enabled` | `true` | Swagger UI / OpenAPI 노출(springdoc은 스타터에 포함됨). `false`로 비활성화(예: 프로덕션). |
| `openapi.title` | `devslab-kit Admin API` | OpenAPI 문서 / Swagger UI에 표시될 제목. |
런타임의 실제 적용값은 `GET /admin/api/v1/settings`에서도 볼 수 있습니다(시크릿 마스킹).
diff --git a/README.md b/README.md
index e353dbe..68b0a30 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ specific product's domain.
| **Cache** | A pluggable cache — `in-memory`, `redis`, or `none`. The Redis backend owns JSON serialization, so you never implement `Serializable` or wire a serializer (ADR 0002). The per-user menu cache rides this shared manager. |
| **First-admin bootstrap** | Idempotently provisions a tenant, a `PLATFORM_ADMIN` role, the `admin.*` permissions, and an admin user on first boot — opt-in and property-driven (ADR 0001). |
| **Admin REST API** | `/admin/api/v1/**` for every entity above, plus diagnostics and a live settings view. |
-| **OpenAPI / Swagger UI** | Add springdoc and `/swagger-ui` comes up with the admin API grouped — no wiring. Toggle off with `openapi.enabled=false`. |
+| **OpenAPI / Swagger UI** | Bundled in the starter — `/swagger-ui` comes up with the admin API grouped, no wiring. Toggle off with `openapi.enabled=false`, or `exclude` the springdoc dependency to drop the jar. |
| **Override-friendly** | Every default bean is `@ConditionalOnMissingBean` — replace any piece by declaring your own. |
| **GraalVM Native** | Reflection-heavy patterns are avoided; the sample app verifies `nativeCompile`. |
@@ -64,7 +64,7 @@ specific product's domain.
**Gradle (Kotlin DSL)**
```kotlin
-implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.0")
+implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.1")
```
**Maven**
@@ -73,7 +73,7 @@ implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.0")
kr.devslab
devslab-kit-spring-boot-starter
- 0.2.0
+ 0.2.1
```
@@ -149,7 +149,7 @@ All keys are under the `devslab.kit.*` prefix. Defaults shown.
| `bootstrap.admin-login-id` | `admin` | First admin login id. |
| `bootstrap.admin-password` | — | Blank → a strong random one is logged once. |
| `bootstrap.must-change-password` | `true` | Force a rotation on first login. |
-| `openapi.enabled` | `true` | Expose Swagger UI / OpenAPI when springdoc is on the classpath. Set `false` to disable (e.g. in production). |
+| `openapi.enabled` | `true` | Expose Swagger UI / OpenAPI (springdoc is bundled in the starter). Set `false` to disable (e.g. in production). |
| `openapi.title` | `devslab-kit Admin API` | Title shown in the OpenAPI doc / Swagger UI. |
The live, effective values are also viewable at runtime via
diff --git a/devslab-kit-sample-app/build.gradle.kts b/devslab-kit-sample-app/build.gradle.kts
index cbf6991..8e22e0a 100644
--- a/devslab-kit-sample-app/build.gradle.kts
+++ b/devslab-kit-sample-app/build.gradle.kts
@@ -17,11 +17,9 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-webmvc")
implementation("org.flywaydb:flyway-database-postgresql")
- // Swagger UI / OpenAPI. The kit's OpenApiAutoConfiguration activates only when
- // springdoc is on the classpath (a consumer opts in by adding this); it then
- // exposes /swagger-ui and groups the admin API. Version pinned in gradle.properties
- // (the Spring Boot BOM doesn't manage springdoc).
- implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:${property("SPRINGDOC_VERSION")}")
+ // No springdoc declared here on purpose: the starter bundles it, so Swagger UI
+ // comes up from the starter alone. The OpenApi*Tests prove /swagger-ui and
+ // /v3/api-docs work without the sample app adding springdoc itself.
compileOnly("org.projectlombok:lombok")
developmentOnly("org.springframework.boot:spring-boot-devtools")
diff --git a/devslab-kit-spring-boot-starter/build.gradle.kts b/devslab-kit-spring-boot-starter/build.gradle.kts
index 55b5204..8a7276c 100644
--- a/devslab-kit-spring-boot-starter/build.gradle.kts
+++ b/devslab-kit-spring-boot-starter/build.gradle.kts
@@ -3,6 +3,14 @@ description = "devslab-kit :: Spring Boot starter (dependency bundle)"
dependencies {
api(project(":devslab-kit-autoconfigure"))
api(project(":devslab-kit-tenant-core"))
+
+ // Bundle springdoc so a consumer gets Swagger UI just by adding the starter —
+ // OpenApiAutoConfiguration (in -autoconfigure, @ConditionalOnClass(GroupedOpenApi))
+ // then activates and serves /swagger-ui + /v3/api-docs with the admin API grouped.
+ // Turn it off with devslab.kit.openapi.enabled=false (the bean stays dormant), or
+ // exclude this dependency if you don't want the jar at all. Version pinned in
+ // gradle.properties (the Spring Boot BOM doesn't manage springdoc).
+ api("org.springdoc:springdoc-openapi-starter-webmvc-ui:${property("SPRINGDOC_VERSION")}")
}
mavenPublishing {
diff --git a/docs/getting-started/installation.ko.md b/docs/getting-started/installation.ko.md
index 959a2d5..505048c 100644
--- a/docs/getting-started/installation.ko.md
+++ b/docs/getting-started/installation.ko.md
@@ -17,13 +17,13 @@
=== "Gradle (Kotlin DSL)"
```kotlin
- implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.0")
+ implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.1")
```
=== "Gradle (Groovy)"
```groovy
- implementation 'kr.devslab:devslab-kit-spring-boot-starter:0.2.0'
+ implementation 'kr.devslab:devslab-kit-spring-boot-starter:0.2.1'
```
=== "Maven"
@@ -32,7 +32,7 @@
kr.devslab
devslab-kit-spring-boot-starter
- 0.2.0
+ 0.2.1
```
@@ -43,10 +43,10 @@
물러납니다(`@ConditionalOnMissingBean`).
```kotlin
-implementation("kr.devslab:devslab-kit-access-core:0.2.0") // RBAC + 그룹 + ABAC
-implementation("kr.devslab:devslab-kit-cache-core:0.2.0") // 플러그형 캐시
+implementation("kr.devslab:devslab-kit-access-core:0.2.1") // RBAC + 그룹 + ABAC
+implementation("kr.devslab:devslab-kit-cache-core:0.2.1") // 플러그형 캐시
// …또는 계약만:
-implementation("kr.devslab:devslab-kit-access-api:0.2.0")
+implementation("kr.devslab:devslab-kit-access-api:0.2.1")
```
동작하는 앱을 부팅하려면 [빠른 시작](quick-start.md)을 참고하세요.
diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md
index 438f71b..a000c17 100644
--- a/docs/getting-started/installation.md
+++ b/docs/getting-started/installation.md
@@ -17,13 +17,13 @@ whole platform; depend on individual modules only if you want à la carte.
=== "Gradle (Kotlin DSL)"
```kotlin
- implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.0")
+ implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.1")
```
=== "Gradle (Groovy)"
```groovy
- implementation 'kr.devslab:devslab-kit-spring-boot-starter:0.2.0'
+ implementation 'kr.devslab:devslab-kit-spring-boot-starter:0.2.1'
```
=== "Maven"
@@ -32,7 +32,7 @@ whole platform; depend on individual modules only if you want à la carte.
kr.devslab
devslab-kit-spring-boot-starter
- 0.2.0
+ 0.2.1
```
@@ -44,10 +44,10 @@ your own — the auto-configuration backs off (`@ConditionalOnMissingBean`) when
do.
```kotlin
-implementation("kr.devslab:devslab-kit-access-core:0.2.0") // RBAC + groups + ABAC
-implementation("kr.devslab:devslab-kit-cache-core:0.2.0") // pluggable cache
+implementation("kr.devslab:devslab-kit-access-core:0.2.1") // RBAC + groups + ABAC
+implementation("kr.devslab:devslab-kit-cache-core:0.2.1") // pluggable cache
// …or just the contract:
-implementation("kr.devslab:devslab-kit-access-api:0.2.0")
+implementation("kr.devslab:devslab-kit-access-api:0.2.1")
```
See [Quick Start](quick-start.md) to boot a working app.
diff --git a/docs/reference/configuration.ko.md b/docs/reference/configuration.ko.md
index 21e6f4e..accd43e 100644
--- a/docs/reference/configuration.ko.md
+++ b/docs/reference/configuration.ko.md
@@ -107,20 +107,44 @@
## OpenAPI / Swagger UI — `devslab.kit.openapi.*` { #openapi }
-킷은 **springdoc이 classpath에 있을 때** OpenAPI와 Swagger UI를 자동 구성합니다 —
-springdoc을 `compileOnly`로 가지고 있으므로, 의존성을 추가해 opt-in 합니다:
-
-```kotlin
-implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.3")
-```
-
-추가하면 추가 설정 없이 `/swagger-ui.html`과 `/v3/api-docs`가 올라오고, 킷의
-`/admin/api/v1/**` 엔드포인트가 하나의 그룹(`/v3/api-docs/admin`)으로 묶입니다.
-springdoc `3.0.x`가 Spring Boot 4 라인입니다(`2.8.x`는 Spring Boot 3 대상).
+스타터가 **springdoc을 포함**하므로, 추가 의존성·설정 없이 스타터만으로
+`/swagger-ui.html`과 `/v3/api-docs`가 올라오고, 킷의 `/admin/api/v1/**` 엔드포인트가
+하나의 그룹(`/v3/api-docs/admin`)으로 묶입니다. springdoc `3.0.x`가 Spring Boot 4
+라인입니다(`2.8.x`는 Spring Boot 3 대상).
+
+끄는 방법 두 가지:
+
+1. **jar는 두고 표면만 끔** — `devslab.kit.openapi.enabled=false`. 자동 구성이
+ 비활성 상태로 남아 아무것도 노출되지 않습니다. 프로덕션의 일반적 선택.
+2. **jar 자체를 제거** — 스타터 의존성에서 springdoc을 exclude:
+
+ === "Gradle (Kotlin DSL)"
+
+ ```kotlin
+ implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.1") {
+ exclude(group = "org.springdoc")
+ }
+ ```
+
+ === "Maven"
+
+ ```xml
+
+ kr.devslab
+ devslab-kit-spring-boot-starter
+ 0.2.1
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+
+
+
+ ```
| 프로퍼티 | 타입 | 기본값 | 설명 |
| --- | --- | --- | --- |
-| `enabled` | boolean | `true` | 마스터 스위치. `false`로 두면 의존성을 제거하지 않고도 킷의 OpenAPI 구성을 끕니다. |
+| `enabled` | boolean | `true` | 마스터 스위치. `false`로 두면 (포함된) 의존성을 그대로 둔 채 킷의 OpenAPI 구성만 끕니다. |
| `admin-group` | string | `admin` | 관리자 API의 Swagger UI 그룹 이름. |
| `title` | string | `devslab-kit Admin API` | OpenAPI 문서 / Swagger UI에 표시될 제목. |
| `version` | string | `v1` | OpenAPI 문서의 버전 문자열. |
@@ -130,5 +154,5 @@ springdoc `3.0.x`가 Spring Boot 4 라인입니다(`2.8.x`는 Spring Boot 3 대
!!! tip "프로덕션"
API 문서는 보통 프로덕션에 노출하지 않습니다.
- `devslab.kit.openapi.enabled=false`로 끄거나(또는 프로덕션 빌드에서 springdoc
- 의존성을 빼서) 해당 표면을 비활성화하세요.
+ `devslab.kit.openapi.enabled=false`로 표면을 끄거나(위 1번), springdoc을
+ `exclude`해 jar를 제거하세요(2번).
diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md
index 397c20e..d7abdf4 100644
--- a/docs/reference/configuration.md
+++ b/docs/reference/configuration.md
@@ -113,22 +113,45 @@ See the [First-admin Bootstrap guide](../guides/bootstrap.md) and
## OpenAPI / Swagger UI — `devslab.kit.openapi.*` { #openapi }
-The kit auto-configures OpenAPI and Swagger UI **when springdoc is on the
-classpath** — it ships springdoc as `compileOnly`, so you opt in by adding the
-dependency:
-
-```kotlin
-implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.3")
-```
-
-With that present, `/swagger-ui.html` and `/v3/api-docs` come up with no further
-wiring, and the kit's `/admin/api/v1/**` endpoints are collected into one group
-(`/v3/api-docs/admin`). springdoc `3.0.x` is the Spring Boot 4 line (`2.8.x`
-targets Spring Boot 3).
+The starter **bundles springdoc**, so `/swagger-ui.html` and `/v3/api-docs` come up
+from the starter alone — no extra dependency, no wiring — and the kit's
+`/admin/api/v1/**` endpoints are collected into one group (`/v3/api-docs/admin`).
+springdoc `3.0.x` is the Spring Boot 4 line (`2.8.x` targets Spring Boot 3).
+
+Two ways to turn it off:
+
+1. **Keep the jar, disable the surface** — `devslab.kit.openapi.enabled=false`. The
+ auto-configuration stays dormant; nothing is served. This is the usual production
+ choice.
+2. **Drop the jar entirely** — exclude springdoc from the starter dependency:
+
+ === "Gradle (Kotlin DSL)"
+
+ ```kotlin
+ implementation("kr.devslab:devslab-kit-spring-boot-starter:0.2.1") {
+ exclude(group = "org.springdoc")
+ }
+ ```
+
+ === "Maven"
+
+ ```xml
+
+ kr.devslab
+ devslab-kit-spring-boot-starter
+ 0.2.1
+
+
+ org.springdoc
+ springdoc-openapi-starter-webmvc-ui
+
+
+
+ ```
| Property | Type | Default | Description |
| --- | --- | --- | --- |
-| `enabled` | boolean | `true` | Master switch. Set `false` to disable the kit's OpenAPI wiring without removing the dependency. |
+| `enabled` | boolean | `true` | Master switch. Set `false` to disable the kit's OpenAPI wiring while leaving the (bundled) dependency in place. |
| `admin-group` | string | `admin` | Swagger UI group name for the admin API. |
| `title` | string | `devslab-kit Admin API` | Title shown in the OpenAPI document / Swagger UI. |
| `version` | string | `v1` | Version string in the OpenAPI document. |
@@ -139,5 +162,5 @@ schemes or servers) and the kit backs off.
!!! tip "Production"
API docs are usually not exposed in production. Set
- `devslab.kit.openapi.enabled=false` (or omit the springdoc dependency from the
- production build) to turn the surface off.
+ `devslab.kit.openapi.enabled=false` to turn the surface off (option 1 above), or
+ `exclude` springdoc to drop the jar (option 2).