[4기 김별] Shorten URL 과제 PR입니다#52
[4기 김별] Shorten URL 과제 PR입니다#52byeolhaha wants to merge 18 commits intoprgrms-be-devcourse:byeolhahafrom
Conversation
- 2차 캐시 이용하여 Origin Url 찾기
|
|
||
| @Scheduled(fixedRate = 3600000) | ||
| public void evictUrlsCache() { | ||
| log.info("캐시는 1시간 뒤에 지워집니다."); |
There was a problem hiding this comment.
사실 테스트를 통해서 검증했어야 했는데
@Scheduled에 대한 테스트 방법을 발견하게 되어 추가하도록 하겠습니다.
중요하지 않고 불필요한 로그 메세지여서 삭제하도록 하겠습니다.
|
|
||
| private final CacheManager cacheManager; | ||
|
|
||
| @Autowired |
There was a problem hiding this comment.
ㅋㅋ 태그걸때 꼭 그걸로 이름지은 놈들 있어서 조심하셔유 ㅋㅋ @Autowired
| @ExceptionHandler(ExistedOriginUrlException.class) | ||
| protected ResponseEntity<ErrorResponse> handleExistedOriginUrlException(ExistedOriginUrlException e) { | ||
| log.warn("Handle ExistedOriginUrlException", e); | ||
| final ErrorResponse response = ErrorResponse.of(e.getErrorCode(), e.getMessage()); |
There was a problem hiding this comment.
왜 지역변수에 final을 사용하셨어요?
파라미터도 final을 붙여주는것이 좋아요.
메서드 내에서 해당 파라미터의 값을 변경할 수 없게 되어 파라미터 값이 예기치 않게 변경되는 것을 방지할수 있거든요
물론 코딩스타일이나 팀의 코딩 컨벤션에 따라 다르기도 해요
There was a problem hiding this comment.
메서드 내에서 변할 수 없다는 것을 내포하고, 실제로 변경에 대한 위험을 방지하기 위해서 넣게 되었습니다.
파라미터에 final도 좋은 방법인 거 같아
다음 프로젝트를 진행할 때 팀원들과 이야기해 코딩 컨벤션을 정하도록 할게요 💡
| */ | ||
| @ExceptionHandler(MethodArgumentNotValidException.class) | ||
| protected ResponseEntity<ErrorResponse> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { | ||
| log.warn("Handle MethodArgumentNotValidException", e.getMessage()); |
| final ErrorResponse response = ErrorResponse.of(INTERNAL_SERVER_ERROR, e.getMessage()); | ||
| return ResponseEntity | ||
| .status(HttpStatus.INTERNAL_SERVER_ERROR) | ||
| .body(response); | ||
| } |
There was a problem hiding this comment.
| final ErrorResponse response = ErrorResponse.of(INTERNAL_SERVER_ERROR, e.getMessage()); | |
| return ResponseEntity | |
| .status(HttpStatus.INTERNAL_SERVER_ERROR) | |
| .body(response); | |
| } | |
| final ErrorResponse response = ErrorResponse.of(INTERNAL_SERVER_ERROR, e.getMessage()); | |
| return ResponseEntity | |
| .status(HttpStatus.INTERNAL_SERVER_ERROR) | |
| .body(response); | |
| } |
There was a problem hiding this comment.
개행에 의미를 부여해서 가독성을 높이도록 하겠습니다 🔦
There was a problem hiding this comment.
e.getMessage도 좋지만 Throwable을 파라미터로 받는것도 괜찮을듯 합니다ㅎ
| shortUrlService.creatShortUrl(naverUrlToSave.getOriginUrl(), "BASE62"); | ||
| savedNaverUrl = shortUrlRepository.findByOriginUrl(naverUrlToSave.getOriginUrl()).get(); | ||
|
|
||
| for (int i = 0; i < 20; i++) { |
There was a problem hiding this comment.
10번 이상일 때 캐시에 저장된 객체를 가져오는가를 테스트하기 위함이었지만
실제로 테스트를 보는 사람은 저 20의 의미를 알기 어렵다고 생각합니다.
그리고 저 20이라는 숫자는 바뀔 수 있는 수이기 때문에
항상 같은 테스트 결과가 나오도록 고치겠습니다.
|
|
||
| private Optional<Urls> getCacheUrl(String shortUrl) { | ||
| return Optional.ofNullable(cacheManager.getCache("urls")).map(c -> c.get(shortUrl, Urls.class)); | ||
| } | ||
|
|
||
| @Test | ||
| @DisplayName("요청 횟수가 정해진 limit 수를 넘어가면 2차 캐시에 저장하여 다음 요청에서 2차 캐시에 있는 origin url을 반환한다.") | ||
| void getUrlByShortUrl_overLimitedBoundCount_returnCache() { | ||
| //when | ||
| Urls urlByShortUrl = shortUrlRepository.getUrlByShortUrl(savedNaverUrl.getShortUrl()); | ||
|
|
||
| //then | ||
| assertThat(urlByShortUrl).isEqualTo(getCacheUrl(savedNaverUrl.getShortUrl()).get()); | ||
| } |
| class ShortUrlServiceImplTest { | ||
|
|
||
| private final Urls NAVERURL = Fixtures.naverUrlInOriginUrl(); | ||
| ; |
There was a problem hiding this comment.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
| shortUrlService.creatShortUrl(NAVERURL.getOriginUrl(), STRATEGY_TYPE); | ||
|
|
||
| //when_then | ||
| assertThrows(ExistedOriginUrlException.class, () -> shortUrlService.creatShortUrl(NAVERURL.getOriginUrl(), STRATEGY_TYPE)); |
There was a problem hiding this comment.
| assertThrows(ExistedOriginUrlException.class, () -> shortUrlService.creatShortUrl(NAVERURL.getOriginUrl(), STRATEGY_TYPE)); | |
| assertThrows(ExistedOriginUrlException.class, | |
| () -> shortUrlService.creatShortUrl(NAVERURL.getOriginUrl(), STRATEGY_TYPE)); |
저는 너무 길어지면 이렇게 쓰기도 해요.
|
|
||
| private final Urls NAVERURL = Fixtures.naverUrlInOriginUrl(); | ||
| ; | ||
| private final String STRATEGY_TYPE = "BASE62"; |
There was a problem hiding this comment.
중복 발견! 오타나면 영문도 모르겠어요. StragteType을 어떻게 관리하면 좋을까요
WooSungHwan
left a comment
There was a problem hiding this comment.
캐시에다가 shortenurl을 저장하는 부분을 제외하고는 괜찮은 것 같습니다. 영수님이 이미 좋은 리뷰를 많이 주셔서 첨언할 부분은 cache 의 hit정도가 이 프로젝트의 그 기능이 적절한지에 대해서 고민해보면 좋을듯요. sql이나 jpa에도 캐시를 활용하는 부분이 있다는 점을 생각해보면 좋을 듯해요.
|
|
||
| private final CacheManager cacheManager; | ||
|
|
||
| @Autowired |
There was a problem hiding this comment.
ㅋㅋ 태그걸때 꼭 그걸로 이름지은 놈들 있어서 조심하셔유 ㅋㅋ @Autowired
|
|
||
| @Scheduled(fixedRate = 3600000) | ||
| public void evictUrlsCache() { | ||
| log.info("캐시는 1시간 뒤에 지워집니다."); |
| final ErrorResponse response = ErrorResponse.of(INTERNAL_SERVER_ERROR, e.getMessage()); | ||
| return ResponseEntity | ||
| .status(HttpStatus.INTERNAL_SERVER_ERROR) | ||
| .body(response); | ||
| } |
There was a problem hiding this comment.
e.getMessage도 좋지만 Throwable을 파라미터로 받는것도 괜찮을듯 합니다ㅎ
| @Column | ||
| @Embedded | ||
| private ShortUrl shortUrl; |
There was a problem hiding this comment.
unique 조건 생략된것 같네요. 비즈니스적 insert 동시성을 해결하는 이슈로 db의 unique를 활용할 수 있습니다.
|
|
||
| public interface ShortUrlRepository { | ||
|
|
||
| void isExistedOriginUrl(String originUrl); |
There was a problem hiding this comment.
프로젝트 전반적으로 is로 시작하는 void가 많이보이는데 is는 플래그를 상징하는 키워드임. getXX랑 같이 뭔가 boolean을 리턴할것같은 느낌을 주니 반드시 고치세요.
|
|
||
| public interface ShortUrlRepository { | ||
|
|
||
| void isExistedOriginUrl(String originUrl); |
There was a problem hiding this comment.
코드를 고치라는 부분이 아니라 이렇게 작성되지 않도록 고쳐보세요. 재발되면 안될것 같아요.
📌 과제 설명
👩💻 요구 사항과 구현 내용
✅ PR 포인트
@Scheduled를 이용해서 비우는 작업을 했습니다.1시간의 의미는 실제 요청에 대한 데이터가 있어야 올바른 예측값이 나올 거 같습니다.https://나http://로 시작하는지 확인하는 작업을 했습니다.