본문 바로가기
카테고리 없음

Django Cache 따닥 중복 요청 방지

by Byeong 2024. 11. 18.

문제 

 게시물이나 댓글을 생성하는 버튼을 화면 전환 전에 여러 번 클릭하면 동일한 요청이 중복으로 발생하는 문제가 나타났다.

이로 인해 데이터베이스에는 의도와 상관없이 중복된 값이 저장되었고, 서버로 필요 없는 API 요청이 여러 번 전달되었다.

 

여러번 클릭시 발생 된 api

 특히 결제 시스템처럼 중요한 트랜잭션이 처리되는 경우, 동일한 결제가 중복으로 발생할 가능성이 있다. 이는 금전적 손실과 사용자 불만으로 이어질 수 있으며, 심각한 신뢰도 문제 생길 수 있다.

 

 단순히 프런트엔드에서만 처리할 경우, 개발자 도구를 이용한 요청 조작이나 네트워크 지연 등으로 인해 중복 요청이 발생할 수 있다. 이를 방지하기 위해 서버에서도 확실한 검증과 처리가 필요하다. 프런트엔드와 백엔드 모두에서 중복 요청 방지를 구현함으로써 시스템 안정성을 높였다."

 


해결방법

 

Frontend

 

클릭 시 disabled 속성을 추가하여 버튼을 비활성화하고, 요청 완료 후 다시 활성화하도록 구현했다.

이렇게 하면 사용자가 요청 처리 중 버튼을 반복 클릭할 수 없게 된다.

<button className={style.button} onClick={postCreate} disabled={isSubmitting}>
    등록
</button>

 

 

Backend 

  1. 요청 데이터(본문) 해시 생성
    요청 데이터를 해시 처리해 고유한 키를 생성. 동일한 데이터가 들어올 경우 동일한 해시 값이 생성되므로 이를 통해 중복 여부를 판단.
  2. Redis를 활용한 중복 요청 방지
    캐시에서 요청 해시를 검색해 중복 여부 확인.
    • 캐시에 이미 해시가 존재하면 오류 응답 반환.
    • 해시가 없으면 캐시에 저장하고 요청 처리.
 
...

def post(self, request):
    data = request.data
    # 요청의 본문을 해시하여 고유한 키 생성
    request_hash = hashlib.md5(str(data).encode('utf-8')).hexdigest()
    cache_key = f'post_request_{request_hash}'

    # 캐시에서 해시를 검색
    if cache.get(cache_key):
        return Response({"error": "Duplicate request"}, 
                    status=status.HTTP_400_BAD_REQUEST)

    #캐시에 해시 저장 (예: 10초 동안)
    cache.set(cache_key, True, timeout=10)
    
...

 

 


결과 

 중복으로 발생하던 요청이 이제 한 번만 처리되도록 개선했다.

데이터베이스의 무결성이 보장되고, 서버 낭비가 줄어들어 서비스의 안정성이 향상됐다.

 

 

중복 요청시 setatus 400발생

 

Redis를 활용한 중복 요청 방지 외에도 자주 조회되는 데이터를 캐싱해 서버 성능을 최적화할 수 있을거같다.