From 08af1c708449fa78f564e04ec47bbd0975ad3794 Mon Sep 17 00:00:00 2001 From: pricelees Date: Thu, 18 Sep 2025 20:23:49 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20API=20=EC=9D=B8=ED=84=B0=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EA=B0=84=EA=B2=B0=ED=99=94=20=EB=B0=8F=20?= =?UTF-8?q?=EC=9D=BC=EB=B6=80=20=EC=98=A4=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/roomescape/auth/docs/AuthAPI.kt | 14 +++----- .../roomescape/payment/docs/PaymentAPI.kt | 9 +++--- .../roomescape/region/docs/RegionAPI.kt | 6 ++-- .../reservation/docs/ReservationAPI.kt | 26 +++++++-------- .../roomescape/schedule/docs/ScheduleAPI.kt | 28 +++++++--------- .../kotlin/roomescape/store/docs/StoreAPI.kt | 4 +-- .../persistence/StoreRepository.kt | 8 ++++- .../kotlin/roomescape/theme/docs/ThemeApi.kt | 32 +++++++++---------- .../kotlin/roomescape/user/docs/UserAPI.kt | 25 +++------------ 9 files changed, 63 insertions(+), 89 deletions(-) diff --git a/src/main/kotlin/roomescape/auth/docs/AuthAPI.kt b/src/main/kotlin/roomescape/auth/docs/AuthAPI.kt index 6ebe2e4d..5571a169 100644 --- a/src/main/kotlin/roomescape/auth/docs/AuthAPI.kt +++ b/src/main/kotlin/roomescape/auth/docs/AuthAPI.kt @@ -3,7 +3,6 @@ package roomescape.auth.docs import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.tags.Tag import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse import jakarta.validation.Valid @@ -11,28 +10,23 @@ import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.RequestBody import roomescape.auth.web.LoginRequest import roomescape.auth.web.LoginSuccessResponse -import roomescape.auth.web.support.User import roomescape.auth.web.support.Public +import roomescape.auth.web.support.User import roomescape.common.dto.CurrentUserContext import roomescape.common.dto.response.CommonApiResponse -@Tag(name = "1. 인증 / 인가 API", description = "로그인, 로그아웃 및 로그인 상태를 확인합니다") interface AuthAPI { @Public @Operation(summary = "로그인") - @ApiResponses( - ApiResponse(responseCode = "200", description = "로그인 성공시 토큰을 반환합니다."), - ) + @ApiResponses(ApiResponse(responseCode = "200")) fun login( @Valid @RequestBody loginRequest: LoginRequest, servletRequest: HttpServletRequest ): ResponseEntity> - @Operation(summary = "로그아웃", tags = ["로그인이 필요한 API"]) - @ApiResponses( - ApiResponse(responseCode = "200"), - ) + @Operation(summary = "로그아웃") + @ApiResponses(ApiResponse(responseCode = "200")) fun logout( @User user: CurrentUserContext, servletResponse: HttpServletResponse diff --git a/src/main/kotlin/roomescape/payment/docs/PaymentAPI.kt b/src/main/kotlin/roomescape/payment/docs/PaymentAPI.kt index a1cd9946..708cec30 100644 --- a/src/main/kotlin/roomescape/payment/docs/PaymentAPI.kt +++ b/src/main/kotlin/roomescape/payment/docs/PaymentAPI.kt @@ -18,16 +18,15 @@ import roomescape.payment.web.PaymentCreateResponse interface PaymentAPI { @UserOnly - @Operation(summary = "결제 승인", tags = ["로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "결제 승인") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun confirmPayment( @RequestParam(required = true) reservationId: Long, @Valid @RequestBody request: PaymentConfirmRequest ): ResponseEntity> - @UserOnly - @Operation(summary = "결제 취소", tags = ["로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "결제 취소") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun cancelPayment( @User user: CurrentUserContext, @Valid @RequestBody request: PaymentCancelRequest diff --git a/src/main/kotlin/roomescape/region/docs/RegionAPI.kt b/src/main/kotlin/roomescape/region/docs/RegionAPI.kt index faa022bf..b3486732 100644 --- a/src/main/kotlin/roomescape/region/docs/RegionAPI.kt +++ b/src/main/kotlin/roomescape/region/docs/RegionAPI.kt @@ -15,7 +15,7 @@ interface RegionAPI { @Public @Operation(summary = "지역 코드 조회") - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findRegionCode( @RequestParam(name = "sidoCode", required = true) sidoCode: String, @RequestParam(name = "sigunguCode", required = true) sigunguCode: String, @@ -23,12 +23,12 @@ interface RegionAPI { @Public @Operation(summary = "모든 시 / 도 목록 조회") - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun readAllSido(): ResponseEntity> @Public @Operation(summary = "모든 시 / 군 / 구 목록 조회") - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findAllSigunguBySido( @RequestParam(required = true) sidoCode: String ): ResponseEntity> diff --git a/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt b/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt index 66a8589f..8366e0d4 100644 --- a/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt +++ b/src/main/kotlin/roomescape/reservation/docs/ReservationAPI.kt @@ -18,45 +18,43 @@ import roomescape.reservation.web.* interface ReservationAPI { @Public - @Operation(summary = "가장 많이 예약된 테마 조회") - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "가장 많이 예약된 테마 ID 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findMostReservedThemeIds( @RequestParam count: Int ): ResponseEntity> - @UserOnly - @Operation(summary = "결제 대기 예약 저장", tags = ["로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "결제 전 임시 예약 저장") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun createPendingReservation( @User user: CurrentUserContext, @Valid @RequestBody request: PendingReservationCreateRequest ): ResponseEntity> @UserOnly - @Operation(summary = "예약 확정", tags = ["로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "결제 후 임시 예약 확정") + @ApiResponses(ApiResponse(responseCode = "200")) fun confirmReservation( @PathVariable("id") id: Long ): ResponseEntity> - @Operation(summary = "예약 취소", tags = ["로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "예약 취소") + @ApiResponses(ApiResponse(responseCode = "200")) fun cancelReservation( @User user: CurrentUserContext, @PathVariable id: Long, @Valid @RequestBody request: ReservationCancelRequest ): ResponseEntity> - @UserOnly - @Operation(summary = "회원별 예약 요약 목록 조회", tags = ["로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "회원별 예약 요약 목록 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findSummaryByMemberId( @User user: CurrentUserContext, ): ResponseEntity> @UserOnly - @Operation(summary = "특정 예약에 대한 상세 조회", tags = ["로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "특정 예약에 대한 상세 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findDetailById( @PathVariable("id") id: Long ): ResponseEntity> diff --git a/src/main/kotlin/roomescape/schedule/docs/ScheduleAPI.kt b/src/main/kotlin/roomescape/schedule/docs/ScheduleAPI.kt index ab1986ea..58141027 100644 --- a/src/main/kotlin/roomescape/schedule/docs/ScheduleAPI.kt +++ b/src/main/kotlin/roomescape/schedule/docs/ScheduleAPI.kt @@ -22,7 +22,7 @@ import java.time.LocalDate interface AdminScheduleAPI { @AdminOnly(privilege = Privilege.READ_SUMMARY) - @Operation(summary = "일정 검색", tags = ["관리자 로그인이 필요한 API"]) + @Operation(summary = "관리자 페이지에서 일정 요약 목록 조회") @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun searchSchedules( @PathVariable("storeId") storeId: Long, @@ -31,14 +31,14 @@ interface AdminScheduleAPI { ): ResponseEntity> @AdminOnly(privilege = Privilege.READ_DETAIL) - @Operation(summary = "일정 상세 조회", tags = ["관리자 로그인이 필요한 API"]) + @Operation(summary = "관지라 페이지에서 특정 예약의 일정 상세 조회") @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findScheduleAudit( @PathVariable("id") id: Long ): ResponseEntity> @AdminOnly(type = AdminType.STORE, privilege = Privilege.CREATE) - @Operation(summary = "일정 생성", tags = ["관리자 로그인이 필요한 API"]) + @Operation(summary = "일정 생성") @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun createSchedule( @PathVariable("storeId") storeId: Long, @@ -46,16 +46,16 @@ interface AdminScheduleAPI { ): ResponseEntity> @AdminOnly(type = AdminType.STORE, privilege = Privilege.UPDATE) - @Operation(summary = "일정 수정", tags = ["관리자 로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) + @Operation(summary = "일정 수정") + @ApiResponses(ApiResponse(responseCode = "200")) fun updateSchedule( @PathVariable("id") id: Long, @Valid @RequestBody request: ScheduleUpdateRequest ): ResponseEntity> @AdminOnly(type = AdminType.STORE, privilege = Privilege.DELETE) - @Operation(summary = "일정 삭제", tags = ["관리자 로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "204", useReturnTypeSchema = true)) + @Operation(summary = "일정 삭제") + @ApiResponses(ApiResponse(responseCode = "204")) fun deleteSchedule( @PathVariable("id") id: Long ): ResponseEntity> @@ -63,14 +63,8 @@ interface AdminScheduleAPI { interface UserScheduleAPI { @UserOnly - @Operation(summary = "일정을 Hold 상태로 변경", tags = ["로그인이 필요한 API"]) - @ApiResponses( - ApiResponse( - responseCode = "200", - description = "일정을 Hold 상태로 변경하여 중복 예약 방지", - useReturnTypeSchema = true - ) - ) + @Operation(summary = "중복 방지를 위해 일정을 Hold 상태로 변경") + @ApiResponses(ApiResponse(responseCode = "200")) fun holdSchedule( @PathVariable("id") id: Long ): ResponseEntity> @@ -78,8 +72,8 @@ interface UserScheduleAPI { interface PublicScheduleAPI { @Public - @Operation(summary = "특정 날짜 + 매장의 일정 조회") - @ApiResponses(ApiResponse(useReturnTypeSchema = true)) + @Operation(summary = "특정 날짜 + 매장의 모든 일정 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun getStoreSchedulesByDate( @PathVariable("storeId") storeId: Long, @RequestParam("date") @DateTimeFormat(pattern = "yyyy-MM-dd") date: LocalDate diff --git a/src/main/kotlin/roomescape/store/docs/StoreAPI.kt b/src/main/kotlin/roomescape/store/docs/StoreAPI.kt index 110ba588..3008582b 100644 --- a/src/main/kotlin/roomescape/store/docs/StoreAPI.kt +++ b/src/main/kotlin/roomescape/store/docs/StoreAPI.kt @@ -32,7 +32,7 @@ interface AdminStoreAPI { @AdminOnly(type = AdminType.STORE, privilege = Privilege.UPDATE) @Operation(summary = "매장 정보 수정") - @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) + @ApiResponses(ApiResponse(responseCode = "200")) fun updateStore( @PathVariable id: Long, @Valid @RequestBody request: StoreUpdateRequest @@ -40,7 +40,7 @@ interface AdminStoreAPI { @AdminOnly(type = AdminType.HQ, privilege = Privilege.DELETE) @Operation(summary = "매장 비활성화") - @ApiResponses(ApiResponse(responseCode = "204", useReturnTypeSchema = true)) + @ApiResponses(ApiResponse(responseCode = "204")) fun disableStore( @PathVariable id: Long ): ResponseEntity> diff --git a/src/main/kotlin/roomescape/store/infrastructure/persistence/StoreRepository.kt b/src/main/kotlin/roomescape/store/infrastructure/persistence/StoreRepository.kt index 84d6b3a3..ee289b2a 100644 --- a/src/main/kotlin/roomescape/store/infrastructure/persistence/StoreRepository.kt +++ b/src/main/kotlin/roomescape/store/infrastructure/persistence/StoreRepository.kt @@ -1,5 +1,6 @@ package roomescape.store.infrastructure.persistence +import com.fasterxml.jackson.databind.util.Named import org.springframework.data.jpa.repository.JpaRepository import org.springframework.data.jpa.repository.Query @@ -26,8 +27,13 @@ interface StoreRepository : JpaRepository { StoreEntity s WHERE s.status = roomescape.store.infrastructure.persistence.StoreStatus.ACTIVE - AND (:regionCode IS NULL OR s.regionCode LIKE ':regionCode%') + AND (:regionCode IS NULL OR s.regionCode LIKE :regionCode%) """ ) fun findAllActiveStoresByRegion(regionCode: String?): List + + fun existsByName(name: String): Boolean + fun existsByContact(contact: String): Boolean + fun existsByAddress(address: String): Boolean + fun existsByBusinessRegNum(businessRegNum: String): Boolean } diff --git a/src/main/kotlin/roomescape/theme/docs/ThemeApi.kt b/src/main/kotlin/roomescape/theme/docs/ThemeApi.kt index a542842c..15fabfc3 100644 --- a/src/main/kotlin/roomescape/theme/docs/ThemeApi.kt +++ b/src/main/kotlin/roomescape/theme/docs/ThemeApi.kt @@ -15,49 +15,49 @@ import roomescape.auth.web.support.Public import roomescape.common.dto.response.CommonApiResponse import roomescape.theme.web.* -@Tag(name = "5. 관리자 테마 API", description = "관리자 페이지에서 테마를 조회 / 추가 / 삭제할 때 사용합니다.") interface AdminThemeAPI { @AdminOnly(type = AdminType.HQ, privilege = Privilege.READ_SUMMARY) - @Operation(summary = "모든 테마 조회", description = "관리자 페이지에서 요약된 테마 목록을 조회합니다.", tags = ["관리자 로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "모든 테마 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun getAdminThemeSummaries(): ResponseEntity> @AdminOnly(type = AdminType.HQ, privilege = Privilege.READ_DETAIL) - @Operation(summary = "테마 상세 조회", description = "해당 테마의 상세 정보를 조회합니다.", tags = ["관리자 로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "테마 상세 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findAdminThemeDetail(@PathVariable("id") id: Long): ResponseEntity> @AdminOnly(type = AdminType.HQ, privilege = Privilege.CREATE) - @Operation(summary = "테마 추가", tags = ["관리자 로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "테마 추가") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun createTheme(@Valid @RequestBody themeCreateRequest: ThemeCreateRequest): ResponseEntity> @AdminOnly(type = AdminType.HQ, privilege = Privilege.DELETE) - @Operation(summary = "테마 삭제", tags = ["관리자 로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "204", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "테마 삭제") + @ApiResponses(ApiResponse(responseCode = "204")) fun deleteTheme(@PathVariable id: Long): ResponseEntity> @AdminOnly(type = AdminType.HQ, privilege = Privilege.UPDATE) - @Operation(summary = "테마 수정", tags = ["관리자 로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "테마 수정") + @ApiResponses(ApiResponse(responseCode = "200")) fun updateTheme( @PathVariable id: Long, @Valid @RequestBody request: ThemeUpdateRequest ): ResponseEntity> @AdminOnly(privilege = Privilege.READ_SUMMARY) - @Operation(summary = "테마 조회", description = "현재 open 상태인 모든 테마 ID + 이름 조회", tags = ["관리자 로그인이 필요한 API"]) - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "현재 활성화 상태인 테마 ID + 이름 목록 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun getActiveThemes(): ResponseEntity> } interface PublicThemeAPI { @Public - @Operation(summary = "입력된 모든 ID에 대한 테마 조회") - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @Operation(summary = "입력된 모든 ID에 대한 테마 정보 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findThemeInfosByIds(request: ThemeIdListRequest): ResponseEntity> + @Public @Operation(summary = "입력된 테마 ID에 대한 정보 조회") - @ApiResponses(ApiResponse(responseCode = "200", description = "성공", useReturnTypeSchema = true)) + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findThemeInfoById(@PathVariable id: Long): ResponseEntity> } diff --git a/src/main/kotlin/roomescape/user/docs/UserAPI.kt b/src/main/kotlin/roomescape/user/docs/UserAPI.kt index 93a0bbca..e809296d 100644 --- a/src/main/kotlin/roomescape/user/docs/UserAPI.kt +++ b/src/main/kotlin/roomescape/user/docs/UserAPI.kt @@ -3,46 +3,29 @@ package roomescape.user.docs import io.swagger.v3.oas.annotations.Operation import io.swagger.v3.oas.annotations.responses.ApiResponse import io.swagger.v3.oas.annotations.responses.ApiResponses -import io.swagger.v3.oas.annotations.tags.Tag import jakarta.validation.Valid import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.RequestBody -import roomescape.auth.web.support.User import roomescape.auth.web.support.Public -import roomescape.auth.web.support.UserOnly +import roomescape.auth.web.support.User import roomescape.common.dto.CurrentUserContext import roomescape.common.dto.response.CommonApiResponse import roomescape.user.web.UserContactResponse import roomescape.user.web.UserCreateRequest import roomescape.user.web.UserCreateResponse -@Tag(name = "2. 회원 API", description = "회원 정보를 관리할 때 사용합니다.") interface UserAPI { @Public @Operation(summary = "회원 가입") - @ApiResponses( - ApiResponse( - responseCode = "200", - description = "성공", - useReturnTypeSchema = true - ) - ) + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun signup( @Valid @RequestBody request: UserCreateRequest ): ResponseEntity> - @UserOnly - @Operation(summary = "회원 가입") - @ApiResponses( - ApiResponse( - responseCode = "200", - description = "성공", - useReturnTypeSchema = true - ) - ) + @Operation(summary = "회원 연락처 조회") + @ApiResponses(ApiResponse(responseCode = "200", useReturnTypeSchema = true)) fun findContact( @User user: CurrentUserContext ): ResponseEntity> - }