이번 시간에는 단일 페이지 블로그를 제외한 클론 페이지 제작 시 중요한 SPA(Single-Page-App)에 대한 해결방법을
포스팅해보겠습니다. 기본적으로 깃허브에서는 SPA를 지원하지 않습니다. 리액트 라우터(React)의 <BrowserRoute />를
사용하면 데모사이트 같은 리액트(react), 그 외 프런트엔드 라이브러리 및 프레임워크를 사용하면 애플리케이션을 쉽게 배포
할 수 있습니다.
1.SPA 가 필요한 이유?
기본적으로 github Pages는 단일 페이지 앱을 지원하지 않습니다. 예를 들어 URL이 example.tId/foo이고 /foo가 프론트엔드 경로인 경우, 깃허브 페이지 서버는 /foo를 모르기 때문에 404 에러를 반환합니다. 이 문제를 해결하는 방법을 알아보겠습니다.
작동방식
- Github 페이지 서버가 fornt-End 경로인 (예: example.tId/foo)로 URL 요청을 받는다면 404.html 페이지로 반환됩니다.
이 문제를 해결하려면 404.html 파일에 스크립트를 만들어줍니다. 이 스크립트는 현재 URL을 가져와서 URL의
경로 (path) 쿼리 (query)에 해당하는 문자열을 모두 쿼리 문자열로 변환 한 다음 쿼리 문자열(query)과 해시(hash) 조각만 있는 새로운 URL로 리다이렉션 됩니다. 예를 들어 URL이 example.tId/one/two? a=b&c=d#qwe인 경우,
example.tId/? p=/one/two&q=a=b~and~c=d#qwe로 변경됩니다.
깃허브 페이지 서버는 example.tId? p=/... 이라는 URL 주소를 요청 받으면 example.tid? p=/..., 에 포함된 쿼리와 해시 문자열을 무시하고 index.html을 반환합니다. index.html 파일에도 스크립트가 존재합니다. 이 스크립트는 SPA가 로드되기 전에 쿼리 문자열의 리다이렉션을 확인합니다. 리다이렉트가 존재하면 올바를 URL로 다시 변환되며
window.history.replcaeState(...)으로 브라우저 히스토리에 추가되지만, 브라우저는 새로운 URL로 로드되지 않습니다.
index.html 파일에서 SPA가 로드되면 , URL이 브라우저 히스토리에 대기하면서 그에 따라 SPA 경로를 지정합니다. (리다이렉션은 새로운 페이지가 로드 될 때만 필요합니다. 이후 SPA 내부를 탐색하는 경우 필요하지 않습니다.
SEO
404페이지로 반환하는 방법은 그다지 좋은 방법은 아닙니다. 서치 앤진 랜드(Search Engine Land)가 실시한 테스트를 참고해보면, 구글 크롤러는 404.html 파일의 자바스크립트 window.location을 처리하는데, 이는 검색 색인 생성을 위한 301 리다이렉션
과 동일하다고 말했습니다. 301 리다이렉션 (Permanent Redirect: 영구 전송) 은 URL(A)가 URL(B)로 구성될 경우
콘텐츠도 URL도 새로운 B를 대상으로 표시합니다. 추가로 개인 테스트를 통해 구글이 문제없이 모든 페이지를 색인하여 검색에
반영하는 것을 확인했습니다. 다만 주의할 점은 리다이렉트 쿼리는 구글의 URL 색인 방식을 따라야한다는 점입니다. 예를 들어
example.tid/about 은 example.tId/?p=/about로 색인화 됩니다. 사용자가 검색 결과를 클릭하면, url은 example.tId/about로 다시 바뀝니다.
사용 설명
- 깃허브 페이지 기본 사용법은 공식 Github Pages Basics에서 확인하실 수 있습니다.
깃허브 페이지는 개인,조직,프로젝트 웹사이트 등으로 사용할 수 있습니다.
기본 사용 설명
이미 만들어진 레퍼지토리 내용을 추가해 깃허브 페이지를 호스팅 하는 방법입니다.
1. 작업 중인 레퍼지토리에 404.html을 만들어 404.html에 있는 내용을 복사 붙여넣기 합니다.
- 커스텀 도메인을 사용하지 않고도 프로젝트 페이지를 사용할 경우 (예를 들어 username.github.io/repo-name)
404.html 파일의 segmentCount 변수를 1로 설정합니다.리다이렉션 된후 루트 내 /repo-name를 유지하게 됩니다.
2. index.html파일 내 리다이렉션 스크립트 부분을 복사해 index.html 파일에 추가합니다.
- 리다이렉션 스크립트 위치는 index.html 파일의 SPA 스크립트 전에 있어야 합니다.
상세 사용 설명
- 다운로드한 이 레퍼지토리를 보일러플레이트(boilerplate)로 사용해 깃허브 페이지에 호스팅 하는 방법입니다.
1. 레퍼지토리를 클론합니다. ( $ git clone https://github.com/rafgraph/spa-github-pages.git)
2. 숨김 폴더인 .git 폴더를 지워줍니다. (cd 명령어로 spa-github-pages 폴더에 들어가서
$ rm -rf .git 명령어로 지워줍니다.)
3.레퍼지토리를 인스턴스화 합니다.
- 보일러플레이트를 새 레퍼지토리로 생성하길 원하는 경우
- - spa-github-pages 폴더에서 $ git init 명령어를 입력합니다. 그다음 $ git add . ,
- $git commit -m "Add SPA for GitHub Pages boilerplate" 명령어로 새 저장소를 초기화 합니다. - 프로젝트 페이지 사이트일 경우, 브랜치 이름을 main에서 gh-pages로 변경합니다.( $git branch -m gh-pages)
로 변경합니다. ($ git branch -m gh-pages). 개인 사용자 또는 기관 페이지 사이트 일 경우 브랜치 이름을 main으로
유지합니다. - 깃허브 홈페지에서 빈 레퍼지도리를 생성합니다. (readme.md, .gitnore, license 파일은 추가 x) 로컬 레퍼지토리에 원결 레퍼지 토리를 추가합니다. ($git remote add origin <내가 생성한 repository 주소>)
- 현재 로컬 폴더 이름인 spa-github-pages를 원하는 이름으로 바꿔줍니다.(예 프로젝트-이름)
- 보일러플레이트를 기존 레퍼지토리의 gh-pages 브랜치로 추가하는 경우
- - 기존 레퍼지토리에서 부모 커밋이 없는 새로운 브랜치인 gh-pages를 만들어줍니다.($ git checkout --orphan gh-pages)
첫 커밋 전까지 gh-pages 에 브랜치 리스트가 없어야 합니다. - - 기존 레퍼지토리 폴더에서 .git폴더를 제외한 모든 파일과 폴더를 삭제합니다. ($ git rm -rf .)
- - 새로운 프로젝트-폴더를 만들고 spa-github-pages폴더에 있는 모든 파일 (숨김 파일 포함) 과 폴더를 복사해 새 폴더로 복사합니다. ($ mv path/to/spa-github-pages/{.[!.],}* path/to/프로젝트-폴더) ㅁ
- $ git add . 명령어를 입력하고 gh-pages 브랜치를 인스턴스화 하기 위해 $git commit -m "Add SPA for Github Pages boilerplate" 명령어를 입력해줍니다.
4.(옵션) 커스텀 도메인 설정
- [깃허브 페이지] 커스텀 도메인 설정 가이드를 참고해서 커스텀 도메인 설정을 해줄 수 있습니다.
- CNAME 파일에 http://을 제외한 커스텀 도메인을 업데이트 해줍니다. 서브도메인과 www를 추가할 수 있습니다.
- CNAME 파일 또는 A 레코드에 DNS 공급자를 업데이트 합니다.
- $ dig your-subdomain.your-domain.tId 명령어를 실행해 DNS가 올바르게 설정되어 있는지 확인합니다. (명령어를 입력 할 때 도메인 주소의 http:// 는 제외 합니다.)
5.(옵션) 커스텀 도메인 없이 설정
- CNAME 파일을 삭제합니다.
- 사용자 또는 조직 페이지 사이트를 만드는 경우, 이 것으로 마치면 됩니다.
- 프로젝트 페이지 사이트 생성을 하고 싶다면 아래와 같이 해줍니다.(사이트 주소는 username.github.io/repo-name 입니다.)
- 404.html 파일에 있는 segmentCount 변수를 1로 설정합니다. 리다이렉션 된 후 루트 내 /repo-name을 유지하기 위합입니다.
- index.html 파일 내 리다이렉션 스크립트 부분을 복사해 index.html 파일에 추가합니다. - bundle.js 파일의 src 경로 부분을 to "/repo-name/build/bundle.js" 로 수정합니다. - 리액트 라우터(React Router) 를 사용할 경우, basename prop에 repo-name을 추가해야 합니다. 예를 들어 <BrowserRouter basename="/repo-name" /> 이라고 URL의 basename을 설정합니다.
6. $ npm install 로 리액트와 의존성 패키지를 설치합니다. 이후 $ npm run build로 빌드 내용을 업데이트 합니다.
7. $ git add . 명령어 입력후, $ git commit- m "Update boilerplate for use with my domain" 커밋 메시지를 작성하고, 깃허브에 푸시합니다. (프로젝트 페이지일 경우 $ git push origin gh-pages 를 입력, 사용자 또는 기관 페이지일 경우 $ git push origin main을 입력) 도메인에 사이트가 게시되어야 합니다.
개발 환경
개발 환경에서 $npm start로 로컬 서버를 실행해줍니다. webpack-dev-server이 적용되어 있습니다.
webpack-dev-server는 소스 파일을 주시하고 있다 변경이 감지되면 변경된 모듈만 새로 번들링 되어 디스크에는
번들 파일이 저장되지 않습니다.
- package.json파일 내 script에서 $npm start를 확인할 수 있습니다. 명령어 입력 시 $ webpack-dev-server --devtool eval-source-map --history-api-fallback --open를 실행합니다.
- -devtool eval-source-map은 개발 중 소스 맵 생성(generating source maps)을 합니다.
- -history-api-fallback은 프론트엔드 라우팅을 허용하고 요청된 파일을 찾을 수 없을 때 index.html이 서빙됩니다.
- --open 은 브라우저에 사이트가 자동으로 열립니다.
- webpack-dev-server는 http://localhost:8080에서 index.html를 제공합니다. (기본 포트 번호는 8080입니다.) 브라우저가 아닌, 서버에서 먼저 index.html를 읽어야 합니다. 반대로 브라우저에서 바로 열 경우 스크립트가 로드되지 않습니다.
그 외
- 리퍼지토리 내 .nojekyll 파일은 깃허브 페이지의 지킬(Jekyll) 사용을 제거합니다
- 정적 웹사이트에 폼 제출(form submission) 기능이 필요하다면 폼즈프리(formspree)을 사용해보세요.
- 깃허브 페이지 CDN의 가장 좋은 점은 모든 파일이 gzip으로 자동 압축된다는 것입니다. 프로덕션 환경을 위해 별도로 HTML, 자바스크립트, CSS 파일을 압축하지 않아도 됩니다.
참고자료
'프론트 엔드 > React' 카테고리의 다른 글
[React] 프로젝트를 Github Pages에 배포하는법 (0) | 2021.10.08 |
---|---|
Sentry.io로 프로젝트 오류 잡아내기 (0) | 2021.09.12 |
[Firebase] React에서 Firebase Auth를 사용한 로그인 구글 로그인 구현 (0) | 2021.09.01 |