평상시 노션에 공부한 내용을 정리하며 티스토리에 옮기는 편인데
기존에 노션을 사용하면서 글자 지워짐 현상, 티스토리에 마크다운으로 옮기기 어려운 문제 등이 지속되면서
이전에 Github Star를 눌러두었던 유림님의 TIL이 생각났다.
처음에는 얼핏 봤을 때 GitBook
으로 만들어졌구나! 하고 넘어갔었는데 오늘날에서야 코드를 보니 VuePress
로 만들어진 것을 확인할 수 있었다.
💡 VuePress?
Vue 기반 정적 사이트 생성기
Vue를 기반으로 GitBook과 같이 문서화, 블로그 등에 많이 쓰이는 라이브러리였다.
GitBook으로 알고 있던 사이트들이 VuePress 였었다는 것에 정말 관심을 가지지 않았구나 싶었다..😅
npmtrends에서 확인해보니 GitBook 보다는 VuePress가 훨씬 많이 사용되고 있었고,
지속적인 업데이트, 커스텀 활용도가 GitBook 보다는 좋아 블로그로 사용하는 분들이 많았다.
⚙️ 본격 VuePress로 TIL 프로젝트 만들어보기
알아보고, 에러를 많이 마주치면서 몇 시간을 날렸는지 모르겠지만 이해만 잘 한다면 생각보다 과정은 쉬웠다.
참고한 사이트
1. https://vuepress.vuejs.org/
2. https://kyounghwan01.github.io/Vue/vuepress/vuepress-start/#%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0
3. https://milooy.wordpress.com/2020/07/28/github-actions%EB%A1%9C-vuepress-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0/
Github 레파지토리 생성 및 clone
- TIL 사이트로 사용할 레파지토리를 생성하고, gh-pages 브랜치를 생성한다.
- 해당 레파지토리의 Settings > Pages > Build and deployment 에서
Source: Deploy from a branch
,Branch: gh-pages
로 설정한다.
- git clone 하기
url 입력 시 <> 부분은 제외 후 본인의 상황에 맞게 입력하기
git clone https://github.com/<github 계정 이름>/<레파지토리명>.git .
git clone url 명령어 뒤의 .
의 경우 현재 로컬 폴더에 클론하겠다는 의미이다.
로컬에 폴더를 이미 생성 했을 경우 .
을 사용하면 현재 폴더에 바로 github에 있는 코드와 remote가 적용되며, 폴더를 생성하지 않았거나 다른 프로젝트 폴더 내에서 클론하는 경우에는 .
을 사용하지 않고 클론하는 것이 좋다.
ex) Test 폴더에서 git clone . 실행 -> Test 폴더 내에 clone한 프로젝트의 파일들이 depth 없이 생성
ex) Test 폴더에서 git clone 실행 -> Test\<clone한 프로젝트 폴더>\<clone한 프로젝트 폴더 내 파일> 생성
VuePress 설치
VuePress 공식 문서에서는 webpack 3.x를 사용하는 경우 yarn 사용을 권장한다.
현재 webpack 버전은 v5.x 이지만, 추후 버전 문제가 생기는걸 방지하기 위해서는 yarn을 사용하자.
VuePress도 React 처럼 create-vuepress-site를 제공한다. 나의 경우에는 불필요한 세팅보다는 간단하게 세팅하고 싶어서 굳이 사용하지 않았다.
yarn init -y
yarn add -D vuepress
첫 번째 문서 만들기
mkdir docs && echo '# vuepress til' > docs/README.md
VuePress는 docs
폴더를 targetDir
(cf. command line interface)로 사용한다.
상대 경로는 docs
폴더를 기준으로 하며, VuePress 공식 문서에 있는 기본 페이지 라우팅 경로는 아래와 같다.
상대 경로 | 페이지 라우팅 |
/README.md | / |
/guide/README.md | /guide/ |
/config.md | /config.html |
따라서 docs/README.md
에 작성한 첫 번째 문서는 VuePress로 만들어진 사이트의 루트 경로에서 보여지게 된다.
package.json 스크립트 추가
{
"scripts": {
"docs:dev": "vuepress dev docs",
"docs:build": "vuepress build docs"
}
}
로컬에서 실행해보기
yarn docs:dev
실행에 성공한다면, https://localhost:8080 에서 아래와 같은 화면이 렌더링 된다.
VuePress 설정하기 | .vuepress/config.js
.
├─ docs
│ ├─ README.md
│ └─ .vuepress
│ └─ config.js
└─ package.json
VuePress 사이트를 구성하기 위해서 .vuepress/config.js 에서 사이트 설정을 해주어야 한다.
아래의 설정 파일까지 작성했다면, 일단 깃헙의 main 브랜치에 push 하도록 하자 !
// title: 표기될 사이트 타이틀
// descrition: 사이트 설명
// base: 사이트가 배포될 기본 URL
module.exports = {
title: 'title',
description: 'desc',
// 배포 사이트가 https://깃헙계정.github.io/레포이름 으로 구성되어있을 경우
// base에 레파토리명을 지정주어야 한다.
// base: '/레포명/',
base: '/TIL/',
};
VuePress 배포하기 | deploy.sh
#!/usr/bin/env sh
# abort on errors
set -e
# build
# yarn docs:build or npm run docs:build
yarn docs:build
# navigate into the build output directory
cd docs/.vuepress/dist
# if you are deploying to a custom domain
# echo 'www.example.com' > CNAME
git init
git add -A
git commit -m 'deploy'
# if you are deploying to https://<USERNAME>.github.io/<REPO>
# git push -f git@github.com:<USERNAME>/<REPO>.git master:gh-pages
# main 브랜치 사용 시 main:gh-pages로 설정
git push -f git@github.com:<USERNAME>/<REPO>.git main:gh-pages
cd -
프로젝트의 루트에 deploy.sh 를 추가하고, sh deploy.sh
를 실행하여 깃헙에 배포한다.
윈도우 터미널의 경우 쉘 스크립트를 실행할 수 없기 때문에 git bash나 vscode 터미널을 bash로 변경하여 해당 명령어를 실행한다.
위에 작성된 deploy.sh의 내용은 아래와 같다.
- 로컬 빌드
- 빌드된 dist 파일을 gh-pages 브랜치에 푸시
이러한 과정으로 gh-pages에 푸시된 작성한 글들이 배포된 사이트에 보여지게 된다.
Github Actions를 사용하면 쉘 스크립트 실행 명령 없이도 main에 푸시하면 바로 사이트에 배포될 수 있도록 변경할 수 있다.
🚀 Github Actions를 사용하여 배포 자동화하기
- 개인 액세스 토큰 생성
- 프로젝트 레포지토리에 Secrets 추가
.github/workflows
에.yml
파일 생성
개인 액세스 토큰 생성
https://github.com/settings/tokens
본인 Github 계정 > Settings > Developer settings > Personal access tockens > Generate new token 으로 토큰을 생성하면 된다.
해당 토큰은 생성 시에 한번 보여주고, 이후에는 보안상 보여주지 않기 때문에 따로 복사해서 저장해두는 것이 좋다.
토큰의 액세스 범위는 repo와 workflow까지 설정해주었다. (다른 OAuth scopes)
workflow 범위는 굳이 필요 없는 것 같지만 혹시 몰라서 체크해주었다.
프로젝트 레파지토리에 Secrets 추가
레파지토리의 Settings > Secrets and variables > Actions 에서 Secret을 추가할 수 있다.
여기서 계정 세팅이 아닌 레파지토리 세팅임을 주의해야한다.
secrets를 사용하여 api키나 password 등의 데이터를 환경 변수처럼 관리할 수 있다.
Name 란에 사용할 secret의 Name을 입력하고, Secret에 이전에 발급받은 계정의 Access Token을 입력한다.
이 때 따옴표 없이 복사한 내용을 붙여넣기만 하면 된다.
.github/workflows에 .yml 파일 생성
프로젝트의 루트에 .github/workflows
폴더를 생성하고 그 아래에 .yml
파일을 생성한다.
나는 main.yml
로 생성해주었다.
아래의 코드는 VuePress 공식 문서에서 소개된 jenkey2011 유저가 배포한 action 코드이다.
링크에 들어가면 리드미에 파라미터에 대한 설명과 데모 예제를 볼 수 있다.
나는 이 파라미터에 대한 설명을 제대로 안 읽어서 여러 번의 배포 실패를 경험했다🥲
코드에서 사용된 ${{ secrets.ACCESS_TOKEN }}
이 위에서 생성하여 설정해준 레파지토리의 secrets에 접근해서 토큰을 참고하는 부분이다.
name: Build and Deploy
on: [push]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@main
- name: vuepress-deploy
uses: jenkey2011/vuepress-deploy@master
env:
ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
TARGET_BRANCH: gh-pages
BUILD_SCRIPT: yarn && yarn docs:build
BUILD_DIR: docs/.vuepress/dist/
작성 후, main 브랜치에 push 하게 되면 자동으로 Actions에서 빌드하고, 배포를 진행해준다 🎉🎉
Tip. 자동으로 카테고리(Sidebar) 생성하기
VuePress의 경우 Sidebar를 직접 config.js에 작성하거나, sidebar: auto
설정으로 각 파일마다 자동으로 Sidebar를 설정하게끔 할 수 있다.
하지만 이 마저도 귀찮을 수 있으니,, 아래의 링크를 참고하여 docs의 폴더를 기반으로 Sidebar를 생성해주는 코드를 작성했다.
아래의 코드를 .vuepress/config.js에 넣어주면 된다.
폴더가 있다면 폴더명으로 Sidebar가 생성되고, 없다면 Home에 글이 작성된다.
module.exports = {
title: "title",
description: "desc",
themeConfig: {
sidebar: getSidebarArr(),
},
//레파지토리 이름 넣기
base: "/TIL/",
};
/** 카테고리 자동 추가 */
function getSidebarArr() {
var fs = require("fs");
var docsPath = __dirname + "/../";
var sidebarArr = [];
var HomeFilelist = [];
var filelist = fs.readdirSync(docsPath);
filelist.forEach(function (file) {
if (file === ".vuepress") return;
var stat = fs.lstatSync(docsPath + "/" + file);
if (stat.isDirectory()) {
// directory
// title is file, children is readdirSync
var docsFolderPath = docsPath + "/" + file;
var list = fs.readdirSync(docsFolderPath);
sidebarArr.push(makeSidebarObject(file, list));
} else {
// NOT directory
// title is '/' children is file
HomeFilelist.push(file);
}
});
sidebarArr.unshift(makeSidebarObject("", HomeFilelist));
return sidebarArr;
}
function makeSidebarObject(folder, mdfileList) {
var path = folder ? "/" + folder + "/" : "/";
mdfileList = aheadOfReadme(mdfileList);
var tmpMdfileList = [];
// remove .md, add Path
mdfileList.forEach(function (mdfile) {
if (mdfile.substr(-3) === ".md") {
mdfile = mdfile.slice(0, -3) === "README" ? "" : mdfile.slice(0, -3);
tmpMdfileList.push(path + mdfile);
}
});
mdfileList = tmpMdfileList;
// remove folder prefix number
if (folder) {
var dotIdx = folder.indexOf(".");
var title = Number(folder.substr(0, dotIdx))
? folder.substr(dotIdx + 1)
: folder;
} else {
title = "HOME";
}
return {
title: title,
children: mdfileList,
};
}
function aheadOfReadme(arr) {
// ['1.test.md','README.md'] => ['README.md','1.test.md']
var readmeIdx = arr.indexOf("README.md");
if (readmeIdx > 0) {
arr.unshift(arr.splice(readmeIdx, 1)[0]);
}
return arr;
}
코드를 push 하면 적용된 화면을 볼 수 있다 🎉🎉
많은 우여곡절 끝에 자동 배포화를 성공하고, 문제점을 찾아 해결할 수 있음에 또 한 걸음 성장함을 느꼈다.
예전에는 공식 문서조차 잘 읽지 못해 무조건 구글링에 의존했는데 공식 문서가 제일 잘 설명되어 있다는 말을 최근에야 이해가 되었다 :D
아직 100% 공식 문서만 보진 않지만 이제는 60% 정도는 참고하고 있지 않나 싶다. 물론 잘 작성되어 있는 공식 문서라는 것에 한해서..!
이 글을 보고 vuepress를 처음 시작하는 사람들에게, 에러를 마주친 사람들에게 도움이 되었으면 좋겠다👍
'Retrospective > Project' 카테고리의 다른 글
[TailwindCSS] Tailwind CSS 동적 스타일링 적용법 (+ 주의사항) (0) | 2024.11.02 |
---|---|
[AWS] AWS Lambda + S3 연동해서 파일 가져오기 (0) | 2023.11.15 |
[React] 상품/장바구니 수량 조절 기능 구현하기 (0) | 2023.06.09 |
[HTML/CSS] 오늘 내 사자는? - 웹 접근성과 성능을 고려하여 TIL 기록 페이지 리팩토링하기 (0) | 2023.05.15 |
[JS] <progressbar>를 사용하여 설문지의 진행도를 구현해보자! (0) | 2023.04.29 |