Skip to content

Latest commit

Β 

History

History
174 lines (132 loc) Β· 4.56 KB

File metadata and controls

174 lines (132 loc) Β· 4.56 KB

● ν”„λ‘ νŠΈμ—”λ“œ μˆ˜μ • 사항 πŸ“±

  1. 둜그인 응닡 ꡬ쑰 λ³€κ²½ ⭐ ν•„μˆ˜

이전: { "userId": 12345, "jwtToken": "eyJhbG...", "isNewUser": false, "isOnboardingCompleted": true }

λ³€κ²½ ν›„: { "userId": 12345, "accessToken": "eyJhbG...", "refreshToken": "eyJhbG...", "isNewUser": false, "isOnboardingCompleted": true }

μˆ˜μ • ν•„μš”:

  • jwtToken β†’ accessToken + refreshToken 으둜 λ³€κ²½
  • 둜컬 μŠ€ν† λ¦¬μ§€/AsyncStorage에 두 개의 토큰 λͺ¨λ‘ μ €μž₯

// Before localStorage.setItem('token', response.jwtToken);

// After localStorage.setItem('accessToken', response.accessToken); localStorage.setItem('refreshToken', response.refreshToken);


  1. 토큰 μž¬λ°œκΈ‰ 둜직 μΆ”κ°€ ⭐ ν•„μˆ˜

μƒˆλ‘œμš΄ μ—”λ“œν¬μΈνŠΈ: POST /v1/auth/refresh

Request: { "refreshToken": "eyJhbG..." }

Response: { "accessToken": "eyJhbG...", // 항상 μƒˆλ‘œ λ°œκΈ‰ "refreshToken": "eyJhbG..." // 7일 μ΄ν•˜ λ‚¨μœΌλ©΄ μƒˆλ‘œ λ°œκΈ‰, μ•„λ‹ˆλ©΄ null }

κ΅¬ν˜„ 방법 (Axios 인터셉터 μ˜ˆμ‹œ): // API 인터셉터 μ„€μ • axios.interceptors.response.use( response => response, async error => { const originalRequest = error.config;

  // 401 μ—λŸ¬μ΄κ³ , μž¬μ‹œλ„κ°€ μ•„λ‹Œ 경우
  if (error.response?.status === 401 && !originalRequest._retry) {
    originalRequest._retry = true;

    try {
      const refreshToken = localStorage.getItem('refreshToken');

      // λ¦¬ν”„λ ˆμ‹œ ν† ν°μœΌλ‘œ μƒˆ μ•‘μ„ΈμŠ€ 토큰 λ°œκΈ‰
      const response = await axios.post('/v1/auth/refresh', {
        refreshToken
      });

      const { accessToken, refreshToken: newRefreshToken } = response.data.data;

      // μƒˆ μ•‘μ„ΈμŠ€ 토큰 μ €μž₯
      localStorage.setItem('accessToken', accessToken);

      // λ¦¬ν”„λ ˆμ‹œ 토큰도 κ°±μ‹ λ˜μ—ˆμœΌλ©΄ μ €μž₯
      if (newRefreshToken) {
        localStorage.setItem('refreshToken', newRefreshToken);
      }

      // μ›λž˜ μš”μ²­ μž¬μ‹œλ„
      originalRequest.headers.Authorization = `Bearer ${accessToken}`;
      return axios(originalRequest);

    } catch (refreshError) {
      // λ¦¬ν”„λ ˆμ‹œ μ‹€νŒ¨ β†’ 둜그인 νŽ˜μ΄μ§€λ‘œ
      localStorage.removeItem('accessToken');
      localStorage.removeItem('refreshToken');
      window.location.href = '/login';
      return Promise.reject(refreshError);
    }
  }

  return Promise.reject(error);
}

);


  1. λ‘œκ·Έμ•„μ›ƒ 둜직 μΆ”κ°€ ⭐ ν•„μˆ˜

μƒˆλ‘œμš΄ μ—”λ“œν¬μΈνŠΈ: POST /v1/auth/logout (인증 ν•„μš”)

Request: μ—†μŒ (Authorization ν—€λ”λ§Œ ν•„μš”)

κ΅¬ν˜„: const logout = async () => { try { const accessToken = localStorage.getItem('accessToken');

  // μ„œλ²„μ— λ‘œκ·Έμ•„μ›ƒ μš”μ²­
  await axios.post('/v1/auth/logout', {}, {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  });

} catch (error) {
  console.error('λ‘œκ·Έμ•„μ›ƒ μ‹€νŒ¨:', error);
} finally {
  // 둜컬 토큰 μ‚­μ œ (μ„œλ²„ μš”μ²­ μ‹€νŒ¨ν•΄λ„ μ‚­μ œ)
  localStorage.removeItem('accessToken');
  localStorage.removeItem('refreshToken');

  // 둜그인 νŽ˜μ΄μ§€λ‘œ 이동
  window.location.href = '/login';
}

};


  1. API μš”μ²­ μ‹œ 헀더 λ³€κ²½

λ³€κ²½ μ „: headers: { Authorization: Bearer ${localStorage.getItem('token')} }

λ³€κ²½ ν›„: headers: { Authorization: Bearer ${localStorage.getItem('accessToken')} }


μˆ˜μ • μš°μ„ μˆœμœ„

πŸ”΄ ν•„μˆ˜ (λ‹Ήμž₯ μˆ˜μ • ν•„μš”)

  1. βœ… 둜그인 μ‘λ‹΅μ—μ„œ jwtToken β†’ accessToken, refreshToken 뢄리
  2. βœ… 두 토큰 λͺ¨λ‘ μ €μž₯ν•˜λ„λ‘ μˆ˜μ •
  3. βœ… API μš”μ²­ μ‹œ accessToken μ‚¬μš©

🟑 μ€‘μš” (λΉ λ₯΄κ²Œ μΆ”κ°€ ꢌμž₯)

  1. βœ… 토큰 μž¬λ°œκΈ‰ 인터셉터 κ΅¬ν˜„
  2. βœ… λ‘œκ·Έμ•„μ›ƒ API 호좜

🟒 선택 (μΆ”ν›„ κ°œμ„ )

  1. 토큰 만료 μ‹œκ°„ 체크 ν›„ 사전 κ°±μ‹  (UX κ°œμ„ )
  2. λ¦¬ν”„λ ˆμ‹œ 토큰도 만료되면 "μ„Έμ…˜ 만료" λ©”μ‹œμ§€ ν‘œμ‹œ

React Native μ˜ˆμ‹œ (AsyncStorage)

import AsyncStorage from '@react-native-async-storage/async-storage';

// 둜그인 const handleLogin = async (response) => { await AsyncStorage.setItem('accessToken', response.accessToken); await AsyncStorage.setItem('refreshToken', response.refreshToken); };

// API 호좜 const accessToken = await AsyncStorage.getItem('accessToken'); axios.defaults.headers.common['Authorization'] = Bearer ${accessToken};

// λ‘œκ·Έμ•„μ›ƒ await AsyncStorage.multiRemove(['accessToken', 'refreshToken']);