리코일 난 너가 만능인줄 알았어... selector 활용한 GET 요청

Kyle·2021년 7월 4일
2
post-thumbnail

리코일 셀렉터 편하긴한데...

지난번 포스팅 Recoil selector를 사용한 비동기 처리에서 리코일을 사용한 서버요청하는 작업을 소개했다.

이번에 이슈트래커라는 새로운 프로젝트를 진행하며 상태관리에서 recoil을 한번 더 사용해봤다. 그 과정에서 예상치 못한 문제가 발생했다.

지난번 글에서 말했던 서버요청시 캐쉬를 하는 기능 때문에 발생한 문제였다. 어떤 문제가 발생했고 이를 어떻게 해결했는지를 공유하기 위해 이번 포스팅을 준비했다.

셀렉터에서 서버요청 시 큰 장점의 역습

selector에서 서버에 GET요청을 할 때 큰 장점 중 하나는 캐쉬를 한다는 것이다. 지난번 포스팅에서도 다룬 내용인데 사용하는 atom(상태)값, URL을 비교해서 동일하다면 서버로 요청을 다시 보내는 것이 아닌 캐쉬된 값을 사용한다.

이 부분에서 문제가 발생했다.

문제상황

아래 상황의 순서는 이렇다.

1. 이슈의 제목을 변경한다. (`PATCH` 요청)
2. 메인화면인 이슈리스트로 나간다.
3. 다시 이슈 상세페이지로 들어간다.
4. 이슈 제목이..!? **변경이 안됐다.**
  1. 이슈의 제목을 변경한다. (PATCH 요청)
  2. 제목이 변경됐다.
  3. 메인화면인 이슈리스트로 나간다. & 다시 이슈 상세페이지로 들어간다.
  4. 이슈 제목 변경이 안됐다.

즉, 내가 제목을 변경시켰음에도 변경이 안되있는 것이다.

무엇이 문제일까???

확인해보니 서버에는 PATCH 요청이 잘갔다. 무엇이 문제였을까???

PATCH 요청을 했지만 상태나 URL이 달라지는 부분이 없기 때문에 서버의 데이터가가 변했다는 것을 인지를 하지 못하고 기존에 캐쉬 된 값을 반환한 것이다.

그렇기 때문에 변경 전 제목인 타이틀 테스트?가 출력된 것이다.

해결방법

해결방법은 일종의 trigger를 selector내에 두는 것이다.

인위적으로 selector에게 지금 변했으니까 다시 데이터 가져와! 라고 알려주는 것이다.

아래 코드를 보면서 확인해보자

trigger를 적용한 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를 발동시켜서 위와 같은 문제를 해결해야 된다!

리코일을 학습하는 과정에서 작성한 글입니다. 다른 좋은 해결방안 혹은 잘못된 내용이 있다면 댓글로 피드백주시면 감사하겠습니다!

profile
Kyle 발전기

2개의 댓글

comment-user-thumbnail
2021년 8월 4일

좋은 글 감사합니다!
저도 같은 문제에 직면해있어서 공감되네요 ㅜ
트리거를 사용하게되면 유저 액션에따라서 계속 trigger업데이트를 해주고 함수마다 trigger atom을 만들어줘야해서 너무 낭비같아서 획기적인 방법을 강구중인데 잘 없네요 ㅜㅜ

답글 달기