개발자

React/Redux 프로젝트에서 만료된 토큰 사용시 로그인 페이지로 이동하는 방법이 궁금합니다

2023년 04월 25일조회 361

React와 Redux Toolkit을 사용하는 프로젝트에서 토큰 만료 시 로그인 페이지로 이동하는 로직을 구현하려고 하는데, 이에 대한 참고 자료나 코드가 있을까요? 프로젝트에서는 각각의 비동기 요청에서 토큰을 보내고 있는데, 만료된 토큰일 경우에만 로그인 페이지로 이동하는 공통 에러 처리를 어떻게 구현해야 할지 고민 중입니다. 이에 대한 해결책이 있을까요?

이 질문이 도움이 되었나요?
'추천해요' 버튼을 누르면 좋은 질문이 더 많은 사람에게 노출될 수 있어요. '보충이 필요해요' 버튼을 누르면 질문자에게 질문 내용 보충을 요청하는 알림이 가요.
profile picture
익명님의 질문

답변 3

김인후님의 프로필 사진

안녕하세요 저 같은 경우는 먼저 accesstoken 만료시 인터셉터 등을 통하여 재발급 받는 로직을 실행 후 다시 본래 로직을 타는 경우가 많으며 각 페이지의 로그인 인증은 context와 router를 이용합니다. 로그인이 필요한 라우터 없는 라우터를 상위에 감싸는 식으로요.

종현님의 프로필 사진

안녕하세요! 혹시 요청을 하실때 fetch를 사용하시는지 axios를 사용해서 요청을 하시는지 알 수 있을까요?? 그럼 직접적인 예시를 들어 드리는데 도움이 될 수 있을 것 같아요!

커리어리 AI 봇님의 프로필 사진

토큰 만료 시 로그인 페이지로 이동하는 공통 에러 처리를 구현하기 위해, 주로 인터셉터나 미들웨어를 사용하여 API 요청을 처리합니다. axios를 사용하는 경우 인터셉터를 활용할 수 있고, Redux에서는 미들웨어를 사용할 수 있습니다. 예를 들어, axios를 사용한다면 다음과 같은 방식으로 인터셉터를 설정할 수 있습니다. 1. axios 인스턴스 생성: 2. 응답 인터셉터 설정: 3. API 요청 시 해당 인스턴스 사용: 만약 Redux Toolkit을 사용하고 있다면, ' createAsyncThunk '의 두 번째 인자로 전달되는 ' thunkAPI '를 사용하여 에러 처리를 수행할 수 있습니다. #3-1 예시 ) 아래 예제에서는 ' createAsyncThunk '를 사용하여 토큰 만료 여부를 확인하고, 로그인 페이지로 이동하는 로직을 구현했습니다. 이 방법을 사용하면 각 비동기 액션에서 공통된 에러 처리를 적용할 수 있습니다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#1
import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://your-api-domain.com',
  headers: {
    'Content-Type': 'application/json',
  },
});

#2
import { useHistory } from 'react-router-dom';

apiClient.interceptors.response.use(
  (response) => response,
  (error) => {
    // 토큰 만료 시 에러 메시지 확인
    if (error.response.status === 401 && error.response.data.message === 'Token expired') {
      // 로그인 페이지로 이동
      useHistory().push('/login');
    }

    return Promise.reject(error);
  }
);

#3
export const fetchSomeData = async () => {
  const response = await apiClient.get('/some-data');
  return response.data;
};


#3-1
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { fetchSomeData } from '../api';

export const fetchData = createAsyncThunk('data/fetchData', async (_, thunkAPI) => {
  try {
    const data = await fetchSomeData();
    return data;
  } catch (error) {
    // 토큰 만료 시 에러 메시지 확인
    if (error.response.status === 401 && error.response.data.message === 'Token expired') {
      // 로그인 페이지로 이동
      thunkAPI.dispatch(push('/login'));
    }
    return thunkAPI.rejectWithValue(error.response.data);
  }
});

const dataSlice = createSlice({
  name: 'data',
  initialState: [],
  reducers: {},
  extraReducers: (builder) => {
    builder.addCase(fetchData.fulfilled, (state, action) => {
      return action.payload;
    });
  },
});

export default dataSlice.reducer;

커리어리 AI 봇의 답변을 평가해 주세요!

지금 가입하면 모든 질문의 답변을 볼 수 있어요!

현직자들의 명쾌한 답변을 얻을 수 있어요.

또는

이미 회원이신가요?

목록으로
키워드로 질문 모아보기

실무, 커리어 고민이 있다면

새로운 질문 올리기

지금 가입하면 모든 질문의 답변을 볼 수 있어요!