문제 발생 - 막 여러개 씩 저장 가능한거 같아요!
" 맥북에서 사용하는데 문제를 저장하려고 하면 2개씩 저장되는거 같다는 말을 들었다. 때문에 이를 직접 사용해보니 급하게 와다다다 누르면 중복으로 저장되는 것을 알 수 있었다.
위 사진이 바로 그 예시인데, 연속으로 클라이언트에서 클릭하면 많이 나온다는 것을 알 수 있다. 즉, 같은 것을 보내려고 하는데 클라이언트가 화면 전환이 되기전에 연속적으로 클릭이 된다면 api가 추가적으로 요청된다는 것이다.
이는 서버에 불필요한 데이터를 남기는 것이며, 필요이상으로 요청이 많이 들어가는 경우가 생기기 때문에 해결해야 할 문제였다.
해결방안 - 락 걸어두기 (스레드 슬립, RateLimiter, 버킷)
결국 위의 문제를 해결하려면 요청에 제한을 두는 것으로 방지해야 한다는 생각을 했다. 그렇다면 어떤 식으로 해야할까? 하며 여러가지 방법을 찾았다.
- 스레드 슬립
우선 스레드 슬립의 경우 자바 자체에서 제공하는 기능으로 스레드의 ms 단위로 정지시간을 임의대로 부여하여 작동한 스레드에 정직시간을 부여하는 것이다. 이를 활용하면 1번 작동한 스레드에 대하여 정지시간을 부여하기 때문에 위와 같은 문제를 해결가능하지만, try catch 문을 통해 구현하기 때문에 가독성이 떨어진다는 느낌이 강해 잠시 미뤄두었다.
- RateLimiter
RateLimiter 구글에서 제공하는 Guava의 내부에 있는 클래스 중 하나입니다. 이 것은 초당 api 요청 횟수를 제한 가능한 기능으로 지정해 둔 횟수를 초과하는 요청을 보내면 지정해둔 예외를 보내는 형식으로 메소드에 제한을 거는 것이다
예로 api에 제한을 1초당 1회로 걸었다면 2번 이상의 요청은 429 오류를 발생시키며 너무 많은 요청이라는 오류를 던져준다.
- 버킷
버킷의 경우 임의의 사이즈와 시간을 정해서 버킷을 만들어 정해진 시간보다 많은 횟수의 시도를 하면 요청을 거부하는 방식으로 구현 가능하다. 그러나 이 방법은 정확하게 원하는 시간으로 가능한 것도 아니며 뭔가 이 기능은 타임락의 기능을 중심으로 한 것 보다는 우선적으로 하는 몇개의 요청을 받아들이는 기능 같다는 생각이 지배적이였다.
결정 & 진행
때문에 해당 타임락을 구현하는 방식은 코드의 가독성을 중심으로 하여 RateLimiter로 정했다. 초당 요청횟수를 제한한다는 점이 스레드 슬립의 한번 작동하면 대기시간을 부여한다는 방식보다 마음에 들었고 가장 주된이유인 코드의 가독성이 보다 읽기 편해보인다는 생각이 들어 선택하게 되었다.
try& catch 를 통하여 구현하는 것 보다는
private static final RateLimiter rateLimiter = RateLimiter.create(0.5);
--- 컨트롤러 코드 ---
if(!rateLimiter.tryAcquire()) throw new CustomRateLimiterException("잠시만 기다려 주시면 감사하겠습니다. ");
--- 컨트롤러 코드 ---
위의 그림과 같이 구현하는 것이 보다 가독성 측면에서 장점이라고 생각하였다.
그 결과 이제는 아무리 여러번 누르거나 2번 선택된다 하여도 1번의 요청이 들어가는 것으로 수정하였고 잘 진행되었다.
'Spring' 카테고리의 다른 글
알고리즘 풀이 - 자료구조 (0) | 2023.11.27 |
---|---|
기능 구현 - 비회원 기능 (0) | 2023.11.08 |
항해 99 - 트러블 슈팅 Optional(Likes) (1) | 2023.10.25 |
항해 99 - 서비스와 RDB (1) | 2023.10.21 |
항해 99 실전 프로젝트 - 트러블 (Optional) (0) | 2023.10.19 |