프론트엔드에서 중복 요청 방지하기

404·2022년 7월 26일
1

JS ❤️ TS

목록 보기
6/6
post-thumbnail

기존에 했던 프로젝트를 typescript로 다시 만들며 서비스로직도 ssr 의존도를 낮추는 방향으로 변경하고있다.

그 과정중에 고민했던 부분에 대해 적어본다.

깃헙 전체 소스 (97줄 -) https://github.com/FUNco247/typeRemicord/blob/master/src/front/js/writeRecord.ts

대략적인 UI와 함께 로직을 설명하자면, 데이터의 추가 및 삭제는 localstorage를 통해서 하고 최종 데이터를 전송할 때 localstorage에 있는 데이터들을 꺼네 json으로 post한다. 서버에서는 데이터를 받아 저장한다.

서버 로직은 (현재 구현 전이지만) json 데이터를 받아 전송된 날짜에 맞게 저장하고 수정된 데이터가 전송될 경우 해당 날짜의 데이터를 삭제 후 다시 저장한다 (교체)

이 때, 데이터 전송 버튼을 연타했을 경우 동일한 데이터를 삭제하고 저장하는데 들어가는 서버측 리소스를 없애기 위한 방법이 없을까 고민했다. 추가로 전송할 데이터가 없을 때에도 post 요청을 할 수 없도록 하고싶었다.

let postedKeys: string[] = [];

const postData = async (e: Event) => {
  let postData: RecordDataDTO[] = [];
  e.preventDefault();
  if (localStorage.length === 0) {
    return alert("전송할 기록이 없습니다");
  } else {
    const localStorageKeys = Object.keys(localStorage).sort();
    if (localStorageKeys.filter((e) => !postedKeys.includes(e)).length === 0) {
      return alert("이미 전송된 데이터입니다.");
    }
    postedKeys = localStorageKeys;
    for (let i = 0; i < localStorageKeys.length; i++) {
      const data = JSON.parse(localStorage.getItem(localStorageKeys[i])!);
      postData.push(data);
    }
    const userId = location.pathname.split("/").pop();
    const response = await fetch(`http://localhost:8282/record/${userId}`, {
      method: "POST",
      body: JSON.stringify(postData),
      headers: {
        "Content-type": "application/json; charset=UTF-8",
      },
    });
    const json = await response.json();
    alert(`${json.message}`);
  }
};

postBtn.addEventListener("click", postData);

봐야할 부분은 첫 번쨰 else절이다.

로컬스토리지의 key 값들을 불러와 정렬한다 (로컬스토리지 key는 고유한 값을 부여하기 위해 Date.now() 의 시간 값을 사용했다.) 이 값을 postedKeys 배열과 비교한 후 값이 다르면 api를 호출하고 이번 호출에 썼던 key의 배열을 postedKeys에 다시 할당하는 식으로 구현해봤다.

이번에 전송했던 데이터를 그대로 전송하려고 할 경우 첫 단계에서 key들을 비교한 후 api 호출을 막아줄 것이다.

한계점

postedKeys 배열은 페이지가 새로고침 되면 다시 빈 배열로 초기화된다는 것이다. 이렇게 중복요청을 아얘 막을수는 없다는 한계가 있다.

위와 같은 방식을 사용해서 api 중복 요청을 막을 수 있는 방법이 있거나 다른 새로운 방법이 있는지 더 공부를 해봐야겠다.

P.S

혹시 이 글을 보시는 분들 중 누군가 알고계신다면 지도 부탁드리겠습니다 ^_^

profile
T.T

0개의 댓글