인증 API 레이트리밋 설계: 로그인/회원가입/비번재설정은 다르게
브루트포스/계정 유추를 막으면서도 정상 사용자는 덜 불편하게 만드는 레이트리밋 설계
인증 영역은 트래픽 패턴이 특이합니다.
- 정상 사용자: “가끔” 로그인/가입/비번재설정
- 공격자: “짧은 시간에” 수백~수천 회 시도
그래서 인증 API는 “전체를 똑같이 제한”하면 UX가 나빠지고, “제한을 안 하면” 계정 탈취/남용에 취약해집니다.
관련 용어: Rate limiting, Brute force attack
1) 엔드포인트별로 버킷을 분리하세요
추천하는 최소 분리 기준:
- 로그인:
POST /api/auth/login - 회원가입:
POST /api/auth/register - 비밀번호 재설정 요청:
POST /api/auth/forgot-password - 비밀번호 재설정 확정:
POST /api/auth/reset-password - 중복 검사(이메일/아이디/닉네임 등):
POST /api/auth/check/*
특히
check/*같은 “존재 여부를 유추할 수 있는 API”는 더 강하게 제한하는 편이 안전합니다.
2) 예시 정책(초안)
서비스 성격/가입 전환률에 따라 달라질 수 있지만, 시작점으로 쓸 수 있는 값입니다.
- 로그인: 5분 8회
- 회원가입: 10분 20회
- forgot/reset: 10분 10회
- check*: 5분 120회(또는 더 낮게) + 응답은 항상 동일하게
- 일반 API: 15분 200회(서비스별로 조정)
3) 어디에서 제한할까? (nginx vs 앱 vs WAF)
- 앱(Express 등): 사용자별/이메일별/세션별로 더 정교하게 제한 가능 (권장)
- nginx: 기본적인 IP 기반 제한에 강함(간단/고성능)
- WAF/CDN: 국가/ASN/봇 룰 등 상위 레벨 차단에 유리
보통은 앱 레이트리밋 + (필요하면) nginx/WAF 보조 조합이 안전합니다.
4) 계정 유추 방지(중요)
forgot-password 같은 API는 “이메일이 존재하는지”를 공격자가 알아내기 쉬운 포인트입니다.
- 이메일이 없더라도 항상 성공 응답을 줍니다.
- 내부적으로만 로그/알람으로 구분합니다.
5) 운영 체크리스트
- 제한에 걸렸을 때
429+Retry-After를 제공 - 실패 로그인(비밀번호 틀림) 횟수를 따로 집계(알람 기준 설정)
- 동일 IP에서 다수 계정에 대해 시도하면 더 강하게 제한(조합 키: IP + user/email)
같이 보면 좋은 문서: