딱히 React만의 문제는 아니다. SPA면 다 발생하는 일이다. 하지만 필자가 React를 주로 쓰는 관계로 React 항목에 넣어뒀다.
새로고침, 외부 링크를 타고 갔다가 다시 돌아오는 뒤로가기 등등 에서 경로를 찾지 못하는 경우가 많다.
이러한 오류가 발생하는 이유를 connect-history-api-fallback 깃허브 페이지에서 인용하자면,
SPA (Single Page Applications)는 일반적으로 웹 브라우저에서 액세스 할 수있는 하나의 색인 파일(index.html)만 사용합니다. 그런 다음 HTML5 히스토리 API를 사용하여 JavaScript를 사용하여 애플리케이션의 탐색을 일반적으로 처리 합니다.
이로 인해 사용자가 새로 고침 버튼을 누르거나 방문 페이지 이외의 페이지에 직접 액세스 /help하거나 /help/online 웹 서버가 색인 파일을 무시하여이 위치에서 파일을 찾을 때 문제가 발생합니다. 응용 프로그램이 SPA이므로 웹 서버는 파일을 검색하지 못하고 404- 찾을 수 없음 메시지를 사용자에게 반환합니다.
위 issues에서는 다음과 같이 해결하라고 알려주고 있다.
https://github.com/ReactTraining/react-router/issues/5065
CRA 홈페이지는 아예 어떻게 해결하는지도 다뤄줬다!
https://create-react-app.dev/docs/deployment/#serving-apps-with-client-side-routing
그러나 가장 잘 정리하고, express에서도 세부 도메인까지 접근가능하게 만들어주는 방법은 Vue에 설명되어 있었다.
https://router.vuejs.org/guide/essentials/history-mode.html#example-server-configurations
그렇다면 구체적으로 어떻게 해야 하는지를 정리해보자.
필자는 apache, Nginx, express를 쓰므로 세 개를 정리해볼까 한다.
혹시 글을 보시는 분이 S3(+cloudfront)로 React 정적 웹을 배포하고자 하시는 분은 아래 게시물을 참고하시면 됩니다.
에러 폴백을 index.html으로 보내야 하는 게 포인트입니다.
darrengwon.tistory.com/810?category=858367
Apache -> mod_rewrite
Nginx -> nginx.conf에 location / 블락 추가 및 설정
Webpack Dev Server -> historyApiFallback (https://www.youtube.com/watch?v=EDJW88iVORA)
Express/Koa/Hapi/etc. -> a wildcard route to your index.html
express에서의 해결 방법
경로는 알아서 빌드된 곳으로 연결시켜주면 됩니다.
// will serve index.html for every page refresh.
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "/client/build/index.html"));
});
물론 이렇게 했을 경우, 다른 경로로 접근했을 때 강제로 처음 화면으로 이동하게 될 것입니다.
또, 위 코드는 route의 맨 아래에 위치해야 합니다. 최상단이면 다른 백단의 라우팅들을 모두 먹어버립니다.
🚨 주의 : react-router-dom에서 global하게 redirect시키는 부분이 있다면 (아래와 같이 쓴 rediect가 있다면) 당장 지워버리십쇼. 리버스 프록시를 쓰던 무슨 짓을 하던 다음 코드가 있으면 무조건 홈으로 리다이렉트 시킵니다
<Redirect from="*" to="/" />
리다이렉트가 필요하면 Guard를 하나 만드세요.
const GuestGuard = ({ path, children }) => {
// ... 인증 관련 로직
if (isUserAuthenticated) return <Redirect to={redirectRoute} />
return <Route path={path}>{children}</Route>
}
404 페이지를 띄우고 싶으면 다음과 같이 Switch 최 하단에 없는 페이지를 처리하도록 만듭시다.
<Swtich>
<Route render={() => <div>없는 페이지입니다</div>} />
</Swtich>
nginx의 경우 해결 방법
nginx.conf 의 sites-available에서 default 로 설정된 server block 내에 location / 블록을 추가해주면 됩니다.
자세한 설명은 nginx 에서 다루고 있습니다.
location / {
try_files $uri $uri/ /index.html;
}
apache의 경우 해결 방법
다음 경로로 이동한다.
cd /etc/apache2/sites-enabled
다음과 같은 값이 설정되어 있는지 확인한다.
/etc/apache2/sites-enabled/000-default.conf
확인 후에는 RewriteEngine이 실행되게끔 해야 한다. a2enmode rewrite 명령어를 실행해주자.
sudo a2enmod rewrite
다음에는 아파치를 재시작해주자.
sudo /etc/init.d/apache2 restart
이제 /etc/apache2/apache2.conf을 수정해주도록하자.
sudo vim /etc/apache2/apache2.conf
아파치의 웹사이트의 root는 기본적으로 /var/www/html이므로 다음을 복붙해준다.
<Directory "/var/www/html">
RewriteEngine on
# Don't rewrite files or directories
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
# Rewrite everything else to index.html to allow html5 state links
RewriteRule ^ index.html [L]
</Directory>
이제 다른 경로로 접속해도 index.html로 연결되기 때문에 해결될 것이다.
'React, Next, Redux > ⚛ React.JS' 카테고리의 다른 글
react-slick을 이용한 캐러셀 슬라이더 (0) | 2020.04.18 |
---|---|
Nested Routing (0) | 2020.04.14 |
Context API 상태 관리 라이브러리 (0) | 2020.03.23 |
react-create-app breakdown + Webpack 기초 (0) | 2020.03.21 |
props vs state (0) | 2020.03.17 |