Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

개발일기

231201_TIL : 리덕스 툴킷(Redux-toolkit)으로 상태관리하여 로그인 구현하기 본문

TIL

231201_TIL : 리덕스 툴킷(Redux-toolkit)으로 상태관리하여 로그인 구현하기

화영강 2023. 12. 1. 18:51

기존 최상위 컴포넌트에서 useState로 로그인 상태관리했던 것을 redux-toolkit을 사용하여 구현해보았다.

 

상태관리는 redux, mobX, context api 등 여러 종류가 있는데 나는 이전에는 context api만 사용해보았다.

context api는 <Context.Provider>의 value로 정한 값이 변경되면 해당 컨텍스트를 사용하는 컴포넌트(useContext로 Context를 들고온)들이 같이 렌더링 된다고 한다. 즉, 컨텍스트가 가지는 여러 값 중 하나를 들고 왔을 때 그 값이 변경되지 않더라도 해당 컨텍스트의 값 중 하나만 변경되더라도 그 컨텍스트를 들고온 컴포넌트는 렌더링이 일어난다.

 

이런 단점으로 여러 상태관리 라이브러리를 사용하는데 나는 그 중 redux-toolkit을 사용했다.

 

사용방법

1. redux 세팅

* store.js 파일을 만든다. 이곳에서 상태를 관리한다.

* index.js에서 app컴포넌트를 provider로 감싸준다. 이부분은 context api와 비슷하다.

//✅store.js
import { configureStore } from '@reduxjs/toolkit';

export default configureStore({
	reducer: {}
})


//✅index.js
import { Provider } from "react-redux";
import store from './store.js'

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Provider>
  </React.StrictMode>
);

 

 

2. Redux store에 state 설정

* createSlice로 state 이름과 초기값 그리고 reducers로 변경함수를 설정한다. useState와 유사하다.

설정한 변경함수는 선언한상태명.actions로 export시켜서 외부에서 사용할 수 있도록 한다.

또 이 설정한 state를 밖에서 사용할 수 있도록 configureStore 내의 reducer에 등록한다.

import { configureStore, createSlice } from "@reduxjs/toolkit";

const accessToken = createSlice({
  name: "accessToken", //state 이름
  initialState: localStorage.getItem("accessToken"), //state 최초값

  reducers: {  //변경함수
    AddAccessToken(state) {
      state = localStorage.getItem("accessToken");
      return state;
    },
    RemoveAccessToken(state) {
      localStorage.removeItem("accessToken");
      state = null;
      return null;
    },
  },
});

export const { AddAccessToken, RemoveAccessToken } = accessToken.actions;

export default configureStore({
  reducer: {
    accessToken: accessToken.reducer,
  },
});

 

 

3. state사용 및 변경

(redux사용에 필요한 부분만 들고왔다)

* dispatch는 store로 요청을 보내주는 역할을 한다. 즉 상태변경함수를 사용할 때 사용.

상태변경함수는 store파일에서 함수를 import해와야한다.

dispatch함수 안에 import해온 함수변경함수를 작성하여 함수 변경 요청을 수행한다.

 

* useSelect를 사용하여 state를 들고오는데, 매개변수의 state는 store에서 설정한 초기값이다.

import { useDispatch, useSelector } from "react-redux";
import { RemoveAccessToken } from "../store";

// 로고, 검색창, 로그인, 회원가입
export default function Header() {
  const dispatch = useDispatch();  
  const accessToken = useSelector((state) => state.accessToken);

  useEffect(() => {}, [accessToken]);

  const handleLogout = () => {
    // 로그아웃 클릭 시 accessToken 제거되는 작업 실행
    dispatch(RemoveAccessToken());
    alert("로그아웃 되었습니다.");
  };

  return (
   <>
    {accessToken === null || accessToken === undefined ? (
     <div>
      <Link to="/login" className="headerRight">
       로그인
      </Link>
     </div>
    ) : (
     <div>
      <Link to="/" onClick={handleLogout} className="headerRight">
       로그아웃
      </Link>
     </div>
    )}
   </>
  )
 }

 

 

에러해결

1. 

첫번째 에러는 로그아웃 버튼 클릭 시

a case reducer on a non-draftable value must not return undefined

이런 에러가 떴다.

이것은 리듀서에서 상태를 변경하는데에서 생기는 문제이다. 리듀서 내에서 state를 변경할 때 변경 state를 return을 해줘야 하는데 그냥 냅다 state = null 이렇게만 해줘서 에러가 생겼는데, return을 해주니 해결되었다.

//기존코드
RemoveAccessToken(state) {
  localStorage.removeItem("accessToken");
  state = null; // 이 부분에서 문제 발생
}

//변경코드
RemoveAccessToken(state) {
  localStorage.removeItem("accessToken");
  state = null;
  return state;
}

 

 

2. 

로그인을 하면 바로 홈페이지로 넘어가도록 하면서 header가 조건부 렌더링 되도록 했다. redux에서 accessToken이라는 state를 만들고 로그인 시 로컬스토리지의 엑세스토큰 값을 저장하는 함수를 하면서, 이 엑세스토큰에 값이 있을 경우(로그인됐을 경우) 로그아웃이 렌더링 되도록 설정했다. 그런데 로그인이 되어 엑세스토큰이 저장되었는데, 헤더의 조건부렌더링은 되지 않았고 콘솔로 리덕스에서 가져온 값을 찍어보니 null이 떴다.

 

새로고침시에는 제대로 조건부렌더링 되고, 콘솔 값도 제대로 출력되어 비동기처리에서 잘못된건줄 알았다. 그래서 비동기처리관련하여 수정을 했는데도 안됐었다... 그런데 알고보니 이 상태변경함수에도 문제가 있었다. return을 안해주는... 동일하게 return을 작성해주니 정상출력...ㅎㅎ

    //기존코드
    AddAccessToken(state) {
      state = localStorage.getItem("accessToken");
    },
    
    //변경코드
    AddAccessToken(state) {
      state = localStorage.getItem("accessToken");
      return state;
    },

 

상태변경함수에서 상태를 변경할 때는 새로운 객체상태를 반환해야한다.

 

 

이렇게 하여 리덕스툴킷으로 상태관리하여 로그인을 구현해보았다..!