📜 서론
이전에 업로드한 포스팅을 보면 알겠지만, 앞선 과정들을 통해 카카오 로그인 서비스를 원활하게 사용할 수 있게 되었다. 이제 카카오 서버로부터 사용자의 카카오톡 프로필 사진과 닉네임 가져와 사이트 프로필에 박아야 한다. 한마디로 전역적으로 관리해야하는 정보다. redux-toolkit
을 사용할 때가 온 것이다. 오늘 포스팅에서는 이걸 구현하면서 어떤 방법을 사용했고, 어떤 이슈를 겪었는 지에 대한 이야기를 하고자 한다.
⚙️ 사용자 정보 가져와서 리덕스로 관리하기
📌 새로고침 되어도 회원 정보 유지시키기
redux-toolkit
(약칭 RTK)으로 상태를 관리하는 방법은 매우 쉽다. RTK를 어떻게 사용하는 지에 대한 자료들은 넷상에 널려있기 때문에 여기서 그에 대한 이야기는 생략하도록 하겠다. 문제는 새로고침이다. 새로고침을 하면 redux에 저장된 정보들도 초기화되어서 로그인 시 가져온 회원 정보들이 날아간다.
페이지가 새로고침 될 때마다 서버에 회원 정보를 가져오라고 요청하면 쓸데없이 트래픽이 증가하기 때문에 클라이언트에서 해당 정보들이 날아가지 않게 조치를 취해야 한다. 이를 방지하기 위한 가장 쉬운 방법은 localStorage에 정보들을 저장하고, 필요할 때마다 꺼내 쓰면 된다. 카카오 서버로부터 가져온 사용자 정보들도 보안상 치명적인 정보들이 아니기 때문에(사용자 닉네임, 사용자 프로필 사진 주소) localStorage를 사용해도 큰 문제가 없을 것이다. 이제 localStorage 관련 메서드들을 활용하면 앞서 말한 것을 구현할 수 있지만, redux-persist
라이브러리를 사용해 좀 더 깔끔하게 구현할 수 있는 방법을 찾아냈다.
📌 A non-serializable value was detected in an action
이슈
적용하던 도중 이런 에러를 마주했다.
개발자 도구를 열어 localStorage를 확인해보니 _persist
란 필드가 들어있었다.
알아보니 해당 필드는 redux-persist
에서 내부적으로 관리하는 메타데이터였다. 어쨌든 redux-persist
의 깃허브 레포지토리에 해당 이슈가 있는지 찾아보았고, 여기서 redux-toolkit
공식 문서에서 관련 이슈에 대해 안내하는 내용이 있다는 것을 발견했다. 그렇다. 위 에러 사진에 나와있는 링크였다...
Usage Guide | Redux Toolkit
redux-toolkit.js.org
어쨌든 공식 문서의 말에 따르면, 상태 관리의 예측 가능성을 위한 Redux의 핵심 사용 원칙 중 하나는 상태나 액션에 직렬화할 수 없는 값을 넣지 않는 것이라고 한다. 하지만 지금처럼 직렬화할 수 없는 데이터를 받아들여야 하는 액션을 처리해야 하는 경우는 예외에 해당한다. 대신 해당 데이터는 액션을 통해 전달될 수는 있어도 리듀서를 통해 상태에 저장되어서는 안된다. 이 때문에 redux-toolkit
에는 serializableCheck
라는 미들웨어가 작동하는 것이고, 바로 이 미들웨어 때문에 위의 에러가 발생하는 것이다.
친절하게도 공식 문서에서는 redux-persist
라이브러리 사용 시 이 에러를 만났을 때 대처 방법도 알려주고 있었다. 다음과 같은 미들웨어 설정을 통해 redux-persist
가 디스패치하는 모든 액션 타입들을 serializableCheck
에서 무시하도록 하는 것이다.
Usage Guide | Redux Toolkit
redux-toolkit.js.org
import { configureStore } from "@reduxjs/toolkit";
import { persistStore, persistReducer } from "redux-persist";
import storage from "redux-persist/lib/storage";
import userInfoReducer from "@/state/store/userInfoSlice";
import {
FLUSH,
REHYDRATE,
PAUSE,
PERSIST,
PURGE,
REGISTER,
} from "redux-persist";
import reviewDetailOpenSlice from "@/state/store/reviewDetailOpenSlice";
// persist 설정
const persistConfig = {
key: "root",
storage, // 브라우저 로컬스토리지 사용
};
const persistedReducer = persistReducer(persistConfig, userInfoReducer);
const store = configureStore({
reducer: {
userInfo: persistedReducer,
reviewDetailOpen: reviewDetailOpenSlice,
},
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: {
ignoredActions: [FLUSH, REHYDRATE, PAUSE, PERSIST, PURGE, REGISTER],
},
}),
devTools: process.env.NODE_ENV !== "production",
});
export default store;
export const persistor = persistStore(store);
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
위처럼 설정하니 에러가 사라졌다.
👋 로그아웃
이제 마지막으로 로그아웃을 구현할 차례다. 간단하게 쿠키에서 토큰들과 localStorage에 남아있는 redux-persist
가 관리하는 데이터들을 싹 지우고 유저를 홈 화면으로 이동시키면 된다. 여기서 redux-persist
가 관리하는 데이터를 쉽게 지우는 방법도 앞서 언급한 공식문서에서 설명하고 있는 것을 발견해 적용해보기로 했다.
📌 로그아웃 api로 쿠키 삭제
// ... 이전 코드
res.clearCookie("accessToken");
res.clearCookie("refreshToken");
위와 같이 로그아웃 api 요청 시 express.js
의 clearCookie
메서드로 쿠키를 사용해 쿠키를 지울 수 있도록 한다.
📌 redux-persist
가 관리하는 데이터들 지우기
아까 redux-persist
설정 코드의 마지막에서 persistor
란 객체를 export한 것을 볼 수 있을 것이다. 여기 내장된 purge
메서드를 사용하면 redux-persist
가 관리하는 데이터들이 모두 초기화 된다. 이것까지 담으면 로그아웃 버튼을 눌렀을 때 실행할 함수가 다음과 같이 완성된다.
const handleLogOut = async () => {
await logOutKakao();
await persistor.purge(); // 로그아웃 시 redux-persist가 관리하는 모든 상태 초기화
window.location.href = "/";
};
🏁 마무리
이렇게 약 일주일 정도 걸렸던 카카오 로그인 관련 작업들에 대한 설명이 모두 끝났다. 물론 회원 가입 및 탈퇴 과정도 구현해야 하지만, 그건 다른 기본적인 기능들을 모두 완성시키고 구현하기로 했다. 내 글이 카카오 로그인을 도입하는 사람들에게 조금이나마 도움이 됐으면 좋겠다.
'프로젝트 > Re|view' 카테고리의 다른 글
[Re|view] 8. 무한 스크롤 적용기 (0) | 2025.01.30 |
---|---|
[Re|view] 7. FSD 구조 적용 실패기 (0) | 2025.01.28 |
[Re|view] 5. 카카오 로그인 적용기 - Axios 인터셉터로 토큰 자동 갱신 구현하기 (0) | 2024.09.03 |
[Re|view] 4. 카카오 로그인 적용기 - 쿠키에 토큰 저장하기 (5) | 2024.09.03 |
[Re|view] 3. 깃허브 unverified 이슈 해결 과정 (0) | 2024.05.10 |