23/12/4

Laejun Kim·2023년 12월 4일
1

TIL

목록 보기
48/89
post-thumbnail

개인프로젝트

오늘로 개인 프로젝트가 완료되었다. 개인 프로젝트의 종료와 동시에 튜터님의 샘플 코드가 제공된 관계로 "못난 내 코드" 라는 이름으로 본인의 코드의 부족한 점을 파악하고 이를 어떻게 개선할 수 있을지 알아보는 시간을 가지기로 한다.

못난 내 코드 (1/3)

라우터 설정과 분기 처리(react-router-dom)

<내 코드>

const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route element={<Layout />}>
          <Route path="/" element={<Home />} />
          <Route path="detail/:id" element={<Detail />} />
          <Route path="profile" element={<Profile />} />
        </Route>
        <Route path="login" element={<Login />} />
      </Routes>
    </BrowserRouter>
  );
};

export default Router;

<모범 코드> 류제천 튜터님

export default function Router() {
  const isLogin = useSelector((state) => state.auth.isLogin);
  return (
    <BrowserRouter>
      <Routes>
        {isLogin ? (
          <Route element={<Layout />}>
            <Route path="/" element={<Home />} />
            <Route path="/detail/:id" element={<Detail />} />
            <Route path="/profile" element={<Profile />} />
            <Route path="*" element={<Navigate replace to="/" />} />
          </Route>
        ) : (
          <>
            <Route path="/login" element={<Login />} />
            <Route path="*" element={<Navigate replace to="/login" />} />
          </>
        )}
      </Routes>
    </BrowserRouter>
  );
}

무엇이 다른가?

  1. isLogin 상태를 이용한 라우터 분기 처리.

    내 코드에서는 로그인 상태에 따른 라우터의 분기가 아예 이루어지고 있지 않다. 그렇다고 로그인 하지 않은 사용자를 Home이나 Detail 이나 Profile 페이지로 접근시키는 것은 아니고 따로 각 페이지에서 사용자의 accessToken의 유효성을 검사하여 경고 팝업을 띄우고 useNavigate로 Login 페이지로 이동시키는 접근을 취하고 있다.

    이렇게 했을때 문제점은 크게 세가지.
    1) 일단 Home이나 Profile 로 접근하는것 자체는 막을 수 없다는 것.
    2) 그리고 사용자가 뒤로가기를 눌러서 다시 잘못된 접근을 시도할 수 있다는 것.
    3) 각 페이지에서 불필요하게 사용자 accessToken을 검사해야 한다는 것.

    이에 반해 모범 코드에서는 isLogin 상태와 삼항연산자를 이용해 아예 처음부터 분리되어 있는 컴포넌트 트리를 그려내고 있다.

  2. Navigate 컴포넌트 활용과 path="*"

    Navigate 컴포넌트의 활용은 처음 보는 것으로 이번 기회에 반드시 익히고 넘어가야 한다. 기본적으로 const navigate= useNavigate()와 유사한 느낌으로 동작하는데, 컴포넌트가 렌더링 될때 to 에 지정된 주소로 이동시킨다. 모범 코드에서는 로그인 된 상태에서는 Home으로 이동시키고 로그인되지 않은 상태일 경우 Login 페이지로 이동시키고 있다.

    path="*"은 모든 경로를 의미한다. 즉 주소창에 무엇이 입력되었든 무조건 Navigate 컴포넌트가 렌더링 되고 이 Navigate 컴포넌트에 의해 각각 Home 과 Login 으로 이동하게 된다.

  3. replace 사용
    Navigate 가 useNavigate 훅과 비슷한 컴포넌트라는것 까지는 이해했는데 replace가 생소했다. 찾아보니 replace 옵션은 "히스토리 스택에서 현재 페이지를 대체한다" 고 한다. 표현이 좀 복잡한데 아주 간단하게 설명하면 사용자가 뒤로가기로 개발자의 의도에서 벗어난 경로로 이동하는 것을 봉쇄하겠다는 의미이다.
    뒤로가기 버튼을 누르면 이전 히스토리에 남아있는 페이지로 이동하게 되는데 replace 옵션은 이 이전 히스토리를 날려버린다고 생각해도 좋다.

tokenValidation 로직

<내 코드>

//src>utils>tokenValid.js
import { jwtInstance } from "../axios/api";

//accessToken 의 유효성을 검사해서 true/false를 리턴하는 함수
const tokenValid = async (accessToken) => {
try {
  await jwtInstance.get(`/user`, {
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
  });
  return true;
} catch (error) {
  console.error(error);

  return false;
}
};

export default tokenValid;

<모범 코드> 류제천 튜터님

authApi.interceptors.request.use(
  (config) => {
    // 헤더에 토큰 넣기
    const accessToken = localStorage.getItem("accessToken");
    if (accessToken) {
      config.headers["Authorization"] = `Bearer ${accessToken}`;
    }
    return config;
  },
  (err) => {
    return Promise.reject(err);
  }
);

authApi.interceptors.response.use(
  (response) => {
    return response;
  },
  (err) => {
    toast.error(err.response.data.message);
    if (
      err.response.data.message ===
      "토큰이 만료되었습니다. 다시 로그인 해주세요."
    ) {
      // 로그아웃처리
      return store.dispatch(logout());
    }
    return Promise.reject(err);
  }
);

jsonApi.interceptors.request.use(
  async (config) => {
    const { data } = await authApi.get("/user");
    if (data.success) return config;
  },
  (err) => {
    return Promise.reject(err);
  }
);

무엇이 다른가?

  1. interceptor 활용
    나는 인터셉터를 거의 활용하지 못해서 accessToken 검증하는 로직을 함수로 따로 빼고 매번 사용할 때마다 import 해서 사용했다. 그렇지만 모범 코드에서는 interceptor 를 활용하여 api 요청을 할때 자동으로 검증이 이루어지고, 또 그 이후 에러 처리까지 한번에 하는 모습이 보인다.

  2. 특히 jsonApi의 인터셉터 내에서 authApi 를 사용하는 것이 가능한줄 몰랐는데 이번에 알게되었다. 모범 코드에서는 jsonApi에서 요청을 보낼때 authApi.get 으로 유효성 검사를 먼저 하고 이때 오류가 나는 경우에 대해서는 authApi의 인터셉터에서 처리하도록 하고 있다.

0개의 댓글