From 418e3ec052b14eb15f628d33d1e10fb371dfe9a6 Mon Sep 17 00:00:00 2001 From: kim keun tae Date: Fri, 31 Jan 2025 23:02:07 +0900 Subject: [PATCH 1/9] =?UTF-8?q?API=20=EC=9D=91=EB=8B=B5=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/exception/GlobalExceptionHandler.java | 23 ++++++++++++++----- .../hanghae/application/dto/ApiResponse.java | 9 ++++---- .../application/enums/HttpStatusCode.java | 2 ++ .../service/MovieReservationServiceImpl.java | 4 ++-- .../service/MovieScheduleServiceImpl.java | 6 ++--- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/cinema-adapter/src/main/java/com/hanghae/adapter/web/exception/GlobalExceptionHandler.java b/cinema-adapter/src/main/java/com/hanghae/adapter/web/exception/GlobalExceptionHandler.java index 45584144b..baf5428d4 100644 --- a/cinema-adapter/src/main/java/com/hanghae/adapter/web/exception/GlobalExceptionHandler.java +++ b/cinema-adapter/src/main/java/com/hanghae/adapter/web/exception/GlobalExceptionHandler.java @@ -1,6 +1,7 @@ package com.hanghae.adapter.web.exception; import com.hanghae.application.dto.ApiResponse; +import com.hanghae.application.enums.HttpStatusCode; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -14,21 +15,31 @@ public class GlobalExceptionHandler { @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity> handleIllegalArgumentException(IllegalArgumentException e) { log.error("IllegalArgumentException occurred: {}", e.getMessage(), e); // 로그 추가 - ApiResponse apiResponse = ApiResponse.of(e.getMessage(), HttpStatus.BAD_REQUEST.value()); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(apiResponse); + ApiResponse apiResponse = ApiResponse.of(e.getMessage(), HttpStatusCode.BAD_REQUEST); + return ResponseEntity.status(HttpStatusCode.BAD_REQUEST.getCode()).body(apiResponse); } @ExceptionHandler(HttpMessageNotReadableException.class) public ResponseEntity> handleHttpMessageNotReadableException(HttpMessageNotReadableException e) { log.error("HttpMessageNotReadableException occurred: {}", e.getMessage(), e); // 로그 추가 - ApiResponse apiResponse = ApiResponse.of(e.getMessage(), HttpStatus.BAD_REQUEST.value()); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(apiResponse); + ApiResponse apiResponse = ApiResponse.of(e.getMessage(), HttpStatusCode.BAD_REQUEST); + return ResponseEntity.status(HttpStatusCode.BAD_REQUEST.getCode()).body(apiResponse); } @ExceptionHandler(RuntimeException.class) public ResponseEntity> handleRuntimeException(RuntimeException e) { log.error("RuntimeException occurred: {}", e.getMessage(), e); // 로그 추가 - ApiResponse apiResponse = ApiResponse.of(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value()); - return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(apiResponse); + ApiResponse apiResponse = ApiResponse.of(e.getMessage(), HttpStatusCode.INTERNAL_SERVER_ERROR); + return ResponseEntity.status(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()).body(apiResponse); + } + + /** + * 모든 예외를 처리하는 범용 핸들러 (위의 예외에 해당하지 않는 경우) + */ + @ExceptionHandler(Exception.class) + public ResponseEntity> handleGenericException(Exception e) { + log.error("Unhandled exception occurred: {}", e.getMessage(), e); + ApiResponse apiResponse = ApiResponse.of("서버 내부에 오류가 발생했습니다.", HttpStatusCode.INTERNAL_SERVER_ERROR); + return ResponseEntity.status(HttpStatusCode.INTERNAL_SERVER_ERROR.getCode()).body(apiResponse); } } diff --git a/cinema-application/src/main/java/com/hanghae/application/dto/ApiResponse.java b/cinema-application/src/main/java/com/hanghae/application/dto/ApiResponse.java index 879026eec..d1bcaca66 100644 --- a/cinema-application/src/main/java/com/hanghae/application/dto/ApiResponse.java +++ b/cinema-application/src/main/java/com/hanghae/application/dto/ApiResponse.java @@ -1,22 +1,23 @@ package com.hanghae.application.dto; import com.fasterxml.jackson.annotation.JsonInclude; +import com.hanghae.application.enums.HttpStatusCode; import java.util.List; @JsonInclude(JsonInclude.Include.NON_NULL) //null값 JSON에서 제외 public record ApiResponse ( String message, - int status, + HttpStatusCode status, T data ){ - public static ApiResponse of(String message, int status) { + public static ApiResponse of(String message, HttpStatusCode status) { return new ApiResponse<>(message, status, null); } - public static ApiResponse of(String message, int status, T data) { + public static ApiResponse of(String message, HttpStatusCode status, T data) { if ((data == null || (data instanceof List list && list.isEmpty())) && (message == null || message.isEmpty())) { - return new ApiResponse<>("조회된 결과가 없습니다.", 200, null); + return new ApiResponse<>("조회된 결과가 없습니다.", HttpStatusCode.OK, null); } return new ApiResponse<>(message, status, data); } diff --git a/cinema-application/src/main/java/com/hanghae/application/enums/HttpStatusCode.java b/cinema-application/src/main/java/com/hanghae/application/enums/HttpStatusCode.java index f20c5cfa4..e60f8b50c 100644 --- a/cinema-application/src/main/java/com/hanghae/application/enums/HttpStatusCode.java +++ b/cinema-application/src/main/java/com/hanghae/application/enums/HttpStatusCode.java @@ -1,10 +1,12 @@ package com.hanghae.application.enums; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Getter; import lombok.RequiredArgsConstructor; @Getter @RequiredArgsConstructor +@JsonFormat(shape = JsonFormat.Shape.OBJECT) // 객체 형태로 변환 (응답받는 곳에서 코드값, 메시지 같이 보여짐) public enum HttpStatusCode { // 2xx: 성공 OK(200, "OK"), diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java index 00ad43246..02db23ea8 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java @@ -69,10 +69,10 @@ public ApiResponse saveMovieReservation(MovieReservationRequestDto request //완료 메시지 전송 (비동기) messagePort.sendMessage("영화 예매가 완료 되었습니다."); - return ApiResponse.of("예매가 완료 되었습니다.", HttpStatusCode.CREATED.getCode()); + return ApiResponse.of("예매가 완료 되었습니다.", HttpStatusCode.CREATED); }); } catch (IllegalStateException e) { - return ApiResponse.of("현재 좌석을 다른 사용자가 예매 처리 중입니다.", HttpStatusCode.CONFLICT.getCode()); + return ApiResponse.of("현재 좌석을 다른 사용자가 예매 처리 중입니다.", HttpStatusCode.CONFLICT); } } } diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java index 343245381..f3978c43f 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java @@ -32,7 +32,7 @@ public ApiResponse> getMovieSchedules() { List schedules = screeningScheduleRepositoryPort.findAll(); List responseDtos = schedules.stream().map(this::convertToDto).collect(Collectors.toList()); - return ApiResponse.of("Success", HttpStatusCode.OK.getCode(), responseDtos); + return ApiResponse.of("Success", HttpStatusCode.OK, responseDtos); } @Override @@ -73,13 +73,13 @@ public ApiResponse> getShowingMovieSchedul .build()); } - return ApiResponse.of("Success", HttpStatusCode.OK.getCode(), new ArrayList<>(movieMap.values())); + return ApiResponse.of("Success", HttpStatusCode.OK, new ArrayList<>(movieMap.values())); } @Override public ApiResponse evictShowingMovieCache() { movieRepositoryPort.evictShowingMovieCache(); - return ApiResponse.of("Success", HttpStatusCode.NO_CONTENT.getCode()); + return ApiResponse.of("Success", HttpStatusCode.NO_CONTENT); } private MovieScheduleResponseDto convertToDto(ScreeningSchedule schedule) { From 38c706c924981f43add45e86cb30383105ac86f4 Mon Sep 17 00:00:00 2001 From: kim keun tae Date: Fri, 31 Jan 2025 23:36:29 +0900 Subject: [PATCH 2/9] =?UTF-8?q?=EC=98=88=EB=A7=A4API=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hanghae/adapter/web/MovieController.java | 8 ------ .../adapter/web/ReservationController.java | 24 ++++++++++++++++++ .../src/main/resources/static/favicon.ico | Bin 0 -> 1150 bytes .../port/out/{ => message}/MessagePort.java | 2 +- .../out/{ => redis}/RedissonLockPort.java | 2 +- .../MemberRepositoryPort.java | 2 +- .../{ => repository}/MovieRepositoryPort.java | 2 +- .../ScreenSeatLayoutRepositoryPort.java | 4 +-- .../ScreeningScheduleRepositoryPort.java | 2 +- .../TicketReservationRepositoryPort.java | 2 +- .../service/MovieReservationServiceImpl.java | 7 ++++- .../service/MovieScheduleServiceImpl.java | 4 +-- .../adapter/{ => message}/MessageAdapter.java | 4 +-- .../{ => redis}/RedissonLockAdapter.java | 4 +-- .../MemberRepositoryAdapter.java | 4 +-- .../MovieRepositoryAdapter.java | 4 +-- .../ScreenSeatLayoutAdapter.java | 7 ++--- .../ScreeningScheduleRepositoryAdapter.java | 8 ++---- .../TicketReservationAdapter.java | 5 ++-- 19 files changed, 53 insertions(+), 42 deletions(-) create mode 100644 cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java create mode 100644 cinema-adapter/src/main/resources/static/favicon.ico rename cinema-application/src/main/java/com/hanghae/application/port/out/{ => message}/MessagePort.java (59%) rename cinema-application/src/main/java/com/hanghae/application/port/out/{ => redis}/RedissonLockPort.java (87%) rename cinema-application/src/main/java/com/hanghae/application/port/out/{ => repository}/MemberRepositoryPort.java (68%) rename cinema-application/src/main/java/com/hanghae/application/port/out/{ => repository}/MovieRepositoryPort.java (86%) rename cinema-application/src/main/java/com/hanghae/application/port/out/{ => repository}/ScreenSeatLayoutRepositoryPort.java (73%) rename cinema-application/src/main/java/com/hanghae/application/port/out/{ => repository}/ScreeningScheduleRepositoryPort.java (79%) rename cinema-application/src/main/java/com/hanghae/application/port/out/{ => repository}/TicketReservationRepositoryPort.java (89%) rename cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/{ => message}/MessageAdapter.java (86%) rename cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/{ => redis}/RedissonLockAdapter.java (96%) rename cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/{ => repository}/MemberRepositoryAdapter.java (83%) rename cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/{ => repository}/MovieRepositoryAdapter.java (96%) rename cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/{ => repository}/ScreenSeatLayoutAdapter.java (84%) rename cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/{ => repository}/ScreeningScheduleRepositoryAdapter.java (75%) rename cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/{ => repository}/TicketReservationAdapter.java (91%) diff --git a/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java b/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java index 17f79ef43..4a51cbdd8 100644 --- a/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java +++ b/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java @@ -13,7 +13,6 @@ @RequestMapping("/api") public class MovieController { private final MovieScheduleService movieScheduleService; - private final MovieReservationService movieReservationService; //영화 상영 시간표 조회 @GetMapping("/v1/movie-schedules") @@ -27,13 +26,6 @@ public ApiResponse> getShowingMovieSchedul return movieScheduleService.getShowingMovieSchedules(requestDto); } - //영화 예약 - // TODO :: 좌석선택API와 영화예약API 분리 - @PostMapping("/v1/movie-reservation") - public ApiResponse saveMovieReservation(@RequestBody MovieReservationRequestDto requestDto) { - return movieReservationService.saveMovieReservation(requestDto); - } - //redis 캐시삭제 (테스트용) @GetMapping("/test/evict-cache") public ApiResponse evictCache() { diff --git a/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java b/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java new file mode 100644 index 000000000..fd37b5162 --- /dev/null +++ b/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java @@ -0,0 +1,24 @@ +package com.hanghae.adapter.web; + +import com.hanghae.application.dto.ApiResponse; +import com.hanghae.application.dto.MovieReservationRequestDto; +import com.hanghae.application.port.in.MovieReservationService; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class ReservationController { + private final MovieReservationService movieReservationService; + + //영화 예약 + // TODO :: 좌석선택API와 영화예약API 분리 + @PostMapping("/v1/movie-reservation") + public ApiResponse saveMovieReservation(@RequestBody MovieReservationRequestDto requestDto) { + return movieReservationService.saveMovieReservation(requestDto); + } +} diff --git a/cinema-adapter/src/main/resources/static/favicon.ico b/cinema-adapter/src/main/resources/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f9f2ebd69319b3151d092e7485bcc941dfe22b3d GIT binary patch literal 1150 zcmZvbdrZ?;6vwaG65}5l|MCx)ko_mVF#FG$&AI&{W}>1AuR>9rM6_BZ!Uj^2hloQ4 z0g52Dv<2GIimgRQoTBJRtgNF&hp+gKQE5w2M`=sZes}K0E}HQB<#W%y=iKi(_mRuk zEc)lqXViYlaz1Bl0b?wdAQyS2{bU%USpU3f#F(0lRv+8Y@SLTqM-wG#uS=pHbyI&v z(o|k|>M4(lNZfqlC8IHubxv?%at!|A9HSpQbYnYsneegfY$L}DXa!8cVAZ;DR*YaL0m!2LXBH!j- z5&CV-FOf?1f9@PXf!U2bd-?uDr1i$8 z=;O9j-Ide%hj?t?=^!e4r_gABkIrr@I;>VyUXDP~^A2)~$!LyLKth8pke&(S9oe{Xc-gH4eRV94!vu*FK=|+>}^Dre-XV(&GM}-#^#yw}cmFsoY&s z<&#L0eUh{hs2r0xaXpA8g7=#SfWtjuNa~+Nl9kWTq_z4Ma=qLXWOR;fiNqYgT7Dta zY!5)$KLJV2FcK@AbZ3Kfr#Dg4=SOKz5UXT=gqEh8;SEx%?+KEs?qGeX1I1@OsJs}!))LFzA9pr=ks#MapAb9OR>aP04lJ^C){W=~ z-=fv|p4JdR!w2fF`O)&%6l$-$g;C#lU29 literal 0 HcmV?d00001 diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/MessagePort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/message/MessagePort.java similarity index 59% rename from cinema-application/src/main/java/com/hanghae/application/port/out/MessagePort.java rename to cinema-application/src/main/java/com/hanghae/application/port/out/message/MessagePort.java index 0c0829145..8cf839cbc 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/MessagePort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/message/MessagePort.java @@ -1,4 +1,4 @@ -package com.hanghae.application.port.out; +package com.hanghae.application.port.out.message; public interface MessagePort { void sendMessage(String message); diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/RedissonLockPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedissonLockPort.java similarity index 87% rename from cinema-application/src/main/java/com/hanghae/application/port/out/RedissonLockPort.java rename to cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedissonLockPort.java index 748c92d6b..b0808d9da 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/RedissonLockPort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedissonLockPort.java @@ -1,4 +1,4 @@ -package com.hanghae.application.port.out; +package com.hanghae.application.port.out.redis; import com.hanghae.domain.model.enums.ScreenSeat; diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/MemberRepositoryPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/MemberRepositoryPort.java similarity index 68% rename from cinema-application/src/main/java/com/hanghae/application/port/out/MemberRepositoryPort.java rename to cinema-application/src/main/java/com/hanghae/application/port/out/repository/MemberRepositoryPort.java index 7b0d97472..a38ec96be 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/MemberRepositoryPort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/MemberRepositoryPort.java @@ -1,4 +1,4 @@ -package com.hanghae.application.port.out; +package com.hanghae.application.port.out.repository; import com.hanghae.domain.model.Member; diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/MovieRepositoryPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/MovieRepositoryPort.java similarity index 86% rename from cinema-application/src/main/java/com/hanghae/application/port/out/MovieRepositoryPort.java rename to cinema-application/src/main/java/com/hanghae/application/port/out/repository/MovieRepositoryPort.java index e8f7a68d8..213e849ea 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/MovieRepositoryPort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/MovieRepositoryPort.java @@ -1,4 +1,4 @@ -package com.hanghae.application.port.out; +package com.hanghae.application.port.out.repository; import com.hanghae.application.dto.MovieScheduleRequestDto; import com.hanghae.application.projection.MovieScheduleProjection; diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/ScreenSeatLayoutRepositoryPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/ScreenSeatLayoutRepositoryPort.java similarity index 73% rename from cinema-application/src/main/java/com/hanghae/application/port/out/ScreenSeatLayoutRepositoryPort.java rename to cinema-application/src/main/java/com/hanghae/application/port/out/repository/ScreenSeatLayoutRepositoryPort.java index 429f50602..86d24369a 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/ScreenSeatLayoutRepositoryPort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/ScreenSeatLayoutRepositoryPort.java @@ -1,9 +1,7 @@ -package com.hanghae.application.port.out; +package com.hanghae.application.port.out.repository; import com.hanghae.domain.model.ScreenSeatLayout; -import java.util.List; - public interface ScreenSeatLayoutRepositoryPort { ScreenSeatLayout findBySeatRowAndScreenId(String seatRow, Long screenId); } diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/ScreeningScheduleRepositoryPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/ScreeningScheduleRepositoryPort.java similarity index 79% rename from cinema-application/src/main/java/com/hanghae/application/port/out/ScreeningScheduleRepositoryPort.java rename to cinema-application/src/main/java/com/hanghae/application/port/out/repository/ScreeningScheduleRepositoryPort.java index dad904472..c829a888c 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/ScreeningScheduleRepositoryPort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/ScreeningScheduleRepositoryPort.java @@ -1,4 +1,4 @@ -package com.hanghae.application.port.out; +package com.hanghae.application.port.out.repository; import com.hanghae.domain.model.ScreeningSchedule; diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/TicketReservationRepositoryPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/TicketReservationRepositoryPort.java similarity index 89% rename from cinema-application/src/main/java/com/hanghae/application/port/out/TicketReservationRepositoryPort.java rename to cinema-application/src/main/java/com/hanghae/application/port/out/repository/TicketReservationRepositoryPort.java index 6566ef747..b859b3d06 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/TicketReservationRepositoryPort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/TicketReservationRepositoryPort.java @@ -1,4 +1,4 @@ -package com.hanghae.application.port.out; +package com.hanghae.application.port.out.repository; import com.hanghae.domain.model.TicketReservation; import com.hanghae.domain.model.enums.ScreenSeat; diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java index 02db23ea8..9d1c82e4d 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java @@ -4,7 +4,12 @@ import com.hanghae.application.dto.MovieReservationRequestDto; import com.hanghae.application.enums.HttpStatusCode; import com.hanghae.application.port.in.MovieReservationService; -import com.hanghae.application.port.out.*; +import com.hanghae.application.port.out.message.MessagePort; +import com.hanghae.application.port.out.redis.RedissonLockPort; +import com.hanghae.application.port.out.repository.MemberRepositoryPort; +import com.hanghae.application.port.out.repository.ScreenSeatLayoutRepositoryPort; +import com.hanghae.application.port.out.repository.ScreeningScheduleRepositoryPort; +import com.hanghae.application.port.out.repository.TicketReservationRepositoryPort; import com.hanghae.domain.model.Member; import com.hanghae.domain.model.ScreenSeatLayout; import com.hanghae.domain.model.ScreeningSchedule; diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java index f3978c43f..1a1e77d36 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java @@ -6,8 +6,8 @@ import com.hanghae.application.dto.ShowingMovieScheduleResponseDto; import com.hanghae.application.enums.HttpStatusCode; import com.hanghae.application.port.in.MovieScheduleService; -import com.hanghae.application.port.out.MovieRepositoryPort; -import com.hanghae.application.port.out.ScreeningScheduleRepositoryPort; +import com.hanghae.application.port.out.repository.MovieRepositoryPort; +import com.hanghae.application.port.out.repository.ScreeningScheduleRepositoryPort; import com.hanghae.application.projection.MovieScheduleProjection; import com.hanghae.domain.model.Movie; import com.hanghae.domain.model.ScreeningSchedule; diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MessageAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/message/MessageAdapter.java similarity index 86% rename from cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MessageAdapter.java rename to cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/message/MessageAdapter.java index fe6baa2f4..0064a55e9 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MessageAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/message/MessageAdapter.java @@ -1,6 +1,6 @@ -package com.hanghae.infrastructure.adapter; +package com.hanghae.infrastructure.adapter.message; -import com.hanghae.application.port.out.MessagePort; +import com.hanghae.application.port.out.message.MessagePort; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/RedissonLockAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedissonLockAdapter.java similarity index 96% rename from cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/RedissonLockAdapter.java rename to cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedissonLockAdapter.java index 832080783..11666f144 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/RedissonLockAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedissonLockAdapter.java @@ -1,6 +1,6 @@ -package com.hanghae.infrastructure.adapter; +package com.hanghae.infrastructure.adapter.redis; -import com.hanghae.application.port.out.RedissonLockPort; +import com.hanghae.application.port.out.redis.RedissonLockPort; import com.hanghae.domain.model.enums.ScreenSeat; import lombok.RequiredArgsConstructor; import org.redisson.api.RLock; diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MemberRepositoryAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MemberRepositoryAdapter.java similarity index 83% rename from cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MemberRepositoryAdapter.java rename to cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MemberRepositoryAdapter.java index 1d3100bb5..176576dcd 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MemberRepositoryAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MemberRepositoryAdapter.java @@ -1,6 +1,6 @@ -package com.hanghae.infrastructure.adapter; +package com.hanghae.infrastructure.adapter.repository; -import com.hanghae.application.port.out.MemberRepositoryPort; +import com.hanghae.application.port.out.repository.MemberRepositoryPort; import com.hanghae.domain.model.Member; import com.hanghae.infrastructure.mapper.MemberMapper; import com.hanghae.infrastructure.repository.MemberRepositoryJpa; diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MovieRepositoryAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MovieRepositoryAdapter.java similarity index 96% rename from cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MovieRepositoryAdapter.java rename to cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MovieRepositoryAdapter.java index eb4e5b606..7e9900919 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/MovieRepositoryAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MovieRepositoryAdapter.java @@ -1,7 +1,7 @@ -package com.hanghae.infrastructure.adapter; +package com.hanghae.infrastructure.adapter.repository; import com.hanghae.application.dto.MovieScheduleRequestDto; -import com.hanghae.application.port.out.MovieRepositoryPort; +import com.hanghae.application.port.out.repository.MovieRepositoryPort; import com.hanghae.application.projection.MovieScheduleProjection; import com.hanghae.infrastructure.config.RedisCacheName; import com.hanghae.infrastructure.entity.*; diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/ScreenSeatLayoutAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/ScreenSeatLayoutAdapter.java similarity index 84% rename from cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/ScreenSeatLayoutAdapter.java rename to cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/ScreenSeatLayoutAdapter.java index a9994fa3f..a198171ec 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/ScreenSeatLayoutAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/ScreenSeatLayoutAdapter.java @@ -1,6 +1,6 @@ -package com.hanghae.infrastructure.adapter; +package com.hanghae.infrastructure.adapter.repository; -import com.hanghae.application.port.out.ScreenSeatLayoutRepositoryPort; +import com.hanghae.application.port.out.repository.ScreenSeatLayoutRepositoryPort; import com.hanghae.domain.model.ScreenSeatLayout; import com.hanghae.infrastructure.entity.ScreenSeatLayoutEntity; import com.hanghae.infrastructure.mapper.ScreenSeatLayoutMapper; @@ -8,9 +8,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; -import java.util.List; -import java.util.stream.Collectors; - @Component @RequiredArgsConstructor public class ScreenSeatLayoutAdapter implements ScreenSeatLayoutRepositoryPort { diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/ScreeningScheduleRepositoryAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/ScreeningScheduleRepositoryAdapter.java similarity index 75% rename from cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/ScreeningScheduleRepositoryAdapter.java rename to cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/ScreeningScheduleRepositoryAdapter.java index 0b7eccf88..4cd9cd578 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/ScreeningScheduleRepositoryAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/ScreeningScheduleRepositoryAdapter.java @@ -1,12 +1,8 @@ -package com.hanghae.infrastructure.adapter; +package com.hanghae.infrastructure.adapter.repository; -import com.hanghae.application.port.out.ScreeningScheduleRepositoryPort; -import com.hanghae.domain.model.Movie; -import com.hanghae.domain.model.Screen; +import com.hanghae.application.port.out.repository.ScreeningScheduleRepositoryPort; import com.hanghae.domain.model.ScreeningSchedule; -import com.hanghae.infrastructure.entity.ScreeningScheduleEntity; import com.hanghae.infrastructure.mapper.ScreeningScheduleMapper; -import com.hanghae.infrastructure.mapper.UploadFileMapper; import com.hanghae.infrastructure.repository.ScreeningScheduleRepositoryJpa; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/TicketReservationAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/TicketReservationAdapter.java similarity index 91% rename from cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/TicketReservationAdapter.java rename to cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/TicketReservationAdapter.java index 55bfa8dc9..c9888c9f7 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/TicketReservationAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/TicketReservationAdapter.java @@ -1,7 +1,6 @@ -package com.hanghae.infrastructure.adapter; +package com.hanghae.infrastructure.adapter.repository; -import com.hanghae.application.port.out.TicketReservationRepositoryPort; -import com.hanghae.domain.model.ScreenSeatLayout; +import com.hanghae.application.port.out.repository.TicketReservationRepositoryPort; import com.hanghae.domain.model.TicketReservation; import com.hanghae.domain.model.enums.ScreenSeat; import com.hanghae.infrastructure.entity.TicketReservationEntity; From 05357857514af3242f7927124de5edf4165bc3bb Mon Sep 17 00:00:00 2001 From: kim keun tae Date: Sat, 1 Feb 2025 12:22:21 +0900 Subject: [PATCH 3/9] =?UTF-8?q?=EC=98=81=ED=99=94=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EB=B0=8F=20=EC=98=88=EB=A7=A4=EB=A1=9C=EC=A7=81=20RateLimit=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 +- .../hanghae/adapter/web/MovieController.java | 11 ++- .../application/enums/HttpStatusCode.java | 53 +++++++++++- .../port/in/MovieScheduleService.java | 2 +- .../port/out/redis/RedisRateLimitPort.java | 6 ++ .../service/MovieReservationServiceImpl.java | 7 ++ .../service/MovieScheduleServiceImpl.java | 9 +- .../adapter/redis/RedisRateLimitAdapter.java | 85 +++++++++++++++++++ .../infrastructure/lua/LuaScriptLoader.java | 23 +++++ .../resources/lua/reservationRateLimit.lua | 10 +++ .../main/resources/lua/searchRateLimit.lua | 27 ++++++ 11 files changed, 233 insertions(+), 7 deletions(-) create mode 100644 cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedisRateLimitPort.java create mode 100644 cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedisRateLimitAdapter.java create mode 100644 cinema-infrastructure/src/main/java/com/hanghae/infrastructure/lua/LuaScriptLoader.java create mode 100644 cinema-infrastructure/src/main/resources/lua/reservationRateLimit.lua create mode 100644 cinema-infrastructure/src/main/resources/lua/searchRateLimit.lua diff --git a/README.md b/README.md index b8f0604e4..7e143972c 100644 --- a/README.md +++ b/README.md @@ -471,7 +471,12 @@ constant_load ✓ [======================================] 000/100 VUs 10m0s 1 * 로그 확인 : $docker-compose logs -f // `-f`옵션을 주면 실시간 * 특정 서비스 시작 : $docker-compose start <서비스 이름> * 특정 서비스 종료 : $docker-compose stop <서비스 이름> - + * redis 접속 : docker exec -it redis_cinema redis-cli // redis_cinema = 컨테이너명 + * redis 비밀번호 있는 경우 위 명령어 후 : AUTH 비밀번호 + * 현재 존재하는 키 전체보기 : KEYS * + * 특정키 조회 : KEYS rate_limit:0:0:0:0:0:0:0:1 + * 특정 패턴 조회 : KEYS rate_limit:* + * 모든키 삭제 : FLUSHALL -------------------------------------------------------------- ### 적용 아키텍처 diff --git a/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java b/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java index 4a51cbdd8..20aa8adb2 100644 --- a/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java +++ b/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java @@ -1,8 +1,8 @@ package com.hanghae.adapter.web; import com.hanghae.application.dto.*; -import com.hanghae.application.port.in.MovieReservationService; import com.hanghae.application.port.in.MovieScheduleService; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; @@ -22,8 +22,13 @@ public ApiResponse> getMovieSchedules() { //영화별 상영 시간표 조회 (grouping) @GetMapping("/v2/movie-schedules") - public ApiResponse> getShowingMovieSchedules(@ModelAttribute MovieScheduleRequestDto requestDto) { - return movieScheduleService.getShowingMovieSchedules(requestDto); + public ApiResponse> getShowingMovieSchedules(@ModelAttribute MovieScheduleRequestDto requestDto, HttpServletRequest request) { + String ip = request.getHeader("X-Forwarded-For"); + if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + + return movieScheduleService.getShowingMovieSchedules(requestDto, ip); } //redis 캐시삭제 (테스트용) diff --git a/cinema-application/src/main/java/com/hanghae/application/enums/HttpStatusCode.java b/cinema-application/src/main/java/com/hanghae/application/enums/HttpStatusCode.java index e60f8b50c..2bfeaef7f 100644 --- a/cinema-application/src/main/java/com/hanghae/application/enums/HttpStatusCode.java +++ b/cinema-application/src/main/java/com/hanghae/application/enums/HttpStatusCode.java @@ -8,26 +8,77 @@ @RequiredArgsConstructor @JsonFormat(shape = JsonFormat.Shape.OBJECT) // 객체 형태로 변환 (응답받는 곳에서 코드값, 메시지 같이 보여짐) public enum HttpStatusCode { + // 1xx: Informational + CONTINUE(100, "Continue"), + SWITCHING_PROTOCOLS(101, "Switching Protocols"), + PROCESSING(102, "Processing"), + EARLY_HINTS(103, "Early Hints"), + // 2xx: 성공 OK(200, "OK"), CREATED(201, "Created"), ACCEPTED(202, "Accepted"), + NON_AUTHORITATIVE_INFORMATION(203, "Non-Authoritative Information"), NO_CONTENT(204, "No Content"), + RESET_CONTENT(205, "Reset Content"), + PARTIAL_CONTENT(206, "Partial Content"), + MULTI_STATUS(207, "Multi-Status"), + ALREADY_REPORTED(208, "Already Reported"), + IM_USED(226, "IM Used"), + + // 3xx: Redirection + MULTIPLE_CHOICES(300, "Multiple Choices"), + MOVED_PERMANENTLY(301, "Moved Permanently"), + FOUND(302, "Found"), + SEE_OTHER(303, "See Other"), + NOT_MODIFIED(304, "Not Modified"), + USE_PROXY(305, "Use Proxy"), + TEMPORARY_REDIRECT(307, "Temporary Redirect"), + PERMANENT_REDIRECT(308, "Permanent Redirect"), // 4xx: 클라이언트 오류 BAD_REQUEST(400, "Bad Request"), UNAUTHORIZED(401, "Unauthorized"), + PAYMENT_REQUIRED(402, "Payment Required"), FORBIDDEN(403, "Forbidden"), NOT_FOUND(404, "Not Found"), METHOD_NOT_ALLOWED(405, "Method Not Allowed"), + NOT_ACCEPTABLE(406, "Not Acceptable"), + PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required"), + REQUEST_TIMEOUT(408, "Request Timeout"), CONFLICT(409, "Conflict"), + GONE(410, "Gone"), + LENGTH_REQUIRED(411, "Length Required"), + PRECONDITION_FAILED(412, "Precondition Failed"), + PAYLOAD_TOO_LARGE(413, "Payload Too Large"), + URI_TOO_LONG(414, "URI Too Long"), + UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"), + RANGE_NOT_SATISFIABLE(416, "Range Not Satisfiable"), + EXPECTATION_FAILED(417, "Expectation Failed"), + I_AM_A_TEAPOT(418, "I'm a teapot"), + MISDIRECTED_REQUEST(421, "Misdirected Request"), UNPROCESSABLE_ENTITY(422, "Unprocessable Entity"), + LOCKED(423, "Locked"), + FAILED_DEPENDENCY(424, "Failed Dependency"), + TOO_EARLY(425, "Too Early"), + UPGRADE_REQUIRED(426, "Upgrade Required"), + PRECONDITION_REQUIRED(428, "Precondition Required"), + TOO_MANY_REQUESTS(429, "Too Many Requests"), + REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large"), + UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons"), // 5xx: 서버 오류 INTERNAL_SERVER_ERROR(500, "Internal Server Error"), NOT_IMPLEMENTED(501, "Not Implemented"), + BAD_GATEWAY(502, "Bad Gateway"), SERVICE_UNAVAILABLE(503, "Service Unavailable"), - GATEWAY_TIMEOUT(504, "Gateway Timeout"); + GATEWAY_TIMEOUT(504, "Gateway Timeout"), + HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version Not Supported"), + VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates"), + INSUFFICIENT_STORAGE(507, "Insufficient Storage"), + LOOP_DETECTED(508, "Loop Detected"), + NOT_EXTENDED(510, "Not Extended"), + NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required"); private final int code; private final String message; diff --git a/cinema-application/src/main/java/com/hanghae/application/port/in/MovieScheduleService.java b/cinema-application/src/main/java/com/hanghae/application/port/in/MovieScheduleService.java index 785dfa71f..8b2677223 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/in/MovieScheduleService.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/in/MovieScheduleService.java @@ -9,6 +9,6 @@ public interface MovieScheduleService { ApiResponse> getMovieSchedules(); - ApiResponse> getShowingMovieSchedules(MovieScheduleRequestDto requestDto); + ApiResponse> getShowingMovieSchedules(MovieScheduleRequestDto requestDto, String ip); ApiResponse evictShowingMovieCache(); } diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedisRateLimitPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedisRateLimitPort.java new file mode 100644 index 000000000..5bebef1e3 --- /dev/null +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedisRateLimitPort.java @@ -0,0 +1,6 @@ +package com.hanghae.application.port.out.redis; + +public interface RedisRateLimitPort { + boolean isAllowed(String ip); + boolean canReserve(Long scheduleId, Long memberId); +} diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java index 9d1c82e4d..31999168a 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java @@ -5,6 +5,7 @@ import com.hanghae.application.enums.HttpStatusCode; import com.hanghae.application.port.in.MovieReservationService; import com.hanghae.application.port.out.message.MessagePort; +import com.hanghae.application.port.out.redis.RedisRateLimitPort; import com.hanghae.application.port.out.redis.RedissonLockPort; import com.hanghae.application.port.out.repository.MemberRepositoryPort; import com.hanghae.application.port.out.repository.ScreenSeatLayoutRepositoryPort; @@ -32,6 +33,7 @@ public class MovieReservationServiceImpl implements MovieReservationService { private final MessagePort messagePort; private final ReservationService reservationService; private final RedissonLockPort redissonLockPort; // Redisson 분산락 사용 + private final RedisRateLimitPort redisRateLimitPort; @Override @Transactional @@ -41,6 +43,11 @@ public ApiResponse saveMovieReservation(MovieReservationRequestDto request int seatCount = requestDto.seatCount(); ScreenSeat screenSeat = requestDto.screenSeat(); + //동 시간대의 영화를 5분에 1번씩 예매 제한 + if (!redisRateLimitPort.canReserve(scheduleId, memberId)) { + return ApiResponse.of("동일 시간대 영화 예매은 5분 후 가능합니다.", HttpStatusCode.TOO_MANY_REQUESTS); + } + // 예매할 좌석 목록 가져오기 List selectedSeats = ScreenSeat.getSelectedConnectedSeats(screenSeat, seatCount); diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java index 1a1e77d36..e41c83bb3 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java @@ -6,6 +6,7 @@ import com.hanghae.application.dto.ShowingMovieScheduleResponseDto; import com.hanghae.application.enums.HttpStatusCode; import com.hanghae.application.port.in.MovieScheduleService; +import com.hanghae.application.port.out.redis.RedisRateLimitPort; import com.hanghae.application.port.out.repository.MovieRepositoryPort; import com.hanghae.application.port.out.repository.ScreeningScheduleRepositoryPort; import com.hanghae.application.projection.MovieScheduleProjection; @@ -25,6 +26,7 @@ public class MovieScheduleServiceImpl implements MovieScheduleService { private final ScreeningScheduleRepositoryPort screeningScheduleRepositoryPort; private final MovieRepositoryPort movieRepositoryPort; + private final RedisRateLimitPort redisRateLimitPort; @Override @Transactional @@ -37,7 +39,12 @@ public ApiResponse> getMovieSchedules() { @Override @Transactional - public ApiResponse> getShowingMovieSchedules(MovieScheduleRequestDto requestDto) { + public ApiResponse> getShowingMovieSchedules(MovieScheduleRequestDto requestDto, String ip) { + //1분에 50회 이상 조회시 조회 제한 + if (!redisRateLimitPort.isAllowed(ip)) { + return ApiResponse.of("너무 많은 요청으로 조회가 차단되었습니다. ", HttpStatusCode.TOO_MANY_REQUESTS); + } + List projections = movieRepositoryPort.findShowingMovieSchedules(requestDto); Map movieMap = new LinkedHashMap<>(); diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedisRateLimitAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedisRateLimitAdapter.java new file mode 100644 index 000000000..05503d350 --- /dev/null +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedisRateLimitAdapter.java @@ -0,0 +1,85 @@ +package com.hanghae.infrastructure.adapter.redis; + +import com.hanghae.application.port.out.redis.RedisRateLimitPort; +import com.hanghae.infrastructure.lua.LuaScriptLoader; +import lombok.RequiredArgsConstructor; +import org.redisson.api.RScript; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.script.DefaultRedisScript; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.Arrays; +import java.util.Collections; + +@Component +@RequiredArgsConstructor +public class RedisRateLimitAdapter implements RedisRateLimitPort { + private final RedisTemplate redisTemplate; + + /** + * 비정상적 사용 패턴을 감지하고 시스템을 보호하기 위해 + * 1분 내 50회 이상 요청 시 1시간 동안 해당 IP 를 차단 + */ + public boolean isAllowed(String ip) { + String luaScriptPath = "lua/searchRateLimit.lua"; + int maxRequest = 50; // 최대 요청 횟수 + int expireTime = 60; // 요청 카운트 만료 시간 (초) + int blockTime = 3600; // 차단 시간 (초) + + String requestKey = "rate_limit:" + ip; // 요청 카운트 키 + String blockKey = "blocked_ip:" + ip; // 차단된 IP 키 + + //lua script 가져오기 + String luaScript = LuaScriptLoader.loadScript(luaScriptPath); + + DefaultRedisScript script = new DefaultRedisScript<>(); + script.setScriptText(luaScript); + script.setResultType(Long.class); + + Long result = redisTemplate.execute( + script, + Arrays.asList(requestKey, blockKey), // KEYS[1], KEYS[2] + String.valueOf(maxRequest), // ARGV[1] + String.valueOf(expireTime), // ARGV[2] + String.valueOf(blockTime) // ARGV[3] + ); + + return result != null && result == 1; + } + + /** + * 같은 시간대의 영화는 유저당 5분에 1번씩만 예매 가능 + */ + @Override + public boolean canReserve(Long scheduleId, Long memberId) { + String luaScriptPath = "lua/reservationRateLimit.lua"; + int reservationCooldownSecound = 300; // 예약 제한 시간 (초) + String key = "reservation_limit:" + scheduleId + ":" + memberId; // 레디스 키 + + //lua script 가져오기 + String luaScript = LuaScriptLoader.loadScript(luaScriptPath); + + DefaultRedisScript script = new DefaultRedisScript<>(); + script.setScriptText(luaScript); + script.setResultType(Long.class); + + Long result = redisTemplate.execute( + script, + Collections.singletonList(key), // KEYS[1] + String.valueOf(reservationCooldownSecound) // ARGV[1] + ); + + return result != null && result == 1; + + /* + //lua script 없이 아래 방법으로도 가능 + + Boolean isSet = redisTemplate.opsForValue().setIfAbsent( + key, "1", Duration.ofSeconds(reservationCooldownSecound)); + //해당 키가 이미 존재하면 아무것도 하지 않고 false를 반환 + + return Boolean.TRUE.equals(isSet); // 값이 설정되었다면 예약 가능 + */ + } +} diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/lua/LuaScriptLoader.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/lua/LuaScriptLoader.java new file mode 100644 index 000000000..e25f6fd64 --- /dev/null +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/lua/LuaScriptLoader.java @@ -0,0 +1,23 @@ +package com.hanghae.infrastructure.lua; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; + +public class LuaScriptLoader { + public static String loadScript(String resourcePath) { + try (InputStream inputStream = LuaScriptLoader.class.getClassLoader().getResourceAsStream(resourcePath); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { + + if (inputStream == null) { + throw new RuntimeException("Lua script not found: " + resourcePath); + } + + return reader.lines().collect(Collectors.joining("\n")); + } catch (Exception e) { + throw new RuntimeException("Failed to load Lua script: " + resourcePath, e); + } + } +} diff --git a/cinema-infrastructure/src/main/resources/lua/reservationRateLimit.lua b/cinema-infrastructure/src/main/resources/lua/reservationRateLimit.lua new file mode 100644 index 000000000..ec0407cb2 --- /dev/null +++ b/cinema-infrastructure/src/main/resources/lua/reservationRateLimit.lua @@ -0,0 +1,10 @@ +-- 예약 제한 (유저 기준) +local key = KEYS[1] -- 예약 키 (scheduleId + memberId) +local lockTime = tonumber(ARGV[1]) -- 예약 제한 시간 (초) + +-- 이미 예약된 경우 차단 +if redis.call("exists", key) == 1 then return 0 end + +-- 예약 가능 시 만료 시간 설정 +redis.call("setex", key, lockTime, "RESERVED") +return 1 \ No newline at end of file diff --git a/cinema-infrastructure/src/main/resources/lua/searchRateLimit.lua b/cinema-infrastructure/src/main/resources/lua/searchRateLimit.lua new file mode 100644 index 000000000..e9f81e7fc --- /dev/null +++ b/cinema-infrastructure/src/main/resources/lua/searchRateLimit.lua @@ -0,0 +1,27 @@ +--[[ redis 디버깅 로그 출력 +redis.log(redis.LOG_NOTICE, "maxRequests: " .. tostring(ARGV[1])) +redis.log(redis.LOG_NOTICE, "expireTime: " .. tostring(ARGV[2])) +redis.log(redis.LOG_NOTICE, "blockTime: " .. tostring(ARGV[3])) +]] + +--[[ 요청 제한 (IP 기반) ]] +local key = KEYS[1] --[[ 요청 카운트 키 ]] +local blockKey = KEYS[2] --[[ 차단된 IP 키 ]] +local maxRequests = tonumber(ARGV[1]) --[[ 최대 요청 횟수 (초) ]] +local expireTime = tonumber(ARGV[2]) --[[ 요청 카운트 만료 시간 (초) ]] +local blockTime = tonumber(ARGV[3]) --[[ 차단 시간 (초) ]] + +--[[ 차단 여부 확인 ]] +if redis.call("exists", blockKey) == 1 then return 0 end + +--[[ 요청 카운트 증가 및 만료 시간 설정 ]] +local count = redis.call("incr", key) +if count == 1 then redis.call("expire", key, expireTime) end + +--[[ 요청 제한 초과 시 차단 ]] +if count > maxRequests then + redis.call("setex", blockKey, blockTime, "BLOCKED") + return 0 +end + +return 1 \ No newline at end of file From e71d8df5fd5f4557bc1c7a46b8e03a4cdfbc04d0 Mon Sep 17 00:00:00 2001 From: kim keun tae Date: Sat, 1 Feb 2025 13:11:33 +0900 Subject: [PATCH 4/9] =?UTF-8?q?=EC=98=88=EB=A7=A4=20=EC=8B=9C=EB=8F=84=20?= =?UTF-8?q?=EB=B0=8F=20=EC=99=84=EB=A3=8C=20=ED=9B=84=20RateLimit=20=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../port/out/redis/RedisRateLimitPort.java | 2 ++ .../service/MovieReservationServiceImpl.java | 3 +++ .../adapter/redis/RedisRateLimitAdapter.java | 26 ++++++++++++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedisRateLimitPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedisRateLimitPort.java index 5bebef1e3..1167dce4c 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedisRateLimitPort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/redis/RedisRateLimitPort.java @@ -2,5 +2,7 @@ public interface RedisRateLimitPort { boolean isAllowed(String ip); + boolean tryReserveWithLimit(Long scheduleId, Long memberId); boolean canReserve(Long scheduleId, Long memberId); + void setReservationLimit(Long scheduleId, Long memberId); } diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java index 31999168a..8810224ed 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java @@ -78,6 +78,9 @@ public ApiResponse saveMovieReservation(MovieReservationRequestDto request // 예매 내역 저장 ticketReservationRepositoryPort.saveMovieReservations(ticketReservations); + // 예매 성공 후 Redis 제한 설정 + redisRateLimitPort.setReservationLimit(scheduleId, memberId); + //완료 메시지 전송 (비동기) messagePort.sendMessage("영화 예매가 완료 되었습니다."); diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedisRateLimitAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedisRateLimitAdapter.java index 05503d350..a4a360482 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedisRateLimitAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/redis/RedisRateLimitAdapter.java @@ -50,9 +50,10 @@ public boolean isAllowed(String ip) { /** * 같은 시간대의 영화는 유저당 5분에 1번씩만 예매 가능 + * (체크와 동시에 키생성) */ @Override - public boolean canReserve(Long scheduleId, Long memberId) { + public boolean tryReserveWithLimit(Long scheduleId, Long memberId) { String luaScriptPath = "lua/reservationRateLimit.lua"; int reservationCooldownSecound = 300; // 예약 제한 시간 (초) String key = "reservation_limit:" + scheduleId + ":" + memberId; // 레디스 키 @@ -82,4 +83,27 @@ public boolean canReserve(Long scheduleId, Long memberId) { return Boolean.TRUE.equals(isSet); // 값이 설정되었다면 예약 가능 */ } + + /** + * 5분 제한 여부 확인 (제한된 경우 false 반환) + */ + @Override + public boolean canReserve(Long scheduleId, Long memberId) { + String key = getReservationKey(scheduleId, memberId); + return Boolean.FALSE.equals(redisTemplate.hasKey(key)); // 키가 없으면 예약 가능 + } + + /** + * 예매 성공 후 5분 제한 설정 + */ + @Override + public void setReservationLimit(Long scheduleId, Long memberId) { + String key = getReservationKey(scheduleId, memberId); + int reservationCooldownSecound = 300; // 예약 제한 시간 (초) + redisTemplate.opsForValue().set(key, "1", Duration.ofSeconds(reservationCooldownSecound)); + } + + private String getReservationKey(Long scheduleId, Long memberId) { + return "reservation_limit:" + scheduleId + ":" + memberId; + } } From 43b5a39838655285e6247eb1951fc53ab7aa13a4 Mon Sep 17 00:00:00 2001 From: kim keun tae Date: Sat, 1 Feb 2025 13:15:04 +0900 Subject: [PATCH 5/9] =?UTF-8?q?dto=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/hanghae/adapter/web/MovieController.java | 3 +++ .../java/com/hanghae/adapter/web/ReservationController.java | 2 +- .../dto/{ => request}/MovieReservationRequestDto.java | 2 +- .../dto/{ => request}/MovieScheduleRequestDto.java | 2 +- .../dto/{ => response}/MovieScheduleResponseDto.java | 2 +- .../dto/{ => response}/ShowingMovieScheduleResponseDto.java | 2 +- .../application/port/in/MovieReservationService.java | 2 +- .../hanghae/application/port/in/MovieScheduleService.java | 6 +++--- .../port/out/repository/MovieRepositoryPort.java | 2 +- .../application/service/MovieReservationServiceImpl.java | 2 +- .../application/service/MovieScheduleServiceImpl.java | 6 +++--- .../adapter/repository/MovieRepositoryAdapter.java | 2 +- 12 files changed, 18 insertions(+), 15 deletions(-) rename cinema-application/src/main/java/com/hanghae/application/dto/{ => request}/MovieReservationRequestDto.java (93%) rename cinema-application/src/main/java/com/hanghae/application/dto/{ => request}/MovieScheduleRequestDto.java (96%) rename cinema-application/src/main/java/com/hanghae/application/dto/{ => response}/MovieScheduleResponseDto.java (91%) rename cinema-application/src/main/java/com/hanghae/application/dto/{ => response}/ShowingMovieScheduleResponseDto.java (96%) diff --git a/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java b/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java index 20aa8adb2..fe36df5fa 100644 --- a/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java +++ b/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java @@ -1,6 +1,9 @@ package com.hanghae.adapter.web; import com.hanghae.application.dto.*; +import com.hanghae.application.dto.request.MovieScheduleRequestDto; +import com.hanghae.application.dto.response.MovieScheduleResponseDto; +import com.hanghae.application.dto.response.ShowingMovieScheduleResponseDto; import com.hanghae.application.port.in.MovieScheduleService; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; diff --git a/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java b/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java index fd37b5162..041510d90 100644 --- a/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java +++ b/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java @@ -1,7 +1,7 @@ package com.hanghae.adapter.web; import com.hanghae.application.dto.ApiResponse; -import com.hanghae.application.dto.MovieReservationRequestDto; +import com.hanghae.application.dto.request.MovieReservationRequestDto; import com.hanghae.application.port.in.MovieReservationService; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.PostMapping; diff --git a/cinema-application/src/main/java/com/hanghae/application/dto/MovieReservationRequestDto.java b/cinema-application/src/main/java/com/hanghae/application/dto/request/MovieReservationRequestDto.java similarity index 93% rename from cinema-application/src/main/java/com/hanghae/application/dto/MovieReservationRequestDto.java rename to cinema-application/src/main/java/com/hanghae/application/dto/request/MovieReservationRequestDto.java index fabc48631..523582cb8 100644 --- a/cinema-application/src/main/java/com/hanghae/application/dto/MovieReservationRequestDto.java +++ b/cinema-application/src/main/java/com/hanghae/application/dto/request/MovieReservationRequestDto.java @@ -1,4 +1,4 @@ -package com.hanghae.application.dto; +package com.hanghae.application.dto.request; import com.hanghae.domain.model.enums.ScreenSeat; diff --git a/cinema-application/src/main/java/com/hanghae/application/dto/MovieScheduleRequestDto.java b/cinema-application/src/main/java/com/hanghae/application/dto/request/MovieScheduleRequestDto.java similarity index 96% rename from cinema-application/src/main/java/com/hanghae/application/dto/MovieScheduleRequestDto.java rename to cinema-application/src/main/java/com/hanghae/application/dto/request/MovieScheduleRequestDto.java index d7962e887..1ebb07fcc 100644 --- a/cinema-application/src/main/java/com/hanghae/application/dto/MovieScheduleRequestDto.java +++ b/cinema-application/src/main/java/com/hanghae/application/dto/request/MovieScheduleRequestDto.java @@ -1,4 +1,4 @@ -package com.hanghae.application.dto; +package com.hanghae.application.dto.request; import com.hanghae.domain.model.enums.MovieGenre; diff --git a/cinema-application/src/main/java/com/hanghae/application/dto/MovieScheduleResponseDto.java b/cinema-application/src/main/java/com/hanghae/application/dto/response/MovieScheduleResponseDto.java similarity index 91% rename from cinema-application/src/main/java/com/hanghae/application/dto/MovieScheduleResponseDto.java rename to cinema-application/src/main/java/com/hanghae/application/dto/response/MovieScheduleResponseDto.java index a913750f7..f989d2f19 100644 --- a/cinema-application/src/main/java/com/hanghae/application/dto/MovieScheduleResponseDto.java +++ b/cinema-application/src/main/java/com/hanghae/application/dto/response/MovieScheduleResponseDto.java @@ -1,4 +1,4 @@ -package com.hanghae.application.dto; +package com.hanghae.application.dto.response; import java.time.LocalDate; import java.time.LocalDateTime; diff --git a/cinema-application/src/main/java/com/hanghae/application/dto/ShowingMovieScheduleResponseDto.java b/cinema-application/src/main/java/com/hanghae/application/dto/response/ShowingMovieScheduleResponseDto.java similarity index 96% rename from cinema-application/src/main/java/com/hanghae/application/dto/ShowingMovieScheduleResponseDto.java rename to cinema-application/src/main/java/com/hanghae/application/dto/response/ShowingMovieScheduleResponseDto.java index 7e0c8fafb..4ddbc7b1b 100644 --- a/cinema-application/src/main/java/com/hanghae/application/dto/ShowingMovieScheduleResponseDto.java +++ b/cinema-application/src/main/java/com/hanghae/application/dto/response/ShowingMovieScheduleResponseDto.java @@ -1,4 +1,4 @@ -package com.hanghae.application.dto; +package com.hanghae.application.dto.response; import lombok.Builder; import lombok.Getter; diff --git a/cinema-application/src/main/java/com/hanghae/application/port/in/MovieReservationService.java b/cinema-application/src/main/java/com/hanghae/application/port/in/MovieReservationService.java index 6eed90a1c..4836d0f55 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/in/MovieReservationService.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/in/MovieReservationService.java @@ -1,7 +1,7 @@ package com.hanghae.application.port.in; import com.hanghae.application.dto.ApiResponse; -import com.hanghae.application.dto.MovieReservationRequestDto; +import com.hanghae.application.dto.request.MovieReservationRequestDto; public interface MovieReservationService { public ApiResponse saveMovieReservation(MovieReservationRequestDto requestDto); diff --git a/cinema-application/src/main/java/com/hanghae/application/port/in/MovieScheduleService.java b/cinema-application/src/main/java/com/hanghae/application/port/in/MovieScheduleService.java index 8b2677223..3285baeb3 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/in/MovieScheduleService.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/in/MovieScheduleService.java @@ -1,9 +1,9 @@ package com.hanghae.application.port.in; import com.hanghae.application.dto.ApiResponse; -import com.hanghae.application.dto.MovieScheduleRequestDto; -import com.hanghae.application.dto.MovieScheduleResponseDto; -import com.hanghae.application.dto.ShowingMovieScheduleResponseDto; +import com.hanghae.application.dto.request.MovieScheduleRequestDto; +import com.hanghae.application.dto.response.MovieScheduleResponseDto; +import com.hanghae.application.dto.response.ShowingMovieScheduleResponseDto; import java.util.List; diff --git a/cinema-application/src/main/java/com/hanghae/application/port/out/repository/MovieRepositoryPort.java b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/MovieRepositoryPort.java index 213e849ea..ea93d829d 100644 --- a/cinema-application/src/main/java/com/hanghae/application/port/out/repository/MovieRepositoryPort.java +++ b/cinema-application/src/main/java/com/hanghae/application/port/out/repository/MovieRepositoryPort.java @@ -1,6 +1,6 @@ package com.hanghae.application.port.out.repository; -import com.hanghae.application.dto.MovieScheduleRequestDto; +import com.hanghae.application.dto.request.MovieScheduleRequestDto; import com.hanghae.application.projection.MovieScheduleProjection; import java.util.List; diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java index 8810224ed..da77c885d 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java @@ -1,7 +1,7 @@ package com.hanghae.application.service; import com.hanghae.application.dto.ApiResponse; -import com.hanghae.application.dto.MovieReservationRequestDto; +import com.hanghae.application.dto.request.MovieReservationRequestDto; import com.hanghae.application.enums.HttpStatusCode; import com.hanghae.application.port.in.MovieReservationService; import com.hanghae.application.port.out.message.MessagePort; diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java index e41c83bb3..34dadbffa 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieScheduleServiceImpl.java @@ -1,9 +1,9 @@ package com.hanghae.application.service; import com.hanghae.application.dto.ApiResponse; -import com.hanghae.application.dto.MovieScheduleRequestDto; -import com.hanghae.application.dto.MovieScheduleResponseDto; -import com.hanghae.application.dto.ShowingMovieScheduleResponseDto; +import com.hanghae.application.dto.request.MovieScheduleRequestDto; +import com.hanghae.application.dto.response.MovieScheduleResponseDto; +import com.hanghae.application.dto.response.ShowingMovieScheduleResponseDto; import com.hanghae.application.enums.HttpStatusCode; import com.hanghae.application.port.in.MovieScheduleService; import com.hanghae.application.port.out.redis.RedisRateLimitPort; diff --git a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MovieRepositoryAdapter.java b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MovieRepositoryAdapter.java index 7e9900919..46648a9c2 100644 --- a/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MovieRepositoryAdapter.java +++ b/cinema-infrastructure/src/main/java/com/hanghae/infrastructure/adapter/repository/MovieRepositoryAdapter.java @@ -1,6 +1,6 @@ package com.hanghae.infrastructure.adapter.repository; -import com.hanghae.application.dto.MovieScheduleRequestDto; +import com.hanghae.application.dto.request.MovieScheduleRequestDto; import com.hanghae.application.port.out.repository.MovieRepositoryPort; import com.hanghae.application.projection.MovieScheduleProjection; import com.hanghae.infrastructure.config.RedisCacheName; From 4770f4a00798ae04bf5b654ab9320d450a797c37 Mon Sep 17 00:00:00 2001 From: kim keun tae Date: Sun, 2 Feb 2025 20:28:30 +0900 Subject: [PATCH 6/9] =?UTF-8?q?=EC=98=81=ED=99=94=20=EC=98=88=EB=A7=A4=20?= =?UTF-8?q?=EB=B9=84=EC=A6=88=EB=8B=88=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=8B=A8=EC=9C=84=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=86=B5=ED=95=A9?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cinema-adapter/build.gradle.kts | 5 + .../hanghae/adapter/web/MovieController.java | 22 +- .../adapter/web/ReservationController.java | 9 +- .../resources/application-test.properties | 29 +++ .../main/resources/sql/reservationTest.sql | 50 +++++ .../web/ReservationControllerTest.java | 102 +++++++++ .../com/hanghae/adapter/TestDataFactory.java | 20 ++ cinema-application/build.gradle.kts | 6 +- .../service/MovieReservationServiceImpl.java | 2 +- .../application/TestConfiguration.java | 11 + .../MovieReservationServiceImplTest.java | 180 ++++++++++++++++ .../hanghae/application/TestDataFactory.java | 196 ++++++++++++++++++ cinema-domain/build.gradle.kts | 1 + cinema-infrastructure/build.gradle.kts | 1 + 14 files changed, 624 insertions(+), 10 deletions(-) create mode 100644 cinema-adapter/src/main/resources/application-test.properties create mode 100644 cinema-adapter/src/main/resources/sql/reservationTest.sql create mode 100644 cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java create mode 100644 cinema-adapter/src/testFixtures/java/com/hanghae/adapter/TestDataFactory.java create mode 100644 cinema-application/src/test/java/com/hanghae/application/TestConfiguration.java create mode 100644 cinema-application/src/test/java/com/hanghae/application/service/MovieReservationServiceImplTest.java create mode 100644 cinema-application/src/testFixtures/java/com/hanghae/application/TestDataFactory.java diff --git a/cinema-adapter/build.gradle.kts b/cinema-adapter/build.gradle.kts index 63fb3df72..bf785461e 100644 --- a/cinema-adapter/build.gradle.kts +++ b/cinema-adapter/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("java") id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" + id("java-test-fixtures") // 테스트 픽스처 활성화 } group = "com.hanghae" @@ -16,6 +17,10 @@ dependencies { implementation(project(":cinema-infrastructure")) // RepositoryPort 구현체를 찾지 못해서 추가 implementation("org.springframework.boot:spring-boot-starter-web") // web implementation("org.springframework.boot:spring-boot-starter-data-jpa") //jpa 레포지토리 의존성 문제로 추가 (@EnableJpaRepositories) + testFixturesImplementation(project(":cinema-domain")) // testFixtures에서 도메인 객체 사용 위함 + testFixturesImplementation(project(":cinema-application")) // testFixtures에서 application 객체 사용 위함 + // testFixturesImplementation로 의존성 추가한 계층은 /src/testFixtures 하위 경로에서만 사용 가능 하다. + // 양쪽 계층에 테스트 픽스처 활성화 설정(id("java-test-fixtures"))이 되어 있어야 한다. } tasks.test { diff --git a/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java b/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java index fe36df5fa..0343baf61 100644 --- a/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java +++ b/cinema-adapter/src/main/java/com/hanghae/adapter/web/MovieController.java @@ -7,6 +7,7 @@ import com.hanghae.application.port.in.MovieScheduleService; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -19,24 +20,33 @@ public class MovieController { //영화 상영 시간표 조회 @GetMapping("/v1/movie-schedules") - public ApiResponse> getMovieSchedules() { - return movieScheduleService.getMovieSchedules(); + public ResponseEntity>> getMovieSchedules() { + ApiResponse> response = movieScheduleService.getMovieSchedules(); + + //응답코드 일치시켜서 리턴 + return ResponseEntity.status(response.status().getCode()).body(response); } //영화별 상영 시간표 조회 (grouping) @GetMapping("/v2/movie-schedules") - public ApiResponse> getShowingMovieSchedules(@ModelAttribute MovieScheduleRequestDto requestDto, HttpServletRequest request) { + public ResponseEntity>> getShowingMovieSchedules(@ModelAttribute MovieScheduleRequestDto requestDto, HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } - return movieScheduleService.getShowingMovieSchedules(requestDto, ip); + ApiResponse> response = movieScheduleService.getShowingMovieSchedules(requestDto, ip); + + //응답코드 일치시켜서 리턴 + return ResponseEntity.status(response.status().getCode()).body(response); } //redis 캐시삭제 (테스트용) @GetMapping("/test/evict-cache") - public ApiResponse evictCache() { - return movieScheduleService.evictShowingMovieCache(); + public ResponseEntity> evictCache() { + ApiResponse response = movieScheduleService.evictShowingMovieCache(); + + //응답코드 일치시켜서 리턴 + return ResponseEntity.status(response.status().getCode()).body(response); } } diff --git a/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java b/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java index 041510d90..332580890 100644 --- a/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java +++ b/cinema-adapter/src/main/java/com/hanghae/adapter/web/ReservationController.java @@ -2,8 +2,10 @@ import com.hanghae.application.dto.ApiResponse; import com.hanghae.application.dto.request.MovieReservationRequestDto; +import com.hanghae.application.enums.HttpStatusCode; import com.hanghae.application.port.in.MovieReservationService; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -18,7 +20,10 @@ public class ReservationController { //영화 예약 // TODO :: 좌석선택API와 영화예약API 분리 @PostMapping("/v1/movie-reservation") - public ApiResponse saveMovieReservation(@RequestBody MovieReservationRequestDto requestDto) { - return movieReservationService.saveMovieReservation(requestDto); + public ResponseEntity> saveMovieReservation(@RequestBody MovieReservationRequestDto requestDto) { + ApiResponse response = movieReservationService.saveMovieReservation(requestDto); + + //응답코드 일치시켜서 리턴 + return ResponseEntity.status(response.status().getCode()).body(response); } } diff --git a/cinema-adapter/src/main/resources/application-test.properties b/cinema-adapter/src/main/resources/application-test.properties new file mode 100644 index 000000000..91578b8e5 --- /dev/null +++ b/cinema-adapter/src/main/resources/application-test.properties @@ -0,0 +1,29 @@ +# H2 +spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=MySQL +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=test_user +spring.datasource.password=test_password +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect + +# h2 (http://localhost:8080/h2-console) +spring.h2.console.enabled=true +spring.h2.console.path=/h2-console + +# JPA +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect +spring.jpa.generate-ddl=true +spring.jpa.open-in-view=false + +# Redis 설정 +spring.data.redis.host=localhost +spring.data.redis.port=6378 +spring.data.redis.password=cinemaredis + +# log +#logging.level.root=info + + + diff --git a/cinema-adapter/src/main/resources/sql/reservationTest.sql b/cinema-adapter/src/main/resources/sql/reservationTest.sql new file mode 100644 index 000000000..8a3d9c3f8 --- /dev/null +++ b/cinema-adapter/src/main/resources/sql/reservationTest.sql @@ -0,0 +1,50 @@ +INSERT INTO member (member_id, birth_date, created_by, created_at) +VALUES (1, '1999-01-01', 99, NOW()); + +INSERT INTO upload_file (file_id, file_path, file_name, origin_file_name, created_by, created_at) +VALUES (1, '/radis/test/', 'test1.png', 'origin.png', 99, NOW()); + +INSERT INTO upload_file (file_id, file_path, file_name, origin_file_name, created_by, created_at) +VALUES (2, '/radis/test/', 'test2.png', 'origin.png', 99, NOW()); + +INSERT INTO upload_file (file_id, file_path, file_name, origin_file_name, created_by, created_at) +VALUES (3, '/radis/test/', 'test3.png', 'origin.png', 99, NOW()); + +INSERT INTO movie (movie_id, file_id, title, rating, release_date, running_time_minutes ,genre, created_by, created_at) +VALUES (1, 1, '치토스', '2', '2024-12-11', 90, 'T', 99, NOW()); + +INSERT INTO movie (movie_id, file_id, title, rating, release_date, running_time_minutes ,genre, created_by, created_at) +VALUES (2, 2, '칸초', '1', '2024-11-17', 120, 'F', 99, NOW()); + +INSERT INTO movie (movie_id, file_id, title, rating, release_date, running_time_minutes ,genre, created_by, created_at) +VALUES (3, 3, '공공칠빵', '3', '2024-10-13', 110, 'A', 99, NOW()); + +INSERT INTO screen (screen_id, screen_name, created_by, created_at) +VALUES (1, '1관', 99, NOW()); + +INSERT INTO screen (screen_id, screen_name, created_by, created_at) +VALUES (2, '2관', 99, NOW()); + +INSERT INTO screening_schedule (schedule_id, movie_id, screen_id, show_start_at, created_by, created_at) +VALUES (1, 1, 1, '2025-02-13 10:50:00', 99, NOW()); + +INSERT INTO screening_schedule (schedule_id, movie_id, screen_id, show_start_at, created_by, created_at) +VALUES (2, 2, 2, '2025-02-20 12:00:00', 99, NOW()); + +INSERT INTO screening_schedule (schedule_id, movie_id, screen_id, show_start_at, created_by, created_at) +VALUES (3, 3, 1, '2025-02-17 13:20:00', 99, NOW()); + +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (1, 1, 'A', 5, 99, NOW()); +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (2, 1, 'B', 5, 99, NOW()); +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (3, 1, 'C', 5, 99, NOW()); +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (4, 1, 'D', 5, 99, NOW()); +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (5, 1, 'E', 5, 99, NOW()); + +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (6, 2, 'A', 5, 99, NOW()); +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (7, 2, 'B', 5, 99, NOW()); +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (8, 2, 'C', 5, 99, NOW()); +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (9, 2, 'D', 5, 99, NOW()); +INSERT INTO screen_seat_layout (seat_layout_id, screen_id, seat_row, max_seat_number, created_by, created_at) VALUES (10, 2, 'E', 5, 99, NOW()); + +INSERT INTO ticket_reservation (ticket_id, schedule_id, screen_seat, member_id, created_by, created_at) +VALUES (1, 1, 'E01', 1, 99, NOW()); \ No newline at end of file diff --git a/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java b/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java new file mode 100644 index 000000000..1ad35f3ca --- /dev/null +++ b/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java @@ -0,0 +1,102 @@ +package com.hanghae.adapter.web; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.hanghae.adapter.TestDataFactory; +import com.hanghae.application.dto.request.MovieReservationRequestDto; +import com.hanghae.application.port.in.MovieReservationService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + + +@SpringBootTest +@ActiveProfiles("test") // application-test.properties 사용 +@AutoConfigureMockMvc +@Transactional +@Sql(scripts = "/sql/reservationTest.sql") // SQL 파일 실행 +class ReservationControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private MovieReservationService movieReservationService; + + private MovieReservationRequestDto requestDto; + + @BeforeEach + void setUp() { + requestDto = TestDataFactory.createMovieReservationRequestDto(); + } + + @Test + @DisplayName("[통합] 정상적인 영화 예매 요청 테스트") + void saveMovieReservationSuccess() throws Exception { + // When & Then + mockMvc.perform(post("/api/v1/movie-reservation") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.message").value("예매가 완료 되었습니다.")); + } + + @Test + @DisplayName("[통합] 5분내 동일 일정 영화 예매 예외 발생 테스트") + void saveMovieReservationTooManyRequests() throws Exception { + // 1번 요청을 먼저 수행하여 Redis Rate Limit를 초과시키기 + mockMvc.perform(post("/api/v1/movie-reservation") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isCreated()); + + // 5분 내 동일한 요청을 보내면 예외 발생 확인 + mockMvc.perform(post("/api/v1/movie-reservation") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isTooManyRequests()) + .andExpect(jsonPath("$.message").value("동일 시간대 영화 예매는 5분 후 가능합니다.")); + } + + @Test + @DisplayName("[통합] 좌석이 이미 예매된 경우 예외 발생 테스트") + void saveMovieReservation_SeatAlreadyReserved() throws Exception { + //테스트 sql에서 미리 넣어둔 예매데이터와 동일한 좌석 세팅 + requestDto = TestDataFactory.createMovieReservationRequestDto("E", 1); + + // 동일한 좌석을 다시 예매하면 예외 발생 확인 + mockMvc.perform(post("/api/v1/movie-reservation") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(requestDto))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message").value("선택한 좌석은 이미 예매되었습니다.")); + } + + @Test + @DisplayName("[통합] 회원당 예매 좌석 개수 초과시 예외 발생 테스트") + void saveMovieReservationSeatLimitExceeded() throws Exception { + //테스트 sql에서 미리 넣어둔 예매데이터 + 추가로 5좌석 예매 + MovieReservationRequestDto invalidRequest = TestDataFactory.createMovieReservationRequestDto(5); + + // 좌석 5개 초과 예매 요청시 예외 발생 확인 + mockMvc.perform(post("/api/v1/movie-reservation") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(invalidRequest))) + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.message").value("상영시간별 예매는 최대 5개까지 할 수 있습니다.")); + } +} \ No newline at end of file diff --git a/cinema-adapter/src/testFixtures/java/com/hanghae/adapter/TestDataFactory.java b/cinema-adapter/src/testFixtures/java/com/hanghae/adapter/TestDataFactory.java new file mode 100644 index 000000000..806a19c60 --- /dev/null +++ b/cinema-adapter/src/testFixtures/java/com/hanghae/adapter/TestDataFactory.java @@ -0,0 +1,20 @@ +package com.hanghae.adapter; + +import com.hanghae.application.dto.request.MovieReservationRequestDto; +import com.hanghae.domain.model.enums.ScreenSeat; + +public class TestDataFactory { + + // 영화 예매 요청 DTO 생성 + public static MovieReservationRequestDto createMovieReservationRequestDto() { + return new MovieReservationRequestDto(1L, 1L, ScreenSeat.A01, 2); + } + + public static MovieReservationRequestDto createMovieReservationRequestDto(int seatCount) { + return new MovieReservationRequestDto(1L, 1L, ScreenSeat.A01, seatCount); + } + + public static MovieReservationRequestDto createMovieReservationRequestDto(String prefix, int number) { + return new MovieReservationRequestDto(1L, 1L, ScreenSeat.fromRowAndNumber(prefix, number), 1); + } +} diff --git a/cinema-application/build.gradle.kts b/cinema-application/build.gradle.kts index 833110af7..f45033300 100644 --- a/cinema-application/build.gradle.kts +++ b/cinema-application/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("java") id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" + id("java-test-fixtures") // 테스트 픽스처 활성화 } group = "com.hanghae" @@ -13,7 +14,10 @@ repositories { dependencies { implementation(project(":cinema-domain")) // 도메인 계층 의존성 - implementation("com.fasterxml.jackson.core:jackson-annotations:2.16.0") // Java, JSON 변환 라이브러리 + implementation("com.fasterxml.jackson.core:jackson-annotations:2.16.0") // Java, JSON 변환 라이브러리 + testFixturesImplementation(project(":cinema-domain")) // testFixtures에서 도메인 객체 사용 위함 + // testFixturesImplementation로 의존성 추가한 계층은 /src/testFixtures 하위 경로에서만 사용 가능 하다. + // 양쪽 계층에 테스트 픽스처 활성화 설정(id("java-test-fixtures"))이 되어 있어야 한다. } tasks.test { diff --git a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java index da77c885d..27d45d858 100644 --- a/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java +++ b/cinema-application/src/main/java/com/hanghae/application/service/MovieReservationServiceImpl.java @@ -45,7 +45,7 @@ public ApiResponse saveMovieReservation(MovieReservationRequestDto request //동 시간대의 영화를 5분에 1번씩 예매 제한 if (!redisRateLimitPort.canReserve(scheduleId, memberId)) { - return ApiResponse.of("동일 시간대 영화 예매은 5분 후 가능합니다.", HttpStatusCode.TOO_MANY_REQUESTS); + return ApiResponse.of("동일 시간대 영화 예매는 5분 후 가능합니다.", HttpStatusCode.TOO_MANY_REQUESTS); } // 예매할 좌석 목록 가져오기 diff --git a/cinema-application/src/test/java/com/hanghae/application/TestConfiguration.java b/cinema-application/src/test/java/com/hanghae/application/TestConfiguration.java new file mode 100644 index 000000000..2dcfd22c2 --- /dev/null +++ b/cinema-application/src/test/java/com/hanghae/application/TestConfiguration.java @@ -0,0 +1,11 @@ +package com.hanghae.application; + +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TestConfiguration { + /** + * 어뎁터에서 @SpringBootApplication 를 가진 main 메서드를 가지고 있기 떄문에 + * 테스트시 실행을 위해 테스트용 SpringBootApplication 생성 + */ +} diff --git a/cinema-application/src/test/java/com/hanghae/application/service/MovieReservationServiceImplTest.java b/cinema-application/src/test/java/com/hanghae/application/service/MovieReservationServiceImplTest.java new file mode 100644 index 000000000..c9a201d88 --- /dev/null +++ b/cinema-application/src/test/java/com/hanghae/application/service/MovieReservationServiceImplTest.java @@ -0,0 +1,180 @@ +package com.hanghae.application.service; + +import com.hanghae.application.TestDataFactory; +import com.hanghae.application.dto.ApiResponse; +import com.hanghae.application.dto.request.MovieReservationRequestDto; +import com.hanghae.application.enums.HttpStatusCode; +import com.hanghae.application.port.out.message.MessagePort; +import com.hanghae.application.port.out.redis.RedisRateLimitPort; +import com.hanghae.application.port.out.redis.RedissonLockPort; +import com.hanghae.application.port.out.repository.MemberRepositoryPort; +import com.hanghae.application.port.out.repository.ScreenSeatLayoutRepositoryPort; +import com.hanghae.application.port.out.repository.ScreeningScheduleRepositoryPort; +import com.hanghae.application.port.out.repository.TicketReservationRepositoryPort; +import com.hanghae.domain.model.Member; +import com.hanghae.domain.model.ScreenSeatLayout; +import com.hanghae.domain.model.ScreeningSchedule; +import com.hanghae.domain.model.TicketReservation; +import com.hanghae.domain.model.enums.ScreenSeat; +import com.hanghae.domain.service.ReservationService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.function.Supplier; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class MovieReservationServiceImplTest { + + @InjectMocks + private MovieReservationServiceImpl movieReservationService; + + @Mock + private TicketReservationRepositoryPort ticketReservationRepositoryPort; + @Mock + private ScreeningScheduleRepositoryPort screeningScheduleRepositoryPort; + @Mock + private ScreenSeatLayoutRepositoryPort screenSeatLayoutRepositoryPort; + @Mock + private MemberRepositoryPort memberRepositoryPort; + @Mock + private MessagePort messagePort; + @Mock + private ReservationService reservationService; + @Mock + private RedissonLockPort redissonLockPort; + @Mock + private RedisRateLimitPort redisRateLimitPort; + + private MovieReservationRequestDto requestDto; + private ScreeningSchedule screeningSchedule; + private Member member; + private ScreenSeatLayout screenSeatLayout; + private List selectedSeats; + private List ticketReservations; + + @BeforeEach + void setUp() { + requestDto = TestDataFactory.createMovieReservationRequestDto(); + screeningSchedule = TestDataFactory.createScreeningSchedule(); + member = TestDataFactory.createMember(); + screenSeatLayout = TestDataFactory.createScreenSeatLayout(); + selectedSeats = ScreenSeat.getSelectedConnectedSeats(ScreenSeat.A01, 2); + ticketReservations = TestDataFactory.createTicketReservations(); + + // 예상 동작 정의 + // 필요하지 않은 Stubbing이 있어도 예외 없이 테스트가 진행되게 lenient() 사용 + lenient().when(screeningScheduleRepositoryPort.findById(anyLong())).thenReturn(screeningSchedule); + lenient().when(memberRepositoryPort.findById(anyLong())).thenReturn(member); + lenient().when(screenSeatLayoutRepositoryPort.findBySeatRowAndScreenId(anyString(), anyLong())).thenReturn(screenSeatLayout); + lenient().when(ticketReservationRepositoryPort.countByScreeningScheduleIdAndMemberId(anyLong(), anyLong())).thenReturn(0); + lenient().when(ticketReservationRepositoryPort.countByScheduleIdAndScreenSeats(anyLong(), anyList())).thenReturn(0); + lenient().when(reservationService.createTicketReservations(any(), any(), any(), any(), anyInt())).thenReturn(ticketReservations); + lenient().when(redisRateLimitPort.canReserve(anyLong(), anyLong())).thenReturn(true); + lenient().when(redissonLockPort.executeWithSeatsLocks(anyLong(), anyList(), any())).thenAnswer(invocation -> { + Supplier> supplier = invocation.getArgument(2); + return supplier.get(); + }); + } + + @Test + @DisplayName("정상적인 예매 성공 테스트") + void saveMovieReservationSuccess() { + ApiResponse response = movieReservationService.saveMovieReservation(requestDto); + + // 응답 코드 비교 + assertEquals(HttpStatusCode.CREATED, response.status()); + + //ticketReservationRepositoryPort.saveMovieReservations 메서드가 1회 호출 되었는지 확인 + verify(ticketReservationRepositoryPort, times(1)).saveMovieReservations(anyList()); + + //messagePort.sendMessage 메서드가 1회 호출 되었는지 확인 + verify(messagePort, times(1)).sendMessage(anyString()); + } + + @Test + @DisplayName("동일 시간대 예매 제한 초과 시 예외 처리 테스트") + void saveMovieReservationTooManyRequests() { + when(redisRateLimitPort.canReserve(anyLong(), anyLong())).thenReturn(false); + + ApiResponse response = movieReservationService.saveMovieReservation(requestDto); + + // 응답 코드 확인 + assertEquals(HttpStatusCode.TOO_MANY_REQUESTS, response.status()); + + //ticketReservationRepositoryPort.saveMovieReservations 메서드가 호출 되지 않았는지 확인 + verify(ticketReservationRepositoryPort, never()).saveMovieReservations(anyList()); + } + + @Test + @DisplayName("이미 예매된 좌석일 경우 예외 발생 테스트") + void saveMovieReservationSeatAlreadyReserved() { + when(ticketReservationRepositoryPort.countByScheduleIdAndScreenSeats(anyLong(), anyList())).thenReturn(1); + + //validateSeatAvailability 인자로 받은 값이 0보다 크면 예외처리, 아닐 경우 그냥 통과 + doAnswer(invocation -> { + int count = invocation.getArgument(0); + if (count > 0) { + throw new IllegalArgumentException("선택한 좌석은 이미 예매되었습니다."); + } + return null; + }).when(reservationService).validateSeatAvailability(anyInt()); + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> + movieReservationService.saveMovieReservation(requestDto)); + + // 응답 메시지 비교 + assertEquals("선택한 좌석은 이미 예매되었습니다.", exception.getMessage()); + } + + @Test + @DisplayName("예매좌석 5개 초과시 예외 발생 테스트") + void saveMovieReservationSeatLimitExceeded() { + when(ticketReservationRepositoryPort.countByScreeningScheduleIdAndMemberId(anyLong(), anyLong())).thenReturn(5); + + //validateReservationSeatLimit 인자로 받은 값의 합이 5보다 크면 예외처리, 아닐 경우 그냥 통과 + doAnswer(invocation -> { + int reservedTicketCount = invocation.getArgument(0); + int seatCount = invocation.getArgument(1); + + if (reservedTicketCount + seatCount > 5) { + throw new IllegalArgumentException("상영시간별 예매는 최대 5개까지 할 수 있습니다."); + } + + return null; // void 메서드이므로 null 반환 + }).when(reservationService).validateReservationSeatLimit(anyInt(), anyInt()); + + + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> + movieReservationService.saveMovieReservation(requestDto)); + + // 응답 메시지 확인 + assertEquals("상영시간별 예매는 최대 5개까지 할 수 있습니다.", exception.getMessage()); + } + + @Test + @DisplayName("Redisson Lock을 획득하지 못했을 경우 예외 처리 테스트") + void saveMovieReservationLockFailed() { + // 기존 Mock 설정 제거 + Mockito.reset(redissonLockPort); + + // executeWithSeatsLocks 예상 동작 다시 정의 + when(redissonLockPort.executeWithSeatsLocks(anyLong(), anyList(), any())) + .thenThrow(new IllegalStateException("현재 좌석을 다른 사용자가 예매 처리 중입니다.")); + + ApiResponse response = movieReservationService.saveMovieReservation(requestDto); + + // 응답 코드 확인 + assertEquals(HttpStatusCode.CONFLICT, response.status()); + } +} diff --git a/cinema-application/src/testFixtures/java/com/hanghae/application/TestDataFactory.java b/cinema-application/src/testFixtures/java/com/hanghae/application/TestDataFactory.java new file mode 100644 index 000000000..4c6f2a328 --- /dev/null +++ b/cinema-application/src/testFixtures/java/com/hanghae/application/TestDataFactory.java @@ -0,0 +1,196 @@ +package com.hanghae.application; + +import com.hanghae.application.dto.request.MovieReservationRequestDto; +import com.hanghae.domain.model.*; +import com.hanghae.domain.model.enums.MovieGenre; +import com.hanghae.domain.model.enums.MovieRating; +import com.hanghae.domain.model.enums.ScreenSeat; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; + +/** + * java-test-fixtures - 테스트를 수행하기 위한 일관적이고 고정된 상태를 설정 + * 테스트시 사용하는 데이터들(영화정보, 회원정보 등)에 대한 Fixture의 재사용성을 높이기 위해 따로 분리 + */ +public class TestDataFactory { + + // 영화 예매 요청 DTO 생성 + public static MovieReservationRequestDto createMovieReservationRequestDto() { + return new MovieReservationRequestDto(1L, 1L, ScreenSeat.A01, 2); + } + + public static MovieReservationRequestDto createMovieReservationRequestDto(Long scheduleId, Long memberId, int seatCount, ScreenSeat seat) { + return new MovieReservationRequestDto(scheduleId, memberId, seat, seatCount); + } + + // 첨부파일 생성 + public static UploadFile createUploadFile() { + return new UploadFile( + 1L, + "/file/test", + "test.png", + "test.png", + 99L, + null, + null, + null + ); + } + + // 영화 생성 + public static Movie createMovie() { + return new Movie( + 1L, + "테스트 영화", + MovieRating.ALL, + LocalDate.of(2024, 1, 1), + 90L, + MovieGenre.ACTION, + createUploadFile(), + 99L, + null, + null, + null + ); + } + + // 상영관 생성 + public static Screen createScreen() { + return new Screen( + 1L, + "1관", + 99L, + null, + null, + null + ); + } + + public static Screen createScreen(Long screenId, String screenName) { + return new Screen( + screenId, + screenName, + 99L, + null, + null, + null + ); + } + + // 영화 상영 일정 생성 + public static ScreeningSchedule createScreeningSchedule() { + return new ScreeningSchedule( + 1L, + createMovie(), + createScreen(), + LocalDateTime.of(2024, 10, 15, 11, 11, 11), + 99L, + null, + null, + null + ); + } + + // 상영 시간표 생성 + public static ScreeningSchedule createScreeningSchedule(Long scheduleId, Screen screen) { + return new ScreeningSchedule( + scheduleId, + createMovie(), + screen, + LocalDateTime.of(2024, 10, 15, 11, 11, 11), + 99L, + null, + null, + null + ); + } + + // 회원 생성 + public static Member createMember() { + return new Member( + 99L, + LocalDate.of(1995, 1, 1), + 99L, + null, + null, + null + ); + } + + public static Member createMember(Long memberId, LocalDate birthDate) { + return new Member( + memberId, + birthDate, + memberId, + null, + null, + null + ); + } + + // 좌석 배치 정보 생성 + public static ScreenSeatLayout createScreenSeatLayout() { + return new ScreenSeatLayout( + 1L, + createScreen(), + "A", + 5L, + 99L, + null, + null, + null + ); + } + + public static ScreenSeatLayout createScreenSeatLayout(String seatRow, Long maxSeatNumber) { + return new ScreenSeatLayout( + 1L, + createScreen(), + seatRow, + maxSeatNumber, + 99L, + null, + null, + null + ); + } + + // 예매 정보 생성 + public static TicketReservation createTicketReservation() { + return new TicketReservation( + 1L, + ScreenSeat.A01, + createScreeningSchedule(), + createMember(), + 99L, + null, + null, + null + ); + } + + public static TicketReservation createTicketReservation(Long ticketId, ScreeningSchedule schedule, Member member, ScreenSeat seat) { + return new TicketReservation( + ticketId, + seat, + schedule, + member, + 99L, + null, + null, + null + ); + } + + public static List createTicketReservations() { + ScreeningSchedule screeningSchedule = createScreeningSchedule(); + Member member = createMember(); + + return List.of( + createTicketReservation(1L, screeningSchedule, member, ScreenSeat.A01), + createTicketReservation(2L, screeningSchedule, member, ScreenSeat.A02) + ); + } +} diff --git a/cinema-domain/build.gradle.kts b/cinema-domain/build.gradle.kts index dd17cc9aa..049f50318 100644 --- a/cinema-domain/build.gradle.kts +++ b/cinema-domain/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("java") id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" + id("java-test-fixtures") // 테스트 픽스처 활성화 } group = "com.hanghae" diff --git a/cinema-infrastructure/build.gradle.kts b/cinema-infrastructure/build.gradle.kts index 4687e6ad7..806715771 100644 --- a/cinema-infrastructure/build.gradle.kts +++ b/cinema-infrastructure/build.gradle.kts @@ -2,6 +2,7 @@ plugins { id("java") id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" + id("java-test-fixtures") // 테스트 픽스처 활성화 } group = "com.hanghae" From 9a632cb49324d6af5c6378086b8490d337b7e428 Mon Sep 17 00:00:00 2001 From: kim keun tae Date: Sun, 2 Feb 2025 21:34:52 +0900 Subject: [PATCH 7/9] =?UTF-8?q?=ED=86=B5=ED=95=A9=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=8B=9C=20redis=20=20Testcontainers=20=EB=A1=9C=20?= =?UTF-8?q?=EC=8B=A4=ED=96=89=EB=90=98=EA=B2=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +++ cinema-adapter/build.gradle.kts | 3 ++ .../web/ReservationControllerTest.java | 28 +++++++++++++++++++ 3 files changed, 35 insertions(+) diff --git a/README.md b/README.md index 7e143972c..795c55bd9 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,10 @@ > Mysql > Redis +### Junit5 테스트 환경 +* DB : H2 +* Redis : Testcontainers + ### 규칙 * `infrastruct` 계층에서의 결과값은 `domain model` 혹은 `Projection(필요한 속성만 조회)` 객체 로 리턴한다. * `domain model`에서 `Dto`로 변환은 `application` 계층에서 한다. diff --git a/cinema-adapter/build.gradle.kts b/cinema-adapter/build.gradle.kts index bf785461e..e32ad6d00 100644 --- a/cinema-adapter/build.gradle.kts +++ b/cinema-adapter/build.gradle.kts @@ -21,6 +21,9 @@ dependencies { testFixturesImplementation(project(":cinema-application")) // testFixtures에서 application 객체 사용 위함 // testFixturesImplementation로 의존성 추가한 계층은 /src/testFixtures 하위 경로에서만 사용 가능 하다. // 양쪽 계층에 테스트 픽스처 활성화 설정(id("java-test-fixtures"))이 되어 있어야 한다. + + testImplementation ("org.testcontainers:testcontainers:1.19.3") //테스트 컨테이너 + testImplementation ("org.testcontainers:junit-jupiter:1.19.3") } tasks.test { diff --git a/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java b/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java index 1ad35f3ca..3c15e1774 100644 --- a/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java +++ b/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java @@ -12,9 +12,15 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.jdbc.Sql; import org.springframework.test.web.servlet.MockMvc; import org.springframework.transaction.annotation.Transactional; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; @@ -24,9 +30,31 @@ @SpringBootTest @ActiveProfiles("test") // application-test.properties 사용 @AutoConfigureMockMvc +@Testcontainers // TestContainers 사용 @Transactional @Sql(scripts = "/sql/reservationTest.sql") // SQL 파일 실행 class ReservationControllerTest { + private static final String REDIS_PASSWORD = "redisPassword"; // 운영과 동일하게 설정 + /** + * @Container 어노테이션은 Testcontainers가 해당 필드에 Docker 컨테이너를 실행하도록 지시 + * 컨테이너의 시작과 종료를 저희가 직접 호출 하지 않고 테스트의 생명주기와 같이 돌 수 있도록 해줄 + * + * 테스트 컨테이너 사용시 도커가 실행중어야 한다. (도커 데스크탑 실행) + */ + @Container + private static final GenericContainer redisContainer = + new GenericContainer<>(DockerImageName.parse("redis:7.4.2-alpine")) + .withExposedPorts(6379) // TestContainers에서는 내부적으로 6379 사용 + .withCommand("redis-server --requirepass " + REDIS_PASSWORD); // 비밀번호 설정 + + @DynamicPropertySource + static void configureProperties(DynamicPropertyRegistry registry) { + redisContainer.start(); + registry.add("spring.data.redis.host", redisContainer::getHost); + registry.add("spring.data.redis.port", () -> redisContainer.getMappedPort(6379)); + registry.add("spring.data.redis.password", () -> REDIS_PASSWORD); // 비밀번호 적용 + // 비밀번호 적용 + } @Autowired private MockMvc mockMvc; From 56fc2e34a8fdcb5a4a58333299de161138fd2c1d Mon Sep 17 00:00:00 2001 From: kim keun tae Date: Mon, 3 Feb 2025 01:41:57 +0900 Subject: [PATCH 8/9] =?UTF-8?q?jacoco=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EB=B3=B4=EA=B3=A0=EC=84=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 +++++++- cinema-adapter/build.gradle.kts | 37 +++++++++++++++++- .../resources/application-test.properties | 5 --- .../web/ReservationControllerTest.java | 12 +++--- cinema-application/build.gradle.kts | 34 +++++++++++++++- cinema-domain/build.gradle.kts | 34 +++++++++++++++- cinema-infrastructure/build.gradle.kts | 34 +++++++++++++++- docs/img/jacoco_test_report.png | Bin 0 -> 243373 bytes 8 files changed, 156 insertions(+), 16 deletions(-) create mode 100644 docs/img/jacoco_test_report.png diff --git a/README.md b/README.md index 795c55bd9..41d00b4ef 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,20 @@ > Redis ### Junit5 테스트 환경 -* DB : H2 -* Redis : Testcontainers +* DB : H2 +* Redis : Testcontainers + +### jacoco 보고서 +![jacoco_test_report.png](docs%2Fimg%2Fjacoco_test_report.png) + +### JaCoCo +* `build.gradle.kts` 파일 `plugins`에 `id("jacoco")` 추가 후 `gradle`을 다시 빌드해야 한다. +* 그 뒤 하단에 `jacoco`, `tasks.jacocoTestCoverageVerification`, `tasks.jacocoTestReport`를 작성 + * 빌드를 다시하지 않으면 빨간줄이 뜬다. +* 테스트 실행 및 보고서 생성 : `./gradlew clean test jacocoTestReport --console verbose` +* 테스트 실행 및 보고서 생성(커버리지 충족 확인) : `./gradlew clean test jacocoTestReport jacocoTestCoverageVerification --console verbose` +* `build.gradle.kts`파일에 보고서 저장경로를 설정하여 `/build/reports/jacoco/index.html` 해당파일을 확인하면 된다. + * `html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정` ### 규칙 * `infrastruct` 계층에서의 결과값은 `domain model` 혹은 `Projection(필요한 속성만 조회)` 객체 로 리턴한다. diff --git a/cinema-adapter/build.gradle.kts b/cinema-adapter/build.gradle.kts index e32ad6d00..3c8e218b6 100644 --- a/cinema-adapter/build.gradle.kts +++ b/cinema-adapter/build.gradle.kts @@ -3,11 +3,17 @@ plugins { id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" id("java-test-fixtures") // 테스트 픽스처 활성화 + id("jacoco") // JaCoCo 플러그인 추가 + //id("jacoco-report-aggregation") // JaCoCo 멀티모듈 리포트 통합하기 위한 플러그인 } group = "com.hanghae" version = "0.0.1-SNAPSHOT" +jacoco { + toolVersion = "0.8.10" +} + repositories { mavenCentral() } @@ -22,10 +28,39 @@ dependencies { // testFixturesImplementation로 의존성 추가한 계층은 /src/testFixtures 하위 경로에서만 사용 가능 하다. // 양쪽 계층에 테스트 픽스처 활성화 설정(id("java-test-fixtures"))이 되어 있어야 한다. + testImplementation("org.springframework.boot:spring-boot-starter-data-redis") // test 코드에서 RedisTemplate 사용 위함 + testImplementation ("org.testcontainers:testcontainers:1.19.3") //테스트 컨테이너 testImplementation ("org.testcontainers:junit-jupiter:1.19.3") } tasks.test { useJUnitPlatform() -} \ No newline at end of file +} + +tasks.jacocoTestReport { + dependsOn(tasks.test) // test 실행 후 리포트 생성 + + reports { + xml.required.set(false) // XML 리포트 비활성화 + csv.required.set(false) // csv 리포트 비활성화 + html.required.set(true) // HTML 리포트 활성화 + html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정 + } +} + +tasks.jacocoTestCoverageVerification { + dependsOn(tasks.jacocoTestReport) + + violationRules { + rule { + element = "CLASS" + limit { + counter = "BRANCH" + value = "COVEREDRATIO" + minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 + excludes = listOf("com.hanghae.adapter.web.MovieController") // 테스트코드 미구현으로 검증 제외 + } + } + } +} diff --git a/cinema-adapter/src/main/resources/application-test.properties b/cinema-adapter/src/main/resources/application-test.properties index 91578b8e5..c570ba014 100644 --- a/cinema-adapter/src/main/resources/application-test.properties +++ b/cinema-adapter/src/main/resources/application-test.properties @@ -17,11 +17,6 @@ spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect spring.jpa.generate-ddl=true spring.jpa.open-in-view=false -# Redis 설정 -spring.data.redis.host=localhost -spring.data.redis.port=6378 -spring.data.redis.password=cinemaredis - # log #logging.level.root=info diff --git a/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java b/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java index 3c15e1774..4bd4143f1 100644 --- a/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java +++ b/cinema-adapter/src/test/java/com/hanghae/adapter/web/ReservationControllerTest.java @@ -4,12 +4,11 @@ import com.hanghae.adapter.TestDataFactory; import com.hanghae.application.dto.request.MovieReservationRequestDto; import com.hanghae.application.port.in.MovieReservationService; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.DynamicPropertyRegistry; @@ -40,6 +39,7 @@ class ReservationControllerTest { * 컨테이너의 시작과 종료를 저희가 직접 호출 하지 않고 테스트의 생명주기와 같이 돌 수 있도록 해줄 * * 테스트 컨테이너 사용시 도커가 실행중어야 한다. (도커 데스크탑 실행) + * @Container를 사용하면 TestContainers가 자동으로 컨테이너를 실행 */ @Container private static final GenericContainer redisContainer = @@ -49,11 +49,9 @@ class ReservationControllerTest { @DynamicPropertySource static void configureProperties(DynamicPropertyRegistry registry) { - redisContainer.start(); registry.add("spring.data.redis.host", redisContainer::getHost); registry.add("spring.data.redis.port", () -> redisContainer.getMappedPort(6379)); registry.add("spring.data.redis.password", () -> REDIS_PASSWORD); // 비밀번호 적용 - // 비밀번호 적용 } @Autowired @@ -65,11 +63,15 @@ static void configureProperties(DynamicPropertyRegistry registry) { @Autowired private MovieReservationService movieReservationService; + @Autowired + private RedisTemplate redisTemplate; + private MovieReservationRequestDto requestDto; @BeforeEach void setUp() { requestDto = TestDataFactory.createMovieReservationRequestDto(); + redisTemplate.getConnectionFactory().getConnection().flushDb(); // Redis 데이터 초기화 } @Test diff --git a/cinema-application/build.gradle.kts b/cinema-application/build.gradle.kts index f45033300..fd2645b2c 100644 --- a/cinema-application/build.gradle.kts +++ b/cinema-application/build.gradle.kts @@ -3,11 +3,16 @@ plugins { id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" id("java-test-fixtures") // 테스트 픽스처 활성화 + id("jacoco") // JaCoCo 플러그인 추가 } group = "com.hanghae" version = "0.0.1-SNAPSHOT" +jacoco { + toolVersion = "0.8.10" +} + repositories { mavenCentral() } @@ -22,4 +27,31 @@ dependencies { tasks.test { useJUnitPlatform() -} \ No newline at end of file +} + +tasks.jacocoTestReport { + dependsOn(tasks.test) // test 실행 후 리포트 생성 + + reports { + xml.required.set(false) // XML 리포트 비활성화 + csv.required.set(false) // csv 리포트 비활성화 + html.required.set(true) // HTML 리포트 활성화 + html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정 + } +} + +tasks.jacocoTestCoverageVerification { + dependsOn(tasks.jacocoTestReport) + + violationRules { + rule { + element = "CLASS" + limit { + counter = "BRANCH" + value = "COVEREDRATIO" + //minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 + minimum = BigDecimal("0.0") // 테스트코드 미구현으로 검증 제외 + } + } + } +} diff --git a/cinema-domain/build.gradle.kts b/cinema-domain/build.gradle.kts index 049f50318..4cf58a36f 100644 --- a/cinema-domain/build.gradle.kts +++ b/cinema-domain/build.gradle.kts @@ -3,11 +3,16 @@ plugins { id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" id("java-test-fixtures") // 테스트 픽스처 활성화 + id("jacoco") // JaCoCo 플러그인 추가 } group = "com.hanghae" version = "0.0.1-SNAPSHOT" +jacoco { + toolVersion = "0.8.10" +} + repositories { mavenCentral() } @@ -17,4 +22,31 @@ dependencies { tasks.test { useJUnitPlatform() -} \ No newline at end of file +} + +tasks.jacocoTestReport { + dependsOn(tasks.test) // test 실행 후 리포트 생성 + + reports { + xml.required.set(false) // XML 리포트 비활성화 + csv.required.set(false) // csv 리포트 비활성화 + html.required.set(true) // HTML 리포트 활성화 + html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정 + } +} + +tasks.jacocoTestCoverageVerification { + dependsOn(tasks.jacocoTestReport) + + violationRules { + rule { + element = "CLASS" + limit { + counter = "BRANCH" + value = "COVEREDRATIO" + //minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 + minimum = BigDecimal("0.0") // 테스트코드 미구현으로 검증 제외 + } + } + } +} diff --git a/cinema-infrastructure/build.gradle.kts b/cinema-infrastructure/build.gradle.kts index 806715771..4fcc7cc11 100644 --- a/cinema-infrastructure/build.gradle.kts +++ b/cinema-infrastructure/build.gradle.kts @@ -3,11 +3,16 @@ plugins { id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" id("java-test-fixtures") // 테스트 픽스처 활성화 + id("jacoco") // JaCoCo 플러그인 추가 } group = "com.hanghae" version = "0.0.1-SNAPSHOT" +jacoco { + toolVersion = "0.8.10" +} + repositories { mavenCentral() } @@ -37,4 +42,31 @@ tasks.test { tasks.withType { options.annotationProcessorPath = configurations["annotationProcessor"] // 컴파일 시 Annotation Processor가 동작하도록 설정 -} \ No newline at end of file +} + +tasks.jacocoTestReport { + dependsOn(tasks.test) // test 실행 후 리포트 생성 + + reports { + xml.required.set(false) // XML 리포트 비활성화 + csv.required.set(false) // csv 리포트 비활성화 + html.required.set(true) // HTML 리포트 활성화 + html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정 + } +} + +tasks.jacocoTestCoverageVerification { + dependsOn(tasks.jacocoTestReport) + + violationRules { + rule { + element = "CLASS" + limit { + counter = "BRANCH" + value = "COVEREDRATIO" + //minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 + minimum = BigDecimal("0.0") // 테스트코드 미구현으로 검증 제외 + } + } + } +} diff --git a/docs/img/jacoco_test_report.png b/docs/img/jacoco_test_report.png new file mode 100644 index 0000000000000000000000000000000000000000..4516a1c21b5a98427c40b8e6c3d171f81ce8446c GIT binary patch literal 243373 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�fwYqP$1Aw%Xkqoo>O3=Ab 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 Date: Mon, 3 Feb 2025 20:00:01 +0900 Subject: [PATCH 9/9] =?UTF-8?q?jacoco=5Freport=5Faggregation=20=ED=94=8C?= =?UTF-8?q?=EB=9F=AC=EA=B7=B8=EC=9D=B8=20=EC=B6=94=EA=B0=80,=20jacoco=20?= =?UTF-8?q?=EB=B3=B4=EA=B3=A0=EC=84=9C=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 11 ++++++-- cinema-adapter/build.gradle.kts | 21 ++++++++++++--- cinema-application/build.gradle.kts | 34 +------------------------ cinema-domain/build.gradle.kts | 34 +------------------------ cinema-infrastructure/build.gradle.kts | 34 +------------------------ docs/img/jacoco_report_aggregation.png | Bin 0 -> 60813 bytes 6 files changed, 29 insertions(+), 105 deletions(-) create mode 100644 docs/img/jacoco_report_aggregation.png diff --git a/README.md b/README.md index 41d00b4ef..60ab06801 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,11 @@ * DB : H2 * Redis : Testcontainers -### jacoco 보고서 -![jacoco_test_report.png](docs%2Fimg%2Fjacoco_test_report.png) +### jacoco 보고서 +![jacoco_test_report.png](docs%2Fimg%2Fjacoco_test_report.png) + +### jacoco_report_aggregation 보고서 +![jacoco_report_aggregation.png](docs%2Fimg%2Fjacoco_report_aggregation.png) ### JaCoCo * `build.gradle.kts` 파일 `plugins`에 `id("jacoco")` 추가 후 `gradle`을 다시 빌드해야 한다. @@ -20,6 +23,10 @@ * 테스트 실행 및 보고서 생성(커버리지 충족 확인) : `./gradlew clean test jacocoTestReport jacocoTestCoverageVerification --console verbose` * `build.gradle.kts`파일에 보고서 저장경로를 설정하여 `/build/reports/jacoco/index.html` 해당파일을 확인하면 된다. * `html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정` +* jacoco-report-aggregation 플러그인을 사용해 멀티모듈의 보고서를 하나로 묶어서 생성 가능 +* jacoco-report-aggregation 플러그인 사용시 명령어 : `./gradlew testCodeCoverageReport` + * 저장 경로 : 위 플러그인 설정한 모듈 build 폴더 + * `cinema-adapter/build/reports/jacoco/testCodeCoverageReport/html/index.html` ### 규칙 * `infrastruct` 계층에서의 결과값은 `domain model` 혹은 `Projection(필요한 속성만 조회)` 객체 로 리턴한다. diff --git a/cinema-adapter/build.gradle.kts b/cinema-adapter/build.gradle.kts index 3c8e218b6..e02671203 100644 --- a/cinema-adapter/build.gradle.kts +++ b/cinema-adapter/build.gradle.kts @@ -3,8 +3,8 @@ plugins { id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" id("java-test-fixtures") // 테스트 픽스처 활성화 - id("jacoco") // JaCoCo 플러그인 추가 - //id("jacoco-report-aggregation") // JaCoCo 멀티모듈 리포트 통합하기 위한 플러그인 + //id("jacoco") // JaCoCo 플러그인 추가 + id("jacoco-report-aggregation") // JaCoCo 멀티모듈 리포트 통합하기 위한 플러그인 (jacoco 플러그인을 내부적으로 포함) } group = "com.hanghae" @@ -32,12 +32,24 @@ dependencies { testImplementation ("org.testcontainers:testcontainers:1.19.3") //테스트 컨테이너 testImplementation ("org.testcontainers:junit-jupiter:1.19.3") + + // JaCoCo Report Aggregation에서만 특정 모듈을 포함하도록 설정 + jacocoAggregation(project(":cinema-domain")) + jacocoAggregation(project(":cinema-application")) + jacocoAggregation(project(":cinema-infrastructure")) + jacocoAggregation(project(":cinema-adapter")) } tasks.test { useJUnitPlatform() } +//jacoco-report-aggregation 관련 추가 +tasks.check { + dependsOn(tasks.named("testCodeCoverageReport")) // <2> +} + + tasks.jacocoTestReport { dependsOn(tasks.test) // test 실행 후 리포트 생성 @@ -58,8 +70,9 @@ tasks.jacocoTestCoverageVerification { limit { counter = "BRANCH" value = "COVEREDRATIO" - minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 - excludes = listOf("com.hanghae.adapter.web.MovieController") // 테스트코드 미구현으로 검증 제외 + //minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 + //excludes = listOf("com.hanghae.adapter.web.MovieController") // 테스트코드 미구현으로 검증 제외 + minimum = BigDecimal("0.0") // 테스트코드 미구현으로 검증 제외 } } } diff --git a/cinema-application/build.gradle.kts b/cinema-application/build.gradle.kts index fd2645b2c..f45033300 100644 --- a/cinema-application/build.gradle.kts +++ b/cinema-application/build.gradle.kts @@ -3,16 +3,11 @@ plugins { id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" id("java-test-fixtures") // 테스트 픽스처 활성화 - id("jacoco") // JaCoCo 플러그인 추가 } group = "com.hanghae" version = "0.0.1-SNAPSHOT" -jacoco { - toolVersion = "0.8.10" -} - repositories { mavenCentral() } @@ -27,31 +22,4 @@ dependencies { tasks.test { useJUnitPlatform() -} - -tasks.jacocoTestReport { - dependsOn(tasks.test) // test 실행 후 리포트 생성 - - reports { - xml.required.set(false) // XML 리포트 비활성화 - csv.required.set(false) // csv 리포트 비활성화 - html.required.set(true) // HTML 리포트 활성화 - html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정 - } -} - -tasks.jacocoTestCoverageVerification { - dependsOn(tasks.jacocoTestReport) - - violationRules { - rule { - element = "CLASS" - limit { - counter = "BRANCH" - value = "COVEREDRATIO" - //minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 - minimum = BigDecimal("0.0") // 테스트코드 미구현으로 검증 제외 - } - } - } -} +} \ No newline at end of file diff --git a/cinema-domain/build.gradle.kts b/cinema-domain/build.gradle.kts index 4cf58a36f..049f50318 100644 --- a/cinema-domain/build.gradle.kts +++ b/cinema-domain/build.gradle.kts @@ -3,16 +3,11 @@ plugins { id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" id("java-test-fixtures") // 테스트 픽스처 활성화 - id("jacoco") // JaCoCo 플러그인 추가 } group = "com.hanghae" version = "0.0.1-SNAPSHOT" -jacoco { - toolVersion = "0.8.10" -} - repositories { mavenCentral() } @@ -22,31 +17,4 @@ dependencies { tasks.test { useJUnitPlatform() -} - -tasks.jacocoTestReport { - dependsOn(tasks.test) // test 실행 후 리포트 생성 - - reports { - xml.required.set(false) // XML 리포트 비활성화 - csv.required.set(false) // csv 리포트 비활성화 - html.required.set(true) // HTML 리포트 활성화 - html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정 - } -} - -tasks.jacocoTestCoverageVerification { - dependsOn(tasks.jacocoTestReport) - - violationRules { - rule { - element = "CLASS" - limit { - counter = "BRANCH" - value = "COVEREDRATIO" - //minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 - minimum = BigDecimal("0.0") // 테스트코드 미구현으로 검증 제외 - } - } - } -} +} \ No newline at end of file diff --git a/cinema-infrastructure/build.gradle.kts b/cinema-infrastructure/build.gradle.kts index 4fcc7cc11..806715771 100644 --- a/cinema-infrastructure/build.gradle.kts +++ b/cinema-infrastructure/build.gradle.kts @@ -3,16 +3,11 @@ plugins { id("org.springframework.boot") version "3.4.1" id("io.spring.dependency-management") version "1.1.7" id("java-test-fixtures") // 테스트 픽스처 활성화 - id("jacoco") // JaCoCo 플러그인 추가 } group = "com.hanghae" version = "0.0.1-SNAPSHOT" -jacoco { - toolVersion = "0.8.10" -} - repositories { mavenCentral() } @@ -42,31 +37,4 @@ tasks.test { tasks.withType { options.annotationProcessorPath = configurations["annotationProcessor"] // 컴파일 시 Annotation Processor가 동작하도록 설정 -} - -tasks.jacocoTestReport { - dependsOn(tasks.test) // test 실행 후 리포트 생성 - - reports { - xml.required.set(false) // XML 리포트 비활성화 - csv.required.set(false) // csv 리포트 비활성화 - html.required.set(true) // HTML 리포트 활성화 - html.outputLocation.set(layout.buildDirectory.dir("reports/jacoco")) //저장경로 설정 - } -} - -tasks.jacocoTestCoverageVerification { - dependsOn(tasks.jacocoTestReport) - - violationRules { - rule { - element = "CLASS" - limit { - counter = "BRANCH" - value = "COVEREDRATIO" - //minimum = BigDecimal("0.60") // 최소 60% 커버리지 필요 - minimum = BigDecimal("0.0") // 테스트코드 미구현으로 검증 제외 - } - } - } -} +} \ No newline at end of file diff --git a/docs/img/jacoco_report_aggregation.png b/docs/img/jacoco_report_aggregation.png new file mode 100644 index 0000000000000000000000000000000000000000..17f3ec75806102b07fc721faf31b935af7ad2d8b GIT binary patch literal 60813 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 a$#4zju+Vljb_|?B2ytN