refactor: theme 내의 DTO 이름 컨벤션 통일

This commit is contained in:
이상진 2025-07-23 16:43:31 +09:00
parent ee56e44bf8
commit 821f379e78
7 changed files with 42 additions and 51 deletions

View File

@ -6,7 +6,7 @@ import roomescape.member.web.MemberRetrieveResponse
import roomescape.member.web.toRetrieveResponse import roomescape.member.web.toRetrieveResponse
import roomescape.reservation.infrastructure.persistence.ReservationEntity import roomescape.reservation.infrastructure.persistence.ReservationEntity
import roomescape.reservation.infrastructure.persistence.ReservationStatus import roomescape.reservation.infrastructure.persistence.ReservationStatus
import roomescape.theme.web.ThemeResponse import roomescape.theme.web.ThemeRetrieveResponse
import roomescape.theme.web.toResponse import roomescape.theme.web.toResponse
import java.time.LocalDate import java.time.LocalDate
import java.time.LocalTime import java.time.LocalTime
@ -41,7 +41,7 @@ data class ReservationRetrieveResponse(
val time: TimeCreateResponse, val time: TimeCreateResponse,
@field:JsonProperty("theme") @field:JsonProperty("theme")
val theme: ThemeResponse, val theme: ThemeRetrieveResponse,
val status: ReservationStatus val status: ReservationStatus
) )

View File

@ -27,11 +27,11 @@ class ThemeService(
) )
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun findThemes(): ThemesResponse = themeRepository.findAll() fun findThemes(): ThemeRetrieveListResponse = themeRepository.findAll()
.toResponse() .toResponse()
@Transactional(readOnly = true) @Transactional(readOnly = true)
fun findMostReservedThemes(count: Int): ThemesResponse { fun findMostReservedThemes(count: Int): ThemeRetrieveListResponse {
val today = LocalDate.now() val today = LocalDate.now()
val startDate = today.minusDays(7) val startDate = today.minusDays(7)
val endDate = today.minusDays(1) val endDate = today.minusDays(1)
@ -41,7 +41,7 @@ class ThemeService(
} }
@Transactional @Transactional
fun createTheme(request: ThemeRequest): ThemeResponse { fun createTheme(request: ThemeCreateRequest): ThemeRetrieveResponse {
if (themeRepository.existsByName(request.name)) { if (themeRepository.existsByName(request.name)) {
throw RoomescapeException( throw RoomescapeException(
ErrorType.THEME_DUPLICATED, ErrorType.THEME_DUPLICATED,

View File

@ -13,9 +13,9 @@ import org.springframework.web.bind.annotation.RequestParam
import roomescape.auth.web.support.Admin import roomescape.auth.web.support.Admin
import roomescape.auth.web.support.LoginRequired import roomescape.auth.web.support.LoginRequired
import roomescape.common.dto.response.CommonApiResponse import roomescape.common.dto.response.CommonApiResponse
import roomescape.theme.web.ThemeRequest import roomescape.theme.web.ThemeCreateRequest
import roomescape.theme.web.ThemeResponse import roomescape.theme.web.ThemeRetrieveResponse
import roomescape.theme.web.ThemesResponse import roomescape.theme.web.ThemeRetrieveListResponse
@Tag(name = "5. 테마 API", description = "테마를 조회 / 추가 / 삭제할 때 사용합니다.") @Tag(name = "5. 테마 API", description = "테마를 조회 / 추가 / 삭제할 때 사용합니다.")
interface ThemeAPI { interface ThemeAPI {
@ -23,13 +23,13 @@ interface ThemeAPI {
@LoginRequired @LoginRequired
@Operation(summary = "모든 테마 조회", description = "모든 테마를 조회합니다.", tags = ["로그인이 필요한 API"]) @Operation(summary = "모든 테마 조회", description = "모든 테마를 조회합니다.", tags = ["로그인이 필요한 API"])
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun findThemes(): ResponseEntity<CommonApiResponse<ThemesResponse>> fun findThemes(): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponse>>
@Operation(summary = "가장 많이 예약된 테마 조회") @Operation(summary = "가장 많이 예약된 테마 조회")
@ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true))
fun findMostReservedThemes( fun findMostReservedThemes(
@RequestParam(defaultValue = "10") @Parameter(description = "최대로 조회할 테마 갯수") count: Int @RequestParam(defaultValue = "10") @Parameter(description = "최대로 조회할 테마 갯수") count: Int
): ResponseEntity<CommonApiResponse<ThemesResponse>> ): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponse>>
@Admin @Admin
@Operation(summary = "테마 추가", tags = ["관리자 로그인이 필요한 API"]) @Operation(summary = "테마 추가", tags = ["관리자 로그인이 필요한 API"])
@ -37,8 +37,8 @@ interface ThemeAPI {
ApiResponse(responseCode = "201", description = "성공", useReturnTypeSchema = true), ApiResponse(responseCode = "201", description = "성공", useReturnTypeSchema = true),
) )
fun createTheme( fun createTheme(
@Valid @RequestBody request: ThemeRequest, @Valid @RequestBody request: ThemeCreateRequest,
): ResponseEntity<CommonApiResponse<ThemeResponse>> ): ResponseEntity<CommonApiResponse<ThemeRetrieveResponse>>
@Admin @Admin
@Operation(summary = "테마 삭제", tags = ["관리자 로그인이 필요한 API"]) @Operation(summary = "테마 삭제", tags = ["관리자 로그인이 필요한 API"])

View File

@ -15,8 +15,8 @@ class ThemeController(
) : ThemeAPI { ) : ThemeAPI {
@GetMapping("/themes") @GetMapping("/themes")
override fun findThemes(): ResponseEntity<CommonApiResponse<ThemesResponse>> { override fun findThemes(): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponse>> {
val response: ThemesResponse = themeService.findThemes() val response: ThemeRetrieveListResponse = themeService.findThemes()
return ResponseEntity.ok(CommonApiResponse(response)) return ResponseEntity.ok(CommonApiResponse(response))
} }
@ -24,17 +24,17 @@ class ThemeController(
@GetMapping("/themes/most-reserved-last-week") @GetMapping("/themes/most-reserved-last-week")
override fun findMostReservedThemes( override fun findMostReservedThemes(
@RequestParam(defaultValue = "10") @Parameter(description = "최대로 조회할 테마 갯수") count: Int @RequestParam(defaultValue = "10") @Parameter(description = "최대로 조회할 테마 갯수") count: Int
): ResponseEntity<CommonApiResponse<ThemesResponse>> { ): ResponseEntity<CommonApiResponse<ThemeRetrieveListResponse>> {
val response: ThemesResponse = themeService.findMostReservedThemes(count) val response: ThemeRetrieveListResponse = themeService.findMostReservedThemes(count)
return ResponseEntity.ok(CommonApiResponse(response)) return ResponseEntity.ok(CommonApiResponse(response))
} }
@PostMapping("/themes") @PostMapping("/themes")
override fun createTheme( override fun createTheme(
@RequestBody @Valid request: ThemeRequest @RequestBody @Valid request: ThemeCreateRequest
): ResponseEntity<CommonApiResponse<ThemeResponse>> { ): ResponseEntity<CommonApiResponse<ThemeRetrieveResponse>> {
val themeResponse: ThemeResponse = themeService.createTheme(request) val themeResponse: ThemeRetrieveResponse = themeService.createTheme(request)
return ResponseEntity.created(URI.create("/themes/${themeResponse.id}")) return ResponseEntity.created(URI.create("/themes/${themeResponse.id}"))
.body(CommonApiResponse(themeResponse)) .body(CommonApiResponse(themeResponse))

View File

@ -1,57 +1,48 @@
package roomescape.theme.web package roomescape.theme.web
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotBlank import jakarta.validation.constraints.NotBlank
import jakarta.validation.constraints.Size import jakarta.validation.constraints.Size
import org.hibernate.validator.constraints.URL import org.hibernate.validator.constraints.URL
import roomescape.theme.infrastructure.persistence.ThemeEntity import roomescape.theme.infrastructure.persistence.ThemeEntity
@Schema(name = "테마 저장 요청", description = "테마 정보를 저장할 때 사용합니다.") data class ThemeCreateRequest(
data class ThemeRequest(
@Schema(description = "필수 값이며, 최대 20글자까지 입력 가능합니다.")
@NotBlank @NotBlank
@Size(max = 20, message = "테마의 이름은 1~20글자 사이여야 합니다.") @Size(max = 20)
val name: String, val name: String,
@Schema(description = "필수 값이며, 최대 100글자까지 입력 가능합니다.")
@NotBlank @NotBlank
@Size(max = 100, message = "테마의 설명은 1~100글자 사이여야 합니다.") @Size(max = 100)
val description: String, val description: String,
@Schema(description = "필수 값이며, 썸네일 이미지 URL 을 입력해주세요.")
@NotBlank
@URL @URL
@NotBlank
val thumbnail: String val thumbnail: String
) )
@Schema(name = "테마 정보", description = "테마 추가 및 조회 응답에 사용됩니다.") fun ThemeCreateRequest.toEntity(): ThemeEntity = ThemeEntity(
data class ThemeResponse( name = this.name,
@Schema(description = "테마 번호. 테마를 식별할 때 사용합니다.") description = this.description,
thumbnail = this.thumbnail
)
data class ThemeRetrieveResponse(
val id: Long, val id: Long,
@Schema(description = "테마 이름. 중복을 허용하지 않습니다.")
val name: String, val name: String,
@Schema(description = "테마 설명")
val description: String, val description: String,
@Schema(description = "테마 썸네일 이미지 URL")
val thumbnail: String val thumbnail: String
) )
fun ThemeEntity.toResponse(): ThemeResponse = ThemeResponse( fun ThemeEntity.toResponse(): ThemeRetrieveResponse = ThemeRetrieveResponse(
id = this.id!!, id = this.id!!,
name = this.name, name = this.name,
description = this.description, description = this.description,
thumbnail = this.thumbnail thumbnail = this.thumbnail
) )
@Schema(name = "테마 목록 조회 응답", description = "모든 테마 목록 조회 응답시 사용됩니다.") data class ThemeRetrieveListResponse(
data class ThemesResponse( val themes: List<ThemeRetrieveResponse>
@Schema(description = "모든 테마 목록")
val themes: List<ThemeResponse>
) )
fun List<ThemeEntity>.toResponse(): ThemesResponse = ThemesResponse( fun List<ThemeEntity>.toResponse(): ThemeRetrieveListResponse = ThemeRetrieveListResponse(
themes = this.map { it.toResponse() } themes = this.map { it.toResponse() }
) )

View File

@ -12,7 +12,7 @@ import roomescape.common.exception.ErrorType
import roomescape.common.exception.RoomescapeException import roomescape.common.exception.RoomescapeException
import roomescape.theme.infrastructure.persistence.ThemeEntity import roomescape.theme.infrastructure.persistence.ThemeEntity
import roomescape.theme.infrastructure.persistence.ThemeRepository import roomescape.theme.infrastructure.persistence.ThemeRepository
import roomescape.theme.web.ThemeRequest import roomescape.theme.web.ThemeCreateRequest
import roomescape.util.ThemeFixture import roomescape.util.ThemeFixture
class ThemeServiceTest : FunSpec({ class ThemeServiceTest : FunSpec({
@ -68,7 +68,7 @@ class ThemeServiceTest : FunSpec({
} returns true } returns true
val exception = shouldThrow<RoomescapeException> { val exception = shouldThrow<RoomescapeException> {
themeService.createTheme(ThemeRequest( themeService.createTheme(ThemeCreateRequest(
name = name, name = name,
description = "Description", description = "Description",
thumbnail = "http://example.com/thumbnail.jpg" thumbnail = "http://example.com/thumbnail.jpg"

View File

@ -58,7 +58,7 @@ class ThemeControllerTest(mockMvc: MockMvc) : RoomescapeApiTest() {
ThemeFixture.create(id = 3, name = "theme3") ThemeFixture.create(id = 3, name = "theme3")
) )
val response: ThemesResponse = runGetTest( val response: ThemeRetrieveListResponse = runGetTest(
mockMvc = mockMvc, mockMvc = mockMvc,
endpoint = endpoint, endpoint = endpoint,
) { ) {
@ -66,7 +66,7 @@ class ThemeControllerTest(mockMvc: MockMvc) : RoomescapeApiTest() {
content { content {
contentType(MediaType.APPLICATION_JSON) contentType(MediaType.APPLICATION_JSON)
} }
}.andReturn().readValue(ThemesResponse::class.java) }.andReturn().readValue(ThemeRetrieveListResponse::class.java)
assertSoftly(response.themes) { assertSoftly(response.themes) {
it.size shouldBe 3 it.size shouldBe 3
@ -78,7 +78,7 @@ class ThemeControllerTest(mockMvc: MockMvc) : RoomescapeApiTest() {
Given("테마를 추가할 때") { Given("테마를 추가할 때") {
val endpoint = "/themes" val endpoint = "/themes"
val request = ThemeRequest( val request = ThemeCreateRequest(
name = "theme1", name = "theme1",
description = "description1", description = "description1",
thumbnail = "http://example.com/thumbnail1.jpg" thumbnail = "http://example.com/thumbnail1.jpg"
@ -138,13 +138,13 @@ class ThemeControllerTest(mockMvc: MockMvc) : RoomescapeApiTest() {
loginAsAdmin() loginAsAdmin()
} }
val request = ThemeRequest( val request = ThemeCreateRequest(
name = "theme1", name = "theme1",
description = "description1", description = "description1",
thumbnail = "http://example.com/thumbnail1.jpg" thumbnail = "http://example.com/thumbnail1.jpg"
) )
fun runTest(request: ThemeRequest) { fun runTest(request: ThemeCreateRequest) {
runPostTest( runPostTest(
mockMvc = mockMvc, mockMvc = mockMvc,
endpoint = endpoint, endpoint = endpoint,
@ -197,7 +197,7 @@ class ThemeControllerTest(mockMvc: MockMvc) : RoomescapeApiTest() {
every { every {
themeService.createTheme(request) themeService.createTheme(request)
} returns ThemeResponse( } returns ThemeRetrieveResponse(
id = theme.id!!, id = theme.id!!,
name = theme.name, name = theme.name,
description = theme.description, description = theme.description,