221222 TIL Bucket4J를 이용해 외부 api 관리

KiCK OFF 프로젝트에서 축구 경기 일정을 조회하기 위해 무료(인줄 알았던..) api인 rapid api를 사용하고 있었다.

그런데 11월 말 코딩을 하던 중 핸드포네서 "띠링" 소리가 울렸다. 확인해보니 카드 결제소리 였다.. 

자동이체 해놓은게 없는데 돈이 빠져나가 확인해보니 RAPIDAPI 에서 자동으로 6,770원을 뺏어(?)갔다.. 

 

부리나케 rapid api 사이트에 가서 pricing 부분을 다시 확인해보니 하루에 100번 요청까지만 무료고 다음 요청부터는 0.005달러씩 추가 요금이 발생한다고 적혀있었다.

 

뭐 아무튼 6,770원만 빠져나간걸 감사하게 생각하고 급한대로 경기 요청 api는 우선 사용하지 못하도록 막아놨었다. 해당 api를 사용하는 부분은 모두 구현을 했기 때문에 배포 전까지는 막아놓고 있었다.

 

근데 이제는 배포를 해야할 때라서 서비스를 출시하기 전에 이 api를 어떻게 과금이 안되게 막을것인지 생각해볼 필요가 있었다.

 

제한할 수 있는 방법을 찾아보다 나에게 아주 딱 유용한 Bucket4J라는 라이브러리를 찾았다.

Bucket4J

https://github.com/bucket4j/bucket4j

목적은 클라이언트로부터 요청이 과도하게 들어왔을때 속도가 느려지는 것을 방지하기 위해 사용하거나 특정 사용자들에게 일정 횟수로 사용을 제한해서 요금을 받고 제한을 풀어주는 Business Model을 적용할떄 사용한다고 한다.

 

이것을 적용하면 하루에 100번만 api요청을 제한할 수 있겠다고 생각을 했다.

 

그런데 해당 라이브러리는 Java에서 사용하는 라이브러리인데 현재 프로젝트에서 api요청을 프론트엔드에서 사용하고 있어서 귀찮지만 rapid api 요청하는 부분을 js -> java로 이동시켜야 했다.

귀찮지만 돈을 지키려면 해야지..

 

버킷 생성 방법

우선 Bucket4j 의존성 부터 추가해줍니다. 

implementation 'com.github.vladimir-bukhtoyarov:bucket4j-core:7.6.0'

 

그 다음 사용을 제한하고 싶은 곳엣서 Bandwidth를 생성하는데 Bandwidth는 사용자가 지정한 시간동안 제한할 개수를 지정할 수 있도록 해준다.

 

나같은 경우는 하루에 100번만 요청하도록 할거니까 아래와 같이 설정해주면 된다.

Bandwidth limit = Bandwidth.simple(100, Duration.ofDays(1));

물론 하루 말고도 초(Duration.ofSeconds()), 분(Duration.ofMinutes()), 시간(Duration.ofHours())등등 제한하고 싶은 시간만큼 설정하고 제한할 갯수를 앞에 써주면 된다.

 

그러면 제한 시간이 지나면 자동으로 설정해준 갯수만큼 bucket이 채워진다.

 

이후에 생성한 Bandwidth를 이용해 Bucket을 생성한다.

Bucket bucket = Bucket4j.builder().addLimit(limit);

 

이제 하루에 100개를 사용할 수 있는 bucket이 생겼다.

 

그 다음 이 bucket을 api 요청한번할때마다 소비하도록 해야한다.

 

if (bucket.tryConsume(1)) {
    
} else {
    이용 초과
}

if문 안에 tryComsume 메서드를 이용해 버킷을 소비할 수 있다. 한번에 소비할 버킷 갯수는 마음대로 설정 가능하다.

 

만약 설정한 bucket을 다 소비하면 else문을 통해 api요청을 못하도록 막으면 된다.

 

추가로 bucket.getAvailableTokens()메서드를 이용하면 버킷이 몇개 남았는지도 알 수 있다.

 

과금방지는 중요하다. 뭐든지 요금 정책을 살피고 사용하도록 하자! (피같은 7천원..)