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개의 댓글

관련 채용 정보