Skip to content

Commit

Permalink
📝docs : springdoc openapi 도입
Browse files Browse the repository at this point in the history
 - springdoc openapi 도입
 - api별 문서화
  • Loading branch information
ParkYunHo committed Feb 28, 2023
1 parent 74ed48a commit 94cb7c1
Show file tree
Hide file tree
Showing 25 changed files with 842 additions and 49 deletions.
10 changes: 7 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
id("org.springframework.boot") version "3.0.1"
id("io.spring.dependency-management") version "1.1.0"
id("org.springdoc.openapi-gradle-plugin") version "1.6.0"
kotlin("jvm") version "1.7.22"
kotlin("plugin.spring") version "1.7.22"
kotlin("plugin.jpa") version "1.7.22"
kotlin("kapt") version "1.7.22"
}

group = "com.nexters"
group = "pimo"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17

Expand Down Expand Up @@ -54,8 +55,11 @@ dependencies {
runtimeOnly("io.jsonwebtoken:jjwt-impl:0.11.5")
runtimeOnly("io.jsonwebtoken:jjwt-jackson:0.11.5")

implementation("com.infobip:infobip-spring-data-r2dbc-querydsl-boot-starter:6.2.0")
kapt("com.infobip:infobip-spring-data-jdbc-annotation-processor-common:6.2.0")
implementation("org.springdoc:springdoc-openapi-starter-webflux-ui:2.0.2") // spring boot 3.0에서 쓰려면 무조건 "2.0.2"버전으로 해야됨!!!!
}

tasks.getByName<Jar>("jar") {
enabled = false
}

tasks.withType<KotlinCompile> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
package com.nexters.pimo.account.adapter.`in`.web

import com.nexters.pimo.account.adapter.`in`.web.dto.AccountInput
import com.nexters.pimo.account.application.dto.AccountDto
import com.nexters.pimo.common.dto.BaseResponse
import com.nexters.pimo.follow.adapter.`in`.web.dto.RegisterInput
import com.nexters.pimo.follow.application.dto.FollowAccountDto
import com.nexters.pimo.follow.application.dto.FollowCntDto
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import io.swagger.v3.oas.annotations.media.Content
import io.swagger.v3.oas.annotations.media.ExampleObject
import io.swagger.v3.oas.annotations.media.Schema
import io.swagger.v3.oas.annotations.parameters.RequestBody
import io.swagger.v3.oas.annotations.responses.ApiResponse
import io.swagger.v3.oas.annotations.security.SecurityRequirement
import org.springdoc.core.annotations.RouterOperation
import org.springdoc.core.annotations.RouterOperations
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.web.bind.annotation.RequestMethod
import org.springframework.web.reactive.function.server.RouterFunction
import org.springframework.web.reactive.function.server.ServerResponse
import org.springframework.web.reactive.function.server.router
Expand All @@ -16,6 +33,253 @@ class AccountRouter(
private val accountHandler: AccountHandler
) {
@Bean
@RouterOperations(
value = [
RouterOperation(
path = "/users",
method = [RequestMethod.GET],
beanClass = AccountHandler::class,
beanMethod = "findMe",
operation = Operation(
tags = ["계정관리"],
summary = "나의 계정정보 조회",
operationId = "findMe",
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "나의 계정정보",
responseCode = "200",
content = [Content(schema = Schema(implementation = AccountDto::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
RouterOperation(
path = "/users/exists",
method = [RequestMethod.GET],
beanClass = AccountHandler::class,
beanMethod = "existUser",
operation = Operation(
tags = ["계정관리"],
summary = "나의 계정정보 존재여부 조회",
operationId = "existUser",
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "나의 계정정보 존재여부",
responseCode = "200",
content = [Content(schema = Schema(implementation = Boolean::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
RouterOperation(
path = "/users/exists/nickname",
method = [RequestMethod.GET],
beanClass = AccountHandler::class,
beanMethod = "existsNickName",
operation = Operation(
tags = ["계정관리"],
summary = "닉네임 존재여부 조회(중복체크)",
operationId = "existsNickName",
parameters = [
Parameter(name = "nickname", description = "닉네임", example = "admin", required = true),
],
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "닉네임 존재여부",
responseCode = "200",
content = [Content(schema = Schema(implementation = Boolean::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
RouterOperation(
path = "/users/search",
method = [RequestMethod.GET],
beanClass = AccountHandler::class,
beanMethod = "findUser",
operation = Operation(
tags = ["계정관리"],
summary = "사용자 계정정보 조회",
operationId = "findUser",
parameters = [
Parameter(name = "userId", description = "사용자 ID", example = "admin", required = true),
],
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "조회한 사용자 계정정보",
responseCode = "200",
content = [Content(schema = Schema(implementation = AccountDto::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
RouterOperation(
path = "/users/search/nickname",
method = [RequestMethod.GET],
beanClass = AccountHandler::class,
beanMethod = "searchUser",
operation = Operation(
tags = ["계정관리"],
summary = "사용자 닉네임 조회",
operationId = "searchUser",
parameters = [
Parameter(name = "nickname", description = "닉네임", example = "admin", required = true),
],
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "조회한 사용자 계정정보",
responseCode = "200",
content = [Content(schema = Schema(implementation = AccountDto::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
RouterOperation(
path = "/users",
method = [RequestMethod.POST],
beanClass = AccountHandler::class,
beanMethod = "saveUser",
operation = Operation(
tags = ["계정관리"],
summary = "사용자 정보 저장",
operationId = "saveUser",
requestBody = RequestBody(
content = [Content(schema = Schema(implementation = AccountInput::class, required = true))]
),
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "저장한 사용자 계정정보",
responseCode = "200",
content = [Content(schema = Schema(implementation = AccountDto::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
RouterOperation(
path = "/users/nickname",
method = [RequestMethod.PATCH],
beanClass = AccountHandler::class,
beanMethod = "updateUser",
operation = Operation(
tags = ["계정관리"],
summary = "사용자 닉네임 정보 업데이트",
operationId = "updateUser",
parameters = [
Parameter(name = "nickname", description = "닉네임", example = "admin", required = true),
],
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "업데이트한 사용자 계정정보",
responseCode = "200",
content = [Content(schema = Schema(implementation = AccountDto::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
RouterOperation(
path = "/users/profile",
method = [RequestMethod.PATCH],
beanClass = AccountHandler::class,
beanMethod = "updateUser",
operation = Operation(
tags = ["계정관리"],
summary = "사용자 프로필사진링크 정보 업데이트",
operationId = "updateUser",
parameters = [
Parameter(name = "profile", description = "프로필사진링크", example = "http://localhost:8080", required = true),
],
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "업데이트한 사용자 계정정보",
responseCode = "200",
content = [Content(schema = Schema(implementation = AccountDto::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
RouterOperation(
path = "/users",
method = [RequestMethod.DELETE],
beanClass = AccountHandler::class,
beanMethod = "deleteUser",
operation = Operation(
tags = ["계정관리"],
summary = "사용자 정보 삭제",
operationId = "deleteUser",
responses = [
// 공통 Response(BaseResponse)객체를 노출하기 위해 사용, responseCode는 swagger에서 맨 앞단에 노출시키기 위해 "0" 고정
ApiResponse(
responseCode = "0",
description = "공통 Response",
content = [Content(schema = Schema(implementation = BaseResponse::class))]
),
ApiResponse(
description = "사용자 삭제 성공여부",
responseCode = "200",
content = [Content(schema = Schema(implementation = Boolean::class))]
)
],
security = [SecurityRequirement(name = "Bearer Authentication")]
)
),
]
)
fun accountRouterFunction(): RouterFunction<ServerResponse> =
router {
accept(MediaType.APPLICATION_JSON).nest {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.nexters.pimo.account.adapter.`in`.web.dto

import io.swagger.v3.oas.annotations.media.Schema
import java.io.Serializable

/**
* @author yoonho
* @since 2023.02.14
*/
data class AccountInput (
@Schema(description = "닉네임", example = "admin1")
val nickName: String,
@Schema(description = "프로필사진링크", example = "https://localhost:8080")
val profileImgUrl: String
): Serializable
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package com.nexters.pimo.account.application.dto

import io.swagger.v3.oas.annotations.media.Schema

/**
* @author yoonho
* @since 2023.02.15
*/
data class AccountDto(
@Schema(description = "사용자ID", example = "admin1")
val userId: String,
@Schema(description = "닉네임", example = "admin1")
var nickName: String,
@Schema(description = "프로필사진링크", example = "https://localhost:8080")
var profileImgUrl: String,
@Schema(description = "계정상태", example = "0")
var status: String,
@Schema(description = "계정 업데이트 일자", example = "yyyyMMddHHmmss")
var updatedAt: String,
@Schema(description = "계정 생성 일자", example = "yyyyMMddHHmmss")
val createdAt: String
)
5 changes: 5 additions & 0 deletions src/main/kotlin/com/nexters/pimo/common/dto/BaseResponse.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.nexters.pimo.common.dto

import io.swagger.v3.oas.annotations.media.Schema
import org.springframework.http.HttpStatus
import org.springframework.web.reactive.function.BodyInserters
import org.springframework.web.reactive.function.server.ServerResponse
Expand All @@ -9,9 +10,13 @@ import java.io.Serializable
* @author yoonho
* @since 2023.01.16
*/
@Schema(description = "공통 Response")
data class BaseResponse (
@Schema(description = "응답 메세지", example = "Success")
val message: String?,
@Schema(description = "응답 HTTP Status", example = "200")
val status: HttpStatus,
@Schema(description = "응답 데이터")
val data: Any?
): Serializable {
constructor(): this(message = "Success", status = HttpStatus.OK, null)
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/com/nexters/pimo/common/dto/BaseTokenInfo.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.nexters.pimo.common.dto

import io.swagger.v3.oas.annotations.media.Schema
import java.io.Serializable

/**
* @author yoonho
* @since 2023.02.14
*/
data class BaseTokenInfo (
@Schema(description = "소셜로그인 구분", example = "kakao")
val provider: String,
@Schema(description = "토큰", example = "0")
val accessToken: String
): Serializable
Loading

0 comments on commit 94cb7c1

Please sign in to comment.