프로젝트를 진행하는데 있어서 회원가입 시 이메일 인증 기능을 구현하게 되었다.
이메일 인증을 구현하기 위해서 구글 SMTP를 이용하여 구현하였다. 이처럼 구글 SMTP는 구글 서버에서 제공되는 서비스이기 때문에 외부 API를 호출하는 것과 같다.
또한 구글 SMTP 서비스는 하루에 500개의 전송 한도가 정해져 있고, 악의적인 사용자가 반복적으로 인증 이메일을 요청하게 될 경우에는 이메일 인증 기능이 정상적으로 작동하지 않아 회원가입도 불가능하게 되는 상황까지 유발할 것이라고 생각이들었다. 이러한 문제점을 해결하기 처리율 제한 장치를 도입한 과정에 대해 회고록을 작성해보려고 한다.
처리율 제한 기능을 구현하기 위해서 공부하던 중, 다양한 처리율 제한 알고리즘이 있다는 것을 알게되었다.
그리고 처리율 제한 기능을 구현하기 위해서 어떠한 알고리즘을 선택하는게 좋을지 생각해보려고 한다.
토큰 버킷이라는 지정된 용량을 갖는 컨테이너를 사용한 알고리즘이다.
토큰 버킷 알고리즘과 비슷하지만 요청 처리율이 고정되어 있다.
보통 FIFO(First In First Out)으로 구현한다.
고정 윈도 카운터 알고리즘은 정해진 시간 구간 동안 허용 임계값 만큼의 요청만 처리하고, 임계값 이상의 요청들은 새로운 시간구간이 찾아올 때 까지 버리는 방식이다.
이동 윈도 로그 알고리즘은 고정 윈도 카운터 알고리즘에서 지적한 단점을 보완하기 위해 등장한 알고리즘이다.
고정 윈도 카운터 알고리즘과 이동 윈도 로그 알고리즘을 결합한 것이다.
이번에는 SpringBoot에서 처리율 제한 기능을 구현하기 위한 대표적인 라이브러리에 대해서 정리해보려고한다.
Bucket4j는 토큰 버킷 알고리즘을 기반으로 하는 Java 속도 제한 라이브러이다.
특징으로는 동시에 lock-free한 구현으로 멀티 스레딩 환경에서의 확장성이 우수하며, 추가적인 동시성 전략도 제공한다.
Guava는 구글에서 개발한 라이브러리이며, 토큰 버킷 알고리즘 기반이다.
Guava의 경우 처리율 제한 목적으로 나온 라이브러리는 아니지만, 제공하는 기능 중 처리율 제한 기능이 존재한다.
RateLimitJ는 이동 윈도 알고리즘을 기반으로 하는 Java 속도 제한 라이브러리이다.
Github ReadMe 첫 줄에 "This project is no longer supported, please consider using Bucket4j instead" 라고 나와 있다...
여러 처리율 제한 알고리즘, 어떠한 라이브러리를 사용하지에 대해 고민해보았다.
우선, 진행하는 프로젝트에서 처리율 제한 장치를 왜 도입하는지에 대해 생각해보았다.
도입하는 이유는 구글 STMP 서비스 제한된 사용량에 따적 악의적인 많은 요청을 예방하기 위한 것이다.
위 요구사항을 만족하기 위해서는, 어떤 처리율 알고리즘을 사용해도 무방할 것이라고 생각이 들었다.
그래서 해당 프로젝트에서 사용할 수 있는 라이브러리를 기반으로 생각해보았다.
진행중인 프로젝트는 3.2.5버전의 Spring Boot 프레임워크로 진행하고 있다.
하지만, RateLimitJ는 현재 더 이상 지원하지 않기때문에 Bucket4J를 사용하라는 문구가 적혀 있으며, 이슈가 발생할 수 있다는 점을 고려했을 때, 후보에서 제외하였다.
남은 Guava
와 Bucket4J
중 고민을 했다.
두 라이브러리 모두 토큰 버킷 알고리즘을 기반으로 하고 있는데 어떤 차이점이 있는지 알아보았다.
Guava는 구글에서 개발한 Java 라이브러리로, 원래 목적으로는 처리율 제한 목적이 아니고 기본적인 토큰 버킷 알고리즘을 제공한다고한다. 그에 비해 Bucket4J는 토큰 생성 속도 조절, 토큰의 최대 용량 설정, 동적 조절 등 다양한 기능을 제공한다고 한다.
따라서, Bucket4J는 Guava에 비해서 더 복잡한 요청 제한을 구현하기 유용하다고 판단해서 토큰 기반 알고리즘 기반의 Bucket4J를 사용하기로 결정했습니다.