Intro.
안녕하세요. 아아덕후입니다.
최근에 markdown 파일을 문서화하는 과정에 사용한 vitepress 프레임워크 설정 방법 및 S3를 이용한 배포 방법을 공유하기 위해 글을 작성했습니다. (vitepress와 AWS S3에 대한 소개와 설명은 위 링크를 참고 부탁드립니다!)
이번 포스팅에서는 아래 세가지 목표를 가지고 글을 작성했습니다.
- vitepress 처음 사용하는 분들이 쉽게 시작할 수 있도록 도움을 드리기 위해서
- markdown 파일로 만든 자료를 공유하기 위한 분들과 markdown으로 기술 문서를 작성하려는 분들께 도움을 드리기 위해
- 그리고 마지막으로 저에게는 급하게 만들고 배포했던 기억을 정리하며 vitepress boilerplate를 만들어
다음에 기술문서 공유 혹은 마크다운 문서화 작업이 필요할 때 빠르고 쉽게 사용하기 위해 준비하기 위해
그렇다면 다른 방법도 있었을텐데 왜 vitepress를 사용했는지 간단히 말씀드리면,
회사에서 vite를 사용하고 있고 예전에도 포스팅으로 가볍게 다루었기때문에 친숙했고,
vue 기반이여서 조금 더 쉽게 접근항 수 있겠다고 판단했습니다.
위 이유들로 md 파일의 문서화 목표에 집중해서 공유하기에 가장 빠르고 효율적으로 할 수 있다고 판단했기 때문입니다.
그렇게 vitepress로 md 파일을 볼 수 있게 개발하여 빌드 후 S3를 사용해 배포했습니다. (간단한 정적 웹이기 때문에)
그럼 아래에서 부터 본격적으로 vitepress 개발 방법 및 S3를 이용한 배포 방법을 소개하겠습니다.
완성 페이지 : http://icedamericano.s3-website.ap-northeast-2.amazonaws.com/
목차
- vitepress 설치
- vitepress 설정
- vitepress 빌드 및 AWS S3 버킷 생성
- AWS S3 버킷 업로드 및 배포
- 마무리
- 참고
1. vitepress 설치
전제 사항
[환경] Node.js 버전 18 이상 설치 및 확인
node -v
1. 터미널에서 다음 명령 중 1개를 선택하여 VitePress를 전역으로 설치 및 실행합니다.
npm add -D vitepress // npm
pnpm add -D vitepress // pnpm
yarn add -D vitepress // yarn
bun add -D vitepress // bun
2. 터미널에서 VitePress 설정 마법사를 실행합니다.
npx vitepress init // npm
pnpm vitepress init // pnpm
yarn vitepress init // yarn
bun vitepress init // bun
아래와 같이 여러 가지 질문 사항에 답을 만들어 주면, 해당 답에 따라 vitepress 기본 설정을 해줍니다.
순서대로
- VitePress에서 구성을 초기화할 위치
- vue프로젝트의 src와 같은 경로 지정
- Site title
- 메인 화면 타이틀
- Site description
- 메인 화면 아래 설명 글
- Theme
- 메인 테마
- 타입스크립트 사용할 것인지?
- 저는 JS만 사용하기 위해서 No 했습니다.
- Package.json에 VitePress npm 스크립트를 추가하시겠습니까?
- Yes.
이후 .gitignore에 배포 시 생성되는 폴더 dist를 추가하라고 하며 설치가 완료됩니다.
그럼 만든 vitepress를 확인해 볼까요?
해당 vitepress를 실행하기 위해서는 아래 커맨드를 작성해서 실행합니다.
npm run docs:dev
짜잔 - 그러면 아래와 같이 아까 설정한 값들이 메인화면에 출력됩니다.
2. vitepress 설정 (nav, sidebar, search, index.md)
저는 vitepress의 정확한 레퍼런스 자료를 찾기 어려워 아래에 소개 드릴 설정은 vitepress 한글 github를 참고한 방법입니다.
위에서 설치한 vitepress - JS버전의 경우, 기본적으로 docs/.vitepress/confing.mjs 파일이 설정 파일입니다.
(이때 docs는 위에서 vitepress 설치 시 작성한 root 폴더입니다.)
아래에서는 3가지 설정 방법에 대해서 소개 드리겠습니다.
- GNB의 네비게이션
- LNB 사이드바 (sidebar)
- 이외 추가 설정 ( 파비콘, 로고, 검색, 문서 footer)
위 설정으로 기본적인 vitepress 템플릿을 완성해 보겠습니다.
시작하기 앞서 완성된 화면(청사진)부터 보고 시작하겠습니다!
가장 처음 config.mjs 파일은 아래와 같습니다.
import { defineConfig } from 'vitepress'
// https://vitepress.dev/reference/site-config
export default defineConfig({
title: "boilerplate-vitepress",
description: "A vitepress boilerplate by Soo",
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
nav: [
{ text: 'Home', link: '/' },
{ text: 'Examples', link: '/markdown-examples' }
],
sidebar: [
{
text: 'Examples',
items: [
{ text: 'Markdown Examples', link: '/markdown-examples' },
{ text: 'Runtime API Examples', link: '/api-examples' }
]
}
],
socialLinks: [
{ icon: 'github', link: 'https://github.com/vuejs/vitepress' }
]
}
})
nav와 sidbar 설정 예시가 잘 나와있습니다.
저는 위 예시 코드에서 nav에는 드롭다운 설정을, sidebar에는 폴더 경로를 추가할 예정입니다.
그리고 검색 옵션 기능 값을 추가하고 마지막으로 index에서 위에서 설정한 경로들로 이동하도록 수정하겠습니다.
그럼 파일 먼저 생성하고 시작하겠습니다!
저는 docs 폴더 아래 .vitepress와 동일한 경로에 examples, section-a, section-b 라는 폴더를 생성하였고 그 안에 추가 md 파일을 생성했습니다.
그러면 위에서 추가한 파일들을 매핑해주는 nav와 sidebar를 만들어보겠습니다!
2-1 GNB의 네비게이션 (nav)
완성 될 화면 상단 GNB의 메뉴 형식은 위와 같습니다!
기본적으로 vitepress에서 지정해 놓은 nav 타입은 아래와 같습니다.
interface NavItemWithLink {
text: string
link: string
items?: never
/**
* `activeMatch` is expected to be a regex string. We can't use actual
* RegExp object here because it isn't serializable
*/
activeMatch?: string
rel?: string
target?: string
noIcon?: boolean
}
여기서 저는 nav에 text, link, items 설정만 추가했습니다.
nav: [
{ text: "Home", link: "/" },
{ text: "Examples", link: "/examples/markdown-examples" },
{
text: "드롭다운 메뉴",
items: [
{
// 섹션의 제목.
text: "섹션 A 제목",
items: [
{
text: "섹션 A 항목 A",
link: "/section-a/section-a-test1",
},
{
text: "섹션 A 항목 B",
link: "/section-a/section-a-test2",
},
],
},
{
// 섹션 두 번째
// 제목을 생략할 수도 있습니다.
// text: "섹션 B 제목",
items: [
{ text: "섹션 B 항목 A", link: "/section-b/section-b-test1" },
{ text: "섹션 B 항목 B", link: "/section-b/section-b-test2" },
],
},
],
},
],
text는 nav에서 출력되는 문자열이고 같은 레벨에 link가 있으면, 클릭 시 해당 링크로 이동하게 됩니다.
이때 link가 아닌 items가 있으면 한 뎁스를 더 들어가게 됩니다.
드롭다운의 경우 첫번째 뎁스에서 text로 제목을 입력하고 items를 추가하여 뎁스를 추가합니다.
두 번째 뎁스에서 text와 link를 설정하면 아래와 같이 nav바를 완성할 수 있습니다.
이때, link와 item이 같이 있으면 link가 우선순위가 되어 items가 출력되지 않고 바로 링크로 이동하게 됩니다.
nav: [
...,
{
text: "드롭다운 메뉴",
link: "/section-a/section-a-test1", // link 추가
items: [
{
// 섹션의 제목.
text: "섹션 A 제목",
items: [
{
text: "섹션 A 항목 A",
link: "/section-a/section-a-test1",
},
{
text: "섹션 A 항목 B",
link: "/section-a/section-a-test2",
},
],
},
{
// 섹션 두 번째
// 제목을 생략할 수도 있습니다.
// text: "섹션 B 제목",
items: [
{ text: "섹션 B 항목 A", link: "/section-b/section-b-test1" },
{ text: "섹션 B 항목 B", link: "/section-b/section-b-test2" },
],
},
],
},
],
2-2 LNB 사이드바 (sidebar)
다음은 sidebar 설정을 해보겠습니다.
sidebar는 각 메뉴별 페이지별 설정을 해주어야 합니다.
.
기본적으로 vitepress에서 지정해 놓은 sidebar 타입은 sidebarItem[] 혹은 SidebarMulti 입니다.
type Sidebar = SidebarItem[] | SidebarMulti
interface SidebarMulti {
[path: string]: SidebarItem[] | { items: SidebarItem[]; base: string }
}
type SidebarItem = {
/**
* The text label of the item.
*/
text?: string
/**
* The link of the item.
*/
link?: string
/**
* The children of the item.
*/
items?: SidebarItem[]
/**
* If not specified, group is not collapsible.
*
* If `true`, group is collapsible and collapsed by default
*
* If `false`, group is collapsible but expanded by default
*/
collapsed?: boolean
/**
* Base path for the children items.
*/
base?: string
/**
* Customize text that appears on the footer of previous/next page.
*/
docFooterText?: string
rel?: string
target?: string
}
저는 SidebarMulti 인터페이스 형식으로 사용했습니다.
각 폴더별 path에 맞는 SidebarItem을 설정해주었습니다.
SidebarItem 타입 속성 중 text, link, items, collapsed, 그리고 base 설정을 사용했습니다.
위에서 3개의 path : examples, section-a, section-b를 기준으로 각 폴더와 매핑하여 sidebar를 구성했습니다.
sidebar: {
// key 값 = 해당 url 경로 (path) : SidebarItem[]
"/examples/": {
base: "/examples/", // base : 해당 경로 폴더
items: [ ... ] // items : 해당 폴더의 파일들 (contents)
},
"/section-a/": {
base: "/section-a/",
items: [ ... ]
},
"/section-b/": {
base: "/section-b/",
items: [ ... ]
},
},
이때 key 인 path가 url이고, base는 폴더의 경로를 지정합니다.
아래 페이지 url은 http://localhost:5173/examples/markdown-examples.html 입니다.
해당 페이지에 매핃되는 파일 경로는 docs/examples/markdown-examples.md 입니다.
따라서 base에서 지정한 examples폴더에서 해당 파일을 찾도록 세팅을 합니다.
같은 방법으로 구성한 두 번째 메뉴인 Section B 페이지 예시도 아래와 같습니다.
페이지 URL : http://localhost:5173/section-a/section-a-test1.html
파일 경로 : docs/section-a/section-a-test1.md
이제 페이지에 맞는 url과 폴더 경로 url을 매핑하였으니 각 페이지에 속하는 컨텐츠들(items)를 매핑해보겠습니다.
sidebar: {
"/examples/": {
base: "/examples/",
items: [
{
text: "Examples", // 파일 그루핑
items: [
{ text: "Markdown Examples", link: "markdown-examples" },
{ text: "Runtime API Examples", link: "api-examples" },
],
},
{
text: "Examples2", // 파일 그루핑
collapsed: true, // 접기 옵션
items: [
{ text: "Examples T1", link: "examples-t1" },
{ text: "Examples T2", link: "examples-t2" },
],
},
],
},
"/section-a/": {
base: "/section-a/",
items: [ ... ],
},
"/section-b/": {
base: "/section-b/",
items:[ ... ],
},
},
컨텐츠(items)는 객체 배열로 되어있으며 각 객체에 text : 그룹명, items : 실제 컨텐츠(md 파일)로 nested하게 구성되어 있습니다.
그리고 items내부에는 text와 link로 text는 화면에서 보이는 이름과 link는 base에서 선언한 폴더 경로 내의 파일 명을 작성해주시면 됩니다!
위와 같이 설정해 놓은 결과물은 아래와 같습니다.
그럼 최종 sidebar 코드는 아래와 같습니다.
sidebar: {
// key 값 = 해당 url 경로 (path) : SidebarItem[]
"/examples/": {
// base : 해당 경로 폴더
base: "/examples/",
// items : 해당 폴더의 파일들 (contents)
items: [
{
text: "Examples",
items: [
{ text: "Markdown Examples", link: "markdown-examples" },
{ text: "Runtime API Examples", link: "api-examples" },
],
},
{
text: "Examples2",
collapsed: true,
items: [
{ text: "Examples T1", link: "examples-t1" },
{ text: "Examples T2", link: "examples-t2" },
],
},
],
},
"/section-a/": {
base: "/section-a/",
items: [
{
text: "Section A",
collapsed: true,
items: [
{ text: "Section A test1", link: "section-a-test1" },
{ text: "Section A test2", link: "section-a-test2" },
],
},
],
},
"/section-b/": {
base: "/section-b/",
items: [
{
text: "Section B",
collapsed: true,
items: [
{ text: "Section B test1", link: "section-b-test1" },
{ text: "Section B test2", link: "section-b-test2" },
],
},
],
},
},
2-3 이외 추가 설정 ( 파비콘, 로고, 검색, 문서 footer )
import { defineConfig } from "vitepress";
export default defineConfig({
title: "boilerplate-vitepress",
description: "A vitepress boilerplate by 아아덕후",
head: [
[
"link",
{ rel: "icon", type: "image/svg+xml", href: "/vitepress-logo-mini.svg" },
],
],
themeConfig: {
// 화면 logo : public 안에 넣어 넣기
logo: { src: "/vitepress-logo-mini.svg", width: 24, height: 24 },
// ...
search: {
provider: "local",
},
// ...
docFooter: {
prev: "이전 페이지",
next: "다음 페이지",
},
},
});
이외 추가적으로 설정하면 좋을 옵션들에 대해 설명 드리겠습니다.
2-3-1. head : 파비콘 설정
2-3-2. logo : 사이트 로고 설정
위 head 속성의 href과 logo 속성의 src의 기본 경로는 .vitepress 폴더와 동일한 뎁스의 public폴더 입니다.
2-3-3. search: 검색 설정
2-3-4 docfooter : 각 페이지 맨 아래에서 이전 페이지/ 다음페이지 이동 설정 입니다.
2-4 cleanUrls 추가 설정 사항 ( 비권장 )
저는 cleanUrls라는 설정도 추가하여 아래에서 S3로 배포한 적이 있었습니다.
cleanUrl 기능은 맨 뒤에. html을 제거해 주는 기능입니다.
하지만 이 기능을 사용 시 발생한 문제는 모바일로 웹 페이지의 세션 A를 읽고 있다가 나중에 다시 들어와서 해당 문서 재요청할 때, url을 찾지 못하여 404 에러가 났습니다. (SPA문제)
문제 원인은 url 맨 뒤에 html이 없을 경우, 해당 문서 찾을 수 있도록 서버에서 설정을 해주어야 하는데 S3에서는 그런 설정이 없었습니다.
(제가 찾아본 바에 의하면 각 변동되는 url 맨 뒤에 추가로 붙여주는 것이 아니라 그냥 하나의 파일로 리디렉트 시키는 기능만 있었습니다..!)
그래서 cloudFront와 lambda를 결합해서 어찌 저찌 해보려고 했지만..
결국 가장 쉬운 방법은 cleanUrls 설정을 지우는 방향으로 결정했습니다!
혹시 cleanUrls 설정 후 어떻게 하면 되는지 해결 방법 아시면 공유 부탁드립니다!!
위의 4가지 설정을 완료한 후 이제 배포해 보도록 하겠습니다.
3. vitepress 빌드 및 AWS S3 버킷 생성
요약
3-1 VitePress 사이트 빌드
3-2 S3 버킷 생성
- AWS 관리 콘솔에 로그인
- S3 서비스로 이동
- 버킷 생성
- "버킷 만들기"을 클릭.
- 고유한 버킷 이름 설정.
- 퍼블릭 접근 허용할 경우, 모든 퍼블릭 액세스 차단 체크박스 해제
- 이외 설정 기본 값으로 두고
- 최하단 "버킷 만들기" 버튼 클릭
3-1 VitePress 사이트 빌드
cmd에 아래 명령어를 통해 vitepress 프로젝트를 빌드합니다.
npm run docs:build
그러면. vitepress 폴더에 dist라는 빌드 폴더가 생성됩니다.
이제 해당 폴더 내부의 파일들을 가지고 S3에 올려주기만 하면 정적 웹사이트를 배포할 수 있습니다.
3-2 S3 버킷 생성
이제 AWS console로 이동하겠습니다.
로그인 후 S3 서비스로 이동합니다.
여기서 오른쪽에 버킷 만들기 버튼을 클릭합니다.
여기서 버킷 이름은 모든 AWS 사용자들과 경쟁(?)해서 네이밍을 해야 합니다.
고유한 자신의 버킷 (폴더)를 만드는 것이기 때문에 다른 사람들과 버킷 이름을 겹치지 않게 지어줘야 합니다.
위에서는 예시로 한글로 적었지만 실제 생성 시에는 영어 소문자로 적으셔야 합니다!
그리고 배포하는 사이트를 모든 사람들이 들어올 수 있도록 하기 위해서는 위 차단 설정을 해제해주어야 합니다.
디폴트로 모든 퍼블릭 엑세스 차단이 되어있습니다.
따라서 퍼블릭 접근을 허용하기 위해서는 모든 퍼블릭 엑세스 차단 체크 해제, 아래 경고 창 내의 체크박스는 체크해서 진행해야 합니다.
빠르게 배포부터 하기 위해 이외 필요한 설정들은 넘어가도록 하겠습니다.
이렇게 설정 후 버킷 만들기 버튼으로 버킷을 생성합니다.
그럼 S3 대시보드에 방금 만든 새로운 버킷이 추가된 걸 확인할 수 있습니다.
4. AWS S3 버킷 업로드 및 배포
요약
4-1 파일 업로드
- 생성한 버킷으로 이동합니다.
- vitepress 빌드 결과물인 dist 폴더 내부 파일 업로드
- "업로드"버튼 클릭.
- dist 폴더의 모든 파일을 드래그 앤 드롭으로 업로드(편한 방법 선택)
- 최하단 "업로드" 클릭.
4-2 버킷 정책 설정
기본적으로 S3 버킷은 비공개로 설정되어 있습니다.
정적 사이트에 대한 접근을 허용하려면 버킷을 공개로 설정해야 합니다.
- S3 버킷의 "권한" 탭으로 이동.
- "버킷 정책"섹션의 "편집" 버튼 클릭하여 버킷 내용을 공개적으로 접근할 수 있도록 설정.
- "버킷 정책" 클릭.
- 아래 정책 추가
- ( ★★주의★★) your-bucket-name을 실제 버킷 이름으로 바꿔야 합니다.
- { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::your-bucket-name/*" } ] }
- 최하단 "변경 사항 저장" 클릭
4-3 정적 웹사이트 호스팅 구성
- S3 버킷의 "속성" 탭으로 이동합니다.
- "정적 웹사이트 호스팅" 섹션으로 스크롤(맨 아래)합니다.
- 정적 웹사이트 호스팅을 활성화합니다:
- "정적 웹 사이트 호스팅" 활성화 선택
- "인덱스 문서"에 index.html을 입력.
- "오류 문서"에 404.html을 입력.
- "변경 사항 저장" 버튼 클릭
4-4 배포 확인
S3 버킷 속성의 맨 아래로 이동하면 정적 웹사이트 호스팅 섹션에 방금 저장한 사이트의 URL이 아래와 같이 나옵니다.
your-bucket-name.s3-website.ap-northeast-2.amazonaws.com url을 통해 배포를 확인합니다.
4-1 파일 업로드
이제 위에서 빌드한 파일을 업로드하겠습니다.
버킷 대시보드에서 이름을 클릭하면 다음과 같이 버킷 객체 속성으로 들어올 수 있습니다.
여기서 오른쪽 업로드 버튼을 클릭합니다.
아까 build 해서 만들어진 dist 폴더 안으로 들어옵니다.
dist 폴더 통째로 올리는 것이 아니라 dist 폴더 내부의 파일들을 올리셔야 합니다!
파일을 올리고 업로드 버튼 클릭하면 S3 버킷에 빌드 파일이 올라갑니다.
4-2 버킷 권한 설정
파일 업로드 후에는 권한 탭을 클릭하여 버킷 정책을 수정해주어야 합니다.
파일 업로드 후에는 권한 탭에서 버킷 정책을 수정해주어야 합니다.
버킷 정책 편집을 누르고 아래 정책을 복사 붙여 넣기 해주세요!
{ "Version": "2012-10-17",
"Statement":
[ { "Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource":"arn:aws:s3:::고유한_버킷_이름/*" }
]
}
위에서 고유한_버킷_이름 란에만 위에서 생성한 버킷 명을 넣어주면 됩니다.
제 경우에는 icedamericano입니다!
버킷 정책 입력하고 변경 사항 저장을 클릭합니다.
4-3 정적 웹사이트 호스팅 구성
이제 마지막으로 정적 웹사이트 호스팅을 설정하겠습니다.
버킷 설정의 속성 탭으로 이동합니다.
스크롤을 쭉 아래로 내리면 정적 웹 사이트 호스팅이 있습니다.
여기서 편집 버튼 클릭 합니다.
정적 웹사이트 호스팅 - 활성화 선택
호스팅 유형 - 정적 웹 사이트 호스팅 선택
인덱스 문서와 오류 문서는 build 된 파일 그대로 올리시면 위와 같이 index.html , 404.html을 적어주시면 되고
혹시 바꾸셨으면 바꾼 이름을 넣어주시면 됩니다.
그리고 리디렉션 규칙은 일단 빠르게 배포하기 위해 생략 후 변경 사항 저장을 클릭합니다!
그럼 이제 배포된 사이트를 확인해보겠습니다.
4-4 배포 확인
다시 맨 아래로 내리면 배포 된 사이트 url 이 나옵니다.
해당 url 클릭하면 아래와 같이 배포 된 vitepress 프로젝트를 확인할 수 있습니다.
5. 마무리
vitepress는 개발자의 문서(?) 마크다운을 편하게 다른 사람들과 공유하기에 좋은 툴이라고 생각합니다!
짧게 제가 vitepress를 찾은 과정(TMI)을 정리하면 아래와 같습니다.
- AWS 자격증을 공부할 때 MD파일로 강의 정리를 했습니다.
- 위에서 정리한 학습 자료를 공유하려고 했는데 pdf, word로 변환하니 포맷팅과 페이지 전환이 마음에 들지 않았습니다.
- 그렇다고 공유 대상 분들에게 md viewer를 설치해서 보시라고 할 수 없었고 방법을 찾아보았습니다.
- 기존 여러 블로그에서 md 파일을 블로그로 만드신 분들이 생각이나서 찾아봤습니다. (그중 캡틴판교님의 크래킹 vue.js가 - vuepress를 사용하셔서 블로그 만든것으로 확인)
- 그 중 vuepress를 검색했는데 md 문서화 프레임워크인 vitepress를 알게 되었었습니다.
이상으로 vitepress 프로젝트를 생성, 설정하고 빌드하여 S3로 배포하는 과정을 마무리 하겠습니다.
다음은 Next.js로 한번 프로젝트 만드는 방법을 연구해오겠습니다.
도움이 되셨다면 좋아요와 댓글 남겨주시면 감사하겠습니다.
감사합니다! 🌟 🌟
함께 읽으면 좋은 글
vite 란 ?! : 2023.03.27 - [Dev/🟨 JavaScript] - [Vite] 빛처럼 빠른 빁 ⚡ ( with. Vue 설치 )
참고
vitepress (한글) : https://vitepress.vuejs.kr/
vitepress github (한글): https://github.com/niceplugin/vitepress-ko
'Dev > 🌐 Web' 카테고리의 다른 글
서버가 만든 쿠키와 웹 스토리지 (0) | 2023.01.05 |
---|---|
[Web] HTML 태그 (feat. 부스트코스 _비전공자를 위한 HTML/CSS ) (0) | 2022.05.04 |
[Web] HTML 이해하기 (feat. 부스트코스 _비전공자를 위한 HTML/CSS ) (0) | 2022.05.04 |
댓글