React

[React] 쿠키(Cookie)를 이용한 애플리케이션 상태 저장

HoneyIT 2025. 3. 13. 21:53
반응형

- SPA(Single Page Application)은 새로고침 시 애플리케이션의 상태가 초기화되기 때문에 LocalStorage나 쿠키(Cookie)를 사용해서 상태 데이터를 보관하고 애플리케이션이 로딩될 때 저장된 정보들을 로딩해서 사용해야합니다.

 

[react-cookie 라이브러리 설치]

npm install react-cookie

 

- 쿠키 사용을 위한 'react-cookie' 라이브러리 설치

 

[Cookie Util 생성]

cookieUtil

import { Cookies } from "react-cookie"

const cookies = new Cookies()

export const setCookie = (name, value, days) => {
    const expires = new Date()
    expires.setUTCDate(expires.getUTCDate() + days) // 보관기간

    return cookies.set(name, value, {path:'/', expires:expires})
}

export const getCookie = (name) => {

    return cookies.get(name)
}

export const removeCookie = (name, path="/") => {

    cookies.remove(name, {path})
}

- 쿠키의 저장/조회/삭제를 위한 함수들을 정의

 

[로그인 결과 쿠키 보관]

import {setCookie} from "../util/cookieUtil";
builder.addCase(loginPostAsync.fulfilled, (state, action) => {
      console.log("fulfilled")

      const payload = action.payload

      // 정상적인 로그인시에만 저장
      if(!payload.error){
          setCookie("member", JSON.stringify(payload), 1) // 1일
      }
      return payload
})

- login을 처리하는 loginSlice.js의 리듀서에 setCookie를 구성

- 로그인 결과는 객체지만 cookie 저장은 문자열만 되기 때문에 JSON.stringfy()를 사용한다는 점을 주의

 

- 브라우저 콘솔 > application > Cookies에서 확인할 수 있음

 

[애플리케이션 로딩 시 쿠키 활용]

import {getCookie, setCookie} from "../util/cookieUtil";
const loginSlice = createSlice({
    name: 'LoginSlice',
    initialState : loadMemberCookie() || initState, // 쿠키가 없으면 초기값 사용
    reducers: {
        login: (state, action) =>{
            console.log("login.....")

            //{email, pw로 구성}
            const data = action.payload

            //새로운 상태
            return {email: data.email}
        },
        logout: (state, action) => {
            console.log("logout.....")
            return {...initState}
        }
    },

- 애플리케이션 실행 시 쿠키가 있는지 체크하고 없으면 초기값을 사용하도록 처리

- 새로고침해도 로그아웃되지 않음

 

[로그아웃 쿠키 처리]

import {getCookie, removeCookie, setCookie} from "../util/cookieUtil";
logout: (state, action) => {

       removeCookie("member")

       return {...initState}
 }

- 로그아웃 처리 시 removeCookie를 사용해 'member' 쿠키 삭제

- 쿠키 삭제는 생성과 달리 바로 삭제되지 않으니 새로고침 또는 다른 메뉴 이벤트 발생 후 확인 가능

 

[Axios 인터셉터와 Refresh Token]

- 로그인 후 쿠키를 생성하더라도 API 호출 시 JWT 방식으로 Access Token 때문에 오류가 발생

- Axios 호출 시 Access Token 전달과정 필요 또한 Access Token 만료 시 Refrsh Token으로 Access Token 갱신 처리 필요

 

jwtUtil

import axios from "axios";

const jwtAxios = axios.create()

// before request
const beforeReq = (config) => {
    console.log("before request..........")

    return config
}

// fail request
const requestFail = (err) => {
    console.log("request error............")

    return Promise.reject(err)
}

// before return response
const beforeRes = async (res) => {
    console.log("before return response.......")

    return res
}

// fail response
const responseFail = (err) => {
    console.log("response fail error..........")

    return Promise.reject(err)
}

jwtAxios.interceptors.request.use(beforeReq, requestFail)

jwtAxios.interceptors.response.use(beforeRes, responseFail)

export default jwtAxios

- jwtUtil.js 파일을 추가하고 Axios의 요청/응답 시에 동작할 함수를 정의

- 요청(beforeReq, requestFail), 응답(beforeRes, responseFail)

 

import jwtAxiosxios from "../util/jwtUtil";
const res = await jwtAxios.post(`${host}/login`, form, header)

 

- 기존에 사용하던 axios 부분을 위에서 정의한 jwtAxios로 변경

 

[Access Token 전달]

const beforeReq = (config) => {
    console.log("before request..........")
    const memberInfo = getCookie("member")

    if(!memberInfo){
        console.log("Member Not Found")
        return Promise.reject(
            {response:
                    {data:
                        {error:"REQUIRE_LOGIN"}
                    }
            }
        )
    }

    const {accessToken} = memberInfo

    //Authorization 헤더 처리
    config.headers.Authorization = `Bearer ${accessToken}`

    return config
}

- API 서버 호출 전에 Authorization 헤더를 추가

- 로그인 쿠키가 없는 경우 예외 처리

- 로그인 후 다른 메뉴도 접속 가능 확인

 

[오류발생]

- properties undefined 오류 발생

- jwtUtil에서 beforeReq를 실행하는 과정에서 'member' 쿠키가 없어서 발생하는 것으로 보임

- memberApi의 axios까지 jwtUtil을 거치도록 변경해서 발생한 문제(멍청한 실수;;)

반응형

'React' 카테고리의 다른 글

[React] 소셜 로그인 (1)  (0) 2025.03.19