2021-01-18 TIL

오늘은 React Router와 Webpack 설정으로 삽질을 했습니다.

기존 routing 설정은 아래와 같았습니다.

function Routes(): ReactElement {
  ...

  return (
    <BrowserRouter>
      <Switch>
        <Route exact path="/login" component={Pages.LoginPage} />
        <Route exact path="/admin-user-add" component={Pages.AdminUserAddPage} /> 
        <Route exact path="/admin-report" component={Pages.AdminReport} />
        <Route exact path="/report" component={Pages.ReportPage} />
        <Route component={Pages.PageNotFound} />
      </Switch>
    </BrowserRouter>
  );
}

admin 관련 페이지가 점점 늘어날 것이 예상되어서 admin 관련 routing을 별도로 분리하고 싶었습니다.

그리고 url도 /admin/user-add, admin/report와 같이 수정하기 위해 다음과 같이 코드를 작성했습니다.

function Routes(): ReactElement {
  ...

  return (
    <BrowserRouter>
      <HelmetComponent />
      <ToastContainer />
      <Switch>
        <Route exact path="/login" component={Pages.LoginPage} />
        <Route path="/admin">
          <AdminRoute />
        </Route>
        <Route exact path="/report" component={Pages.ReportPage} />
        <Route component={Pages.PageNotFound} />
      </Switch>
    </BrowserRouter>
  );
}
export function AdminRoute(): ReactElement {
  const { url } = useRouteMatch();

  return (
    <Switch>
      <Route path={`${url}/user-add`}>
        <Pages.AdminUserAddPage />
      </Route>
      <Route path={`${url}/report`}>
        <Pages.AdminReport/>
      </Route>
    </Switch>
  );
}

코드에는 아무런 이상이 없어보이는데 webpack-dev-server로 로컬에서 실행하면 계속 에러가 발생했습니다.

http://localhost:3000/admin/user-add로 접속하면 브라우저 콘솔에 다음과 같은 에러 메시지가 출력되었습니다.

GET http://localhost:3000/admin/app.js net::ERR_ABORTED 404 (Not Found)

이 문제의 해결 방안은 다음과 같이 Webpack 설정을 추가하여 처리했습니다.

module.exports = env => {
  return {
    entry: {
      app: path.join(__dirname, 'src', 'index.tsx'),
    },
    resolve: {
      extensions: ['.ts', '.tsx', '.js'],
    },
    output: {
      filename: '[name].js',
      publicPath: '/',
      path: path.resolve(__dirname, 'dist'),
    },

    ...

    devServer: {
      port: 3000,
      historyApiFallback: true,
      index: 'index.html',
      host: '0.0.0.0',
      overlay: true,
      disableHostCheck: true,
    },
  };
};

기존에는 output의 publicPath가 설정되어 있지 않았습니다. publicPath/로 설정하면 /admin/user-add 같은 경로가 정상적으로 동작합니다.

publicPath 설정 없이 Webpack을 사용하면 index.html에 다음과 같은 구문이 추가됩니다.

<script type="text/javascript" src="bundle.js"></script>

bundle.js는 보통 Webpack이 js 파일들을 컴파일하여 생성한 파일로 index.html과 같은 경로에 위치한다는 것을 의미합니다.

이 경우 /admin-user-add와 같은 url은 올비른 경로의 bundle.js를 참조하지만, /admin/user-add/admin/ 경로의 bundle.js를 참조하려고 합니다. 그래서 에러가 발생합니다.

그래서 Webpack에 publicPath를 지정하여 항상 /bundle.js를 참조하도록 설정합니다.

publicPath/로 설정하고 Webpack을 실행하면 index.html에 추가되는 구문이 다음과 같이 수정됩니다.

<script type="text/javascript" src="/bundle.js"></script>

참고:

https://stackoverflow.com/questions/56573363/react-router-v4-nested-routes-not-work-with-webpack-dev-server


Written by@[Suho]
뭐든지 만들어보자.