-
Notifications
You must be signed in to change notification settings - Fork 28
[4주차] Rate Limit 구현 및 테스트 코드 작성 #70
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: CJ-1998
Are you sure you want to change the base?
Conversation
명사형이던 메서드명 동사로 수정 메서드명에 불필요한 중복 제거
JpaRepository에 @repository annotation 제거
락 확득 실패 시 그냥 500 에러로 응답되고 있었음 이 예외를 409 conflict로 응답하도록 ApiControllerAdvice에 추가
ReservationService에서 수행하던 valid 로직 클래스로 추출 ReservationValidator라는 클래스에서 수행하도록 이동
DB ddl에 id에 unsigned 추가 인덱스 컬럼 순서 수정 data.sql에 불필요한 데이터 제거
ApiControllerAdvice에 예외 타입 수정하지 않아 오류 발생하던 점 수정
Infrastructure 모듈에 Guava dependency 추가
rate limiter에 필요한 메타데이터 위한 annotation 생성
Rate Limiter의 로직 있는 인터페이스 생성
Guava 사용해 RateLimiter 구현할 구현체 클래스 생성 로직 작성 중
조회 RateLimit 관련 annotation 수정
조회 요청에 대한 Rate Limit 로직 GuavaRateLimiter 구현체에 구현
조회 Rate Limit 위한 Aspect 구현 조회 RateLimiter 인터페이스, 구현체 Object 반환하도록 수정
IP 주소 쉽게 얻기 위한 config 생성 yml에 설정 추가
조회 api에 annotation에서 key로 IP 사용 따라서 조회 api controller에서 IP 받아오게 함 조회 api service의 메서드 파라미터로 IP 넘기도록 수정
GuavaRateLimiter에 예외 터지면 Too Many Requests 터지도록 추가
50번째 요청에서 예외 발생하는지 테스트 코드 구현
Controller에 HttpServlerRequest 사용 그러고 Application 모듈에서 @SpringBootTest 하니까 테스트 터짐 Application 모듈에 Spring Web dependency 추가 이게 맞는 해결 방법인지는 모르겠음
캐시 annotation과 Rate Limit annotation이 함께 있으니 문제 발생 Rate Limit annotation이 작동 안하는 것 같음 테스트에서 예외 발생 안함 우선 캐시 annotation 주석 처리해 놓음 어떻게 해결할지 추후 고민
조회 Rate Limit 정상 동작 테스트 추가 Rate Limiter의 Map clear 하는 메서드 추가
조회용 Rate Limiter 관련 fetchratelimiter 패키지로 이동 조회용 Rate Limiter 모두 Fetch 추가
예약 api에 적용할 Rate Limiter의 인터페이스, 구현체 구현
예약 Api 있는 ReservationService에 annotation 적용 annotation에 userId, screeningId String으로 수정
예약 api에서 Rate Limit 잘 동작하는지 테스트
Guava 붙은 것들 Map으로 수정 생각해보니 Guava는 사용하지 않고 Map으로 해결하고 있었음
Redis 이용한 예약 API Rate Limiter 구현
테스트 코드 application 모듈에 TestApplication 만들어 동작하게 함 presentation 모듈의 CinemaApplication 사용하려고 하니 자꾸 오류남
application 모듈 테스트를 위한 데이터 넣을 data.sql 추가
예약 동시성 테스트 및 예약 Rate Limiter 테스트 동시 수행되게 수정 테스트 이전, 이후에 Rate Limiter의 Redis 비우도록 추가
jacoco 멀티 모듈 프로젝트에서 전체에 대한 리포트 나오도록 설정 추가
|
@CJ-1998 님, 안녕하세요~ 리뷰 시작하겠습니다. |
|
|
guava에 포함된 해당 라이브러리들을 활용해서 데이터들을 관리할 수 있습니다. 아래 예시를 참고해주세요. 조회의 경우 clientIp 를 받고 |
| int blockTime = limitRequestPerTime.blockTime(); | ||
|
|
||
| if (diffMinutes <= blockTime) { | ||
| throw new ResponseStatusException(HttpStatus.TOO_MANY_REQUESTS, "Too many requests"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ResponseStatusException 를 사용하여 TOO_MANY_REQUESTS 로 처리해주셨네요.
guava로 구현된 건 아니지만, 요구사항을 잘 구현해주셨습니다.
|
|
||
| @Component("RedisRateLimiter") | ||
| @RequiredArgsConstructor | ||
| public class RedisFetchRateLimiter implements FetchRateLimiter { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 기능은 presentation 레이어에서 구현하시지 않고, infra 계층에서 구현하신 이유가 있을까요?
| @Override | ||
| public Object tryApiCall(LimitRequestPerTime limitRequestPerTime, ProceedingJoinPoint joinPoint) throws Throwable { | ||
|
|
||
| String blockKey = "block_ip:" + limitRequestPerTime.key(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blockKey 로직의 경우는 재사용이 많이 되기에, 별도 메서드나 유틸로 빼도 좋을 것 같습니다.
|
|
||
| @ResponseStatus(HttpStatus.CONFLICT) | ||
| @ExceptionHandler(IllegalStateException.class) | ||
| public ApiResponse<Object> IllegalStateException(IllegalStateException e) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요고 추가하신 이유가 궁금합니다.
특별히 CONFLICT 되는 부분이 존재하나요?
| HttpServletRequest request) { | ||
| String clientIp = request.getRemoteAddr(); | ||
| List<NowPlayMovieDto> nowPlayMovieDtos | ||
| = movieQueryService.getNowPlayingMovies(movieTitle, movieGenre, clientIp); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ip 가 service 계층에 영향을 줄 필요는 없을 것 같습니다.
따로 intercepter 라던지 Aop 로 관심사를 분리해주시면 더 좋을 것 같아요 👍
|
@CJ-1998 님, 고생하셨습니다. 👍 좋았던 점
아쉬웠던 점
|
제목(title)
[4주차] Rate Limit 구현 및 테스트 코드 작성
📝작업 내용
🔒해결하려는 문제 혹은 고민이 되었던 부분을 남겨주세요.(문제 수 만큼 복사해서 사용할 것)
🔑해당 문제를 어떻게 해결했나요? 그리고 왜 그렇게 생각했는지 이유를 남겨주세요.(자세하게 남겨주실 수록 좋습니다.)
💬리뷰 요구사항(선택)
기타 사항 📌
추가로 언급할 사항이 있다면 여기에 적어주세요.