Scalar API Reference는 Swagger UI를 대체할 수 있는 또다른 API 문서화 방법이다.
Swagger UI와 비교하였을 때 화면 구성이 깔끔하기도 하며 API를 호출할 때 Postman과 같은 편리한 UI를 제공해줘서 개인적으로는 Swagger UI의 대체제로써 훌륭한 선택이라는 생각이다.
이번 포스팅에서는 Spring Web MVC 프로젝트에서 Scalar API Reference를 사용하는 방법에 대해 알아보도록 하겠다.
(코드 예제는 여기에서 확인할 수 있다)
0. Scalar Quickstart 살펴보기
먼저 어떻게 Scalar API Reference를 사용하면 좋을지를 알아보기 위해
Scalar repository README에 있는 Quckstart를 살펴보자.
<!doctype html>
<html>
<head>
<title>Scalar API Reference</title>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1" />
</head>
<body>
<!-- Need a Custom Header? Check out this example https://codepen.io/scalarorg/pen/VwOXqam -->
<script
id="api-reference"
data-url="https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.json"></script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body>
</html>
README에 위와 같은 짧은 html 코드가 있는데 이를 웹 브라우저에서 실행해보면 아래와 같은 API 문서가 나온다.
어떻게 이러한 문서가 나오게 되는걸까?
HTML의 14번째 줄을 보면 data-url에 json 파일을 사용하고 있는 걸 볼 수 있는데 이는 OpenAPI spec이다.
<!doctype html>
<html>
<head>
<title>Scalar API Reference</title>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1" />
</head>
<body>
<!-- Need a Custom Header? Check out this example https://codepen.io/scalarorg/pen/VwOXqam -->
<script
id="api-reference"
data-url="https://cdn.jsdelivr.net/npm/@scalar/galaxy/dist/latest.json"></script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body>
</html>
즉, OpenAPI spec 경로를 사용하여 15번째 라인의 스크립트를 통해 API 문서가 생성되는 것이다.
Scalar API Reference 위해서는 API의 OpenAPI spec를 가져올 수 있으면 된다.
이제 어떻게 Scalar API Reference를 사용할 수 있는지를 알아보았으니 Spring Web MVC프로젝트에서 Scalar API Reference를 어떻게 셋업할지 대해 살펴보자.
1. springdoc-openapi를 통해 OpenAPI spec 생성하기
Spring에서 OpenAPI spec을 만들고 Swagger UI를 실행하는 라이브러리로 가장 많이 사용되는 것이 springdoc-openapi 이다.
springdoc-openapi를 사용하기 위해 의존성을 추가해준다.
// build.gradle.kts
dependencies {
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0")
}
springdoc-openapi starter의 경우 기본적으로 /v3/api-docs를 통해 OpenAPI spec을 생성하게 된다.
서버를 실행한 뒤, /v3/api-docs 경로로 접속해보자.
이렇게 OpenAPI spec을 만드는 설정은 application.yml에서 켜고 끌 수 있다.
Scalar API Reference를 사용하기 위해서는 이 spec이 필요하기 때문에 이 설정은 기본값인 true로 두어야한다.
springdoc:
api-docs:
enabled: true # <===
2. API (Controller) 추가
API의 OpenAPI spec을 생성하는 설정을 마쳤기 때문에 예제를 위해 Controller를 생성하여 API를 추가해보자.
여기에서 API의 produces 옵션을 설정해줘야지 Scalar API Reference 상에서 응답 예제가 나오므로 더 명확한 문서를 위해 produces 옵션을 추가해주는 것을 추천한다..
// com.tistory.devs0n.scalar.UserController.kt
package com.tistory.devs0n.scalar
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.*
@Tag(name = "User API")
@RestController
@RequestMapping("/api/users")
class UserController {
private val users = mutableListOf(
User(name = "Kim", country = "Korea", city = "Seoul"),
User(name = "James", country = "USA", city = "New York"),
User(name = "Chris", country = "Korea", city = "Incheon"),
)
@Operation(description = "사용자 조회")
@GetMapping(produces = [MediaType.APPLICATION_JSON_VALUE]) // `produces` 설정을 해야 응답 예제가 나옴
fun getUsers(
@RequestParam(required = false) country: String?,
@RequestParam(required = false) name: String?,
): List<User> {
var response: List<User> = this.users
if (country != null) {
response = response.filter { it.country == country }
}
if (name != null) {
response = response.filter { it.name == name }
}
return response
}
@Operation(description = "사용자 추가")
@PostMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
fun addUser(@RequestBody request: User): User {
this.users.add(request)
return request
}
}
@Schema(description = "사용자 정보")
data class User(
@Schema(description = "이름", example = "Lee")
val name: String,
@Schema(description = "국가", example = "Korea")
val country: String,
@Schema(description = "도시", example = "Seoul")
val city: String,
)
// com.tistory.devs0n.scalar.ProductController
package com.tistory.devs0n.scalar
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.tags.Tag
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.*
@Tag(name = "Product API")
@RestController
@RequestMapping("/api/products")
class ProductController {
private val products = mutableListOf(
Product(name = "Jeans", price = 55_000),
Product(name = "T-shirt", price = 24_500),
)
@Operation(description = "제품 조회")
@GetMapping(produces = [MediaType.APPLICATION_JSON_VALUE]) // `produces` 설정을 해야 응답 예제가 나옴
fun getProducts(): List<Product> {
return this.products
}
@Operation(description = "제품 추가")
@PostMapping(produces = [MediaType.APPLICATION_JSON_VALUE])
fun addProduct(@RequestBody request: Product): Product {
this.products.add(request)
return request
}
}
@Schema(description = "제품 정보")
data class Product(
@Schema(description = "제품명", example = "Jeans")
val name: String,
@Schema(description = "가격", example = "55_000")
val price: Int,
)
그리고 다시 /v3/api-docs 경로를 확인해보면 OpenAPI spec에 새로 추가한 API에 대한 정보가 추가된 것을 확인할 수 있다.
3. Scalar API Reference 사용을 위한 html 추가
API의 OpenAPI spec을 가져올 수 있기 때문에 이를 사용하기만 하면 된다.
앞서 살펴본 html 파일에서 data-url 옵션만 /v3/api-docs로 변경해준 html 파일을 resources 디렉토리에 추가해준다.
<!doctype html>
<html>
<head>
<title>Scalar API Reference</title>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1" />
</head>
<body>
<script id="api-reference" data-url="/v3/api-docs"></script>
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
</body>
</html>
(나의 경우 resources/static/api-spec/index.html 에 두었다)
이제 서버를 실행한 뒤에 저장한 html 파일 경로에 맞는 url에 접속해서 문서를 확인해보자.
(나의 경우 /api-spec/index.html)
API 문서가 잘 생성되었음을 확인할 수 있고 API를 호출하는 것 또한 잘 동작하는 것을 볼 수 있다.
4. Authorization 추가
JWT와 같이 요청 header에 인증 정보를 추가해야하는 경우가 있다.
Authorization 설정을 추가해보고 Scalar API Reference에서는 어떤 식으로 사용되는지 알아보자.
먼저 OpenAPI 설정 코드를 추가한다.
// com.tistory.devs0n.scalar.OpenAPIConfiguration.kt
package com.tistory.devs0n.scalar
import io.swagger.v3.oas.models.Components
import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.info.Info
import io.swagger.v3.oas.models.security.SecurityRequirement
import io.swagger.v3.oas.models.security.SecurityScheme
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class OpenAPIConfiguration {
@Bean
fun openApi(): OpenAPI {
return OpenAPI()
.info(Info().title("Scalar API Reference example API"))
.components(
Components().addSecuritySchemes(
"Access Token",
SecurityScheme()
.type(SecurityScheme.Type.HTTP)
.`in`(SecurityScheme.In.HEADER)
.name("Authorization")
.scheme("bearer")
.bearerFormat("JWT")
)
)
.addSecurityItem(
SecurityRequirement()
.addList("Access Token")
)
}
}
그리고 서버를 재실행 후 API 문서를 다시 보면 인증 토큰을 설정하는 란이 생긴 것을 확인할 수 있다.
API를 호출하는 창에서 인증 토큰을 그대로 사용하는 것을 확인할 수 있고 실제 요청 header에도 인증 토큰이 잘 전송되는 것을 볼 수 있다.
'Java & Kotlin > Spring' 카테고리의 다른 글
[Spring Data JPA] @OneToMany Entity 연관 관계에 대하여 (7) | 2023.01.20 |
---|---|
[Spring Data JPA] entity update 후 JpaRepository.save 호출에 관하여 (6) | 2023.01.09 |
[springdoc-openapi] 고정 header 설정하기 (0) | 2022.12.31 |
Request Rate Limiting with Spring Cloud Gateway - 부록. custom Filter 만들기 (0) | 2022.02.08 |
Request Rate Limiting with Spring Cloud Gateway - 3. RateLimiterFilter 파헤치기 (2) | 2022.02.08 |
댓글