인증 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)

같이 보면 좋은 문서:

관련 가이드