본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


앵귤러, 리엑트, 뷰/리엑트(React.js)

리코일 set, get 그리고 async(recoil get set async)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2023. 3. 6.

리코일에서 제공하는 함수 중 셀렉터(selector)가 있습니다.

요녀석은 리코일의 set, get 기능을 편리하게 사용 할 수 있게 해주는 기능 입니다.
또한 다양한 리코일의 상태(atom)을 키 값을 통해서 반환 하기도 합니다.

 

이번에 만난 이슈는 리코일의 셀렉터(selector)를 활용 할 때의 동기화 이슈 였습니다.

아래와 같이 세션 스토리지에 간단하게 사용자 정보를 저장하는 기능을 구현 하였습니다.

import { atom, selector,  } from "recoil";
import { recoilPersist } from 'recoil-persist'; //yarn add recoil-persist

//리코일 상태값을 "sessionStorage" 에서 적용하게 합니다.
const { persistAtom } = recoilPersist({
    key: "user",
    storage: sessionStorage,
});

/**
 * 데이터베이스 객체 입니다.
 */
const DB = {
  id: "admin",
  pwd: "test",    
}

/**
 * 사용자 정보를 가지고 있는 상태(atom) 입니다.
 */
const 로그인정보 = atom({
  key: "로그인정보",
  default : {
    id : null  //로그인여부를 확인 할 대표변수 값 입니다.
  },
  effects: [persistAtom]  //해당 상태 값은 로컬세션(window.sessionStorage)을 사용 합니다.
});

/**
 * 사용자의 상태값을 확인하는 셀렉터 입니다.
 */
export const 세션셀렉터 = selector({
  key: "SessionInfo",
  get: ({ get }) => {  //get을 통해 전달
    return get(로그인정보);
  },
  set: ({ set }, newValue) => {  //set을 통해 상태값을 갱신(로그인, 로그아웃)
    const {id :_id , pwd : _pwd} = DB;
    let {id, pwd} = newValue;
    if(_id === id && _pwd === pwd){  //로그인인 경우에 상태값의 id를 변경 합니다.
        set(로그인정보, {id});    
    } else {
        set(로그인정보, {id : null}); //로그아웃인 경우에 상태값에서 id를 제거 합니다.
    }
  }
});

 

별로 어렵지 않는 기능 입니다.

사용자 로그인 정보를 단순하게 Javascript의 DB라는 객체로 관리 하였고(로그인 서버와 연동하기 싫어..서...) 데이터베이스에 정보를 요청하는 것이 아니므로 set 요청에 대해서 바로 반응할 줄 알았습니다.

이를 사용한 로그인 컴포넌트 샘플 모습 입니다.

function LogIn() {
  
  let navigate = useNavigate();  //라우터
  let [info, setInfo] = useRecoilState(세션샐렉터); //로그인 세션 상태를 가져 옵니다.

  /**
   * 로그인 버튼 기능 샘플
   */
  const tryToLogIn = (param) => {
    setInfo(param);
    if (info != null) {  //요기!! 요기!!!
      navigate("/관리페이지로이동");
    } else {
      alert("입력하신 정보에 맞는 사용자가 없습니다.");
    }
  };
  

  //생략..
}

 

위 코드의 tryToLogIn 함수는 로그인 버튼을 누르면 동작하는 함수 입니다.

그래서 setInfo를 통해서 데이터가 갱신되면 info 객체에 바로 반영할줄 알았지만 바로 반영이 되지 않았습니다.

거참 이상해서...설마 이벤트큐에 해당 set 행위가 들어가나 싶어서 아래처럼 setTimeout을 줘 봤더니..

  const tryToLogIn = (param) => {
    setInfo(param);  //set 이벤트를 발생시킨뒤에..
    setTimeout(() => {  //이벤트큐에 다음 행위를 담아 보았습니다.
      if (info != null) {
        navigate("/관리페이지로이동");
      } else {
        alert("입력하신 정보에 맞는 사용자가 없습니다.");
      }
    }, 0);
  };

 

이벤트큐에 info값을 나중에 가져오는 걸로 바꾸었더니 정상적으로 로그인 행위가 동작하는 것 이였습니다!

아니 이거 뭐 http 요청을 한 것도 아닌데  async를 줘야하는 상황이 무척이나 당황스러웠습니다.

물론 사용자 로그인 정보는 웹서버에서 가져오는게 맞습니다만..

덕분에 리코일(recoil)에서 set과 get 이벤트를 동기화 하기 위해서는 이벤트큐와 async 부분을 고려해야 된다는 점에 대해서 알 수 있었습니다.

 

간단하게 끄적여본 리코일 set, get 그리고  async(recoil get set async)에 대한 내용이였습니다.

 * 역시..이래서 사람은 처음부터 책이나 공식 doc로 내용을 공부하는게 맞나봅니다..ㅠ

틀린부분에 대한 말씀이나 다른 의견은 언제든 환영입니다! 👻

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글