지난번 포스팅 Recoil selector를 사용한 비동기 처리에서 리코일을 사용한 서버요청하는 작업을 소개했다.
이번에 이슈트래커라는 새로운 프로젝트를 진행하며 상태관리에서 recoil을 한번 더 사용해봤다. 그 과정에서 예상치 못한 문제가 발생했다.
지난번 글에서 말했던 서버요청시 캐쉬를 하는 기능 때문에 발생한 문제였다. 어떤 문제가 발생했고 이를 어떻게 해결했는지를 공유하기 위해 이번 포스팅을 준비했다.
selector에서 서버에 GET요청을 할 때 큰 장점 중 하나는 캐쉬를 한다는 것이다. 지난번 포스팅에서도 다룬 내용인데 사용하는 atom(상태)값
, URL
을 비교해서 동일하다면 서버로 요청을 다시 보내는 것이 아닌 캐쉬된 값을 사용한다.
이 부분에서 문제가 발생했다.
아래 상황의 순서는 이렇다.
1. 이슈의 제목을 변경한다. (`PATCH` 요청)
2. 메인화면인 이슈리스트로 나간다.
3. 다시 이슈 상세페이지로 들어간다.
4. 이슈 제목이..!? **변경이 안됐다.**
PATCH
요청)즉, 내가 제목을 변경시켰음에도 변경이 안되있는 것이다.
확인해보니 서버에는 PATCH
요청이 잘갔다. 무엇이 문제였을까???
PATCH
요청을 했지만 상태나 URL이 달라지는 부분이 없기 때문에 서버의 데이터가가 변했다는 것을 인지를 하지 못하고 기존에 캐쉬 된 값을 반환한 것이다.
그렇기 때문에 변경 전 제목인 타이틀 테스트?가 출력된 것이다.
해결방법은 일종의 trigger를 selector내에 두는 것이다.
인위적으로 selector에게 지금 변했으니까 다시 데이터 가져와! 라고 알려주는 것이다.
아래 코드를 보면서 확인해보자
//trigger -> PATCH해주는 부분에서 +1씩 해주자
export const detailIssueTrigger = atom({
key: 'detailIssueTrigger',
default: 0,
});
export const getDetailIssueData = selector({
key: 'GET/DetailIssueData',
get: async ({ get }) => {
//PATCH 해주는 부분에서 +1해주며 변경했다는 것을 알려준다.
get(detailIssueTrigger);
//서버에서 가져온 `이슈상세데이터`
const detailData = await fetchIssueDetail(id);
return detailData;
},
});
const handleSubmit = async () => {
//tatusCode === 200이면 true를 반환한다.
const fetchResult = await fetchEditTitle(issueNumber, editTitle);
//성공시 trigger 작동
if (fetchResult) setDetailIssueTrigger((trigger) => trigger + 1);
};
fetchEditTitle
함수에서 PATCH
가 성공적으로 동작해 200을 반환했다면 trigger
를 작동 시켜서 selector
에게 새로운 요청을 하라고 알려주게된다.
해결완료~!
요청을 캐쉬해 불필요한 요청을 하지 않아도 된다는 점이 정말 큰 장점이지만 그것 때문에 발생하는 문제가 있었다. 해결을 위해서 불필요해 보일 수 있는 코드를 작성해야 됐다.
위의 문제에서도 PATCH
한 결과를 기다리지 않고 trigger를 작동 시켜서 마추진 문제도 있었다.
즉, PATCH
,POST
같은 서버를 변경시키는 작업을 하게 된다면 그 결과가 OK인 경우에만 trigger를 발동시켜서 위와 같은 문제를 해결해야 된다!
리코일을 학습하는 과정에서 작성한 글입니다. 다른 좋은 해결방안 혹은 잘못된 내용이 있다면 댓글로 피드백주시면 감사하겠습니다!
좋은 글 감사합니다!
저도 같은 문제에 직면해있어서 공감되네요 ㅜ
트리거를 사용하게되면 유저 액션에따라서 계속 trigger업데이트를 해주고 함수마다 trigger atom을 만들어줘야해서 너무 낭비같아서 획기적인 방법을 강구중인데 잘 없네요 ㅜㅜ