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).