오늘은 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>
참고: