noir1458.github.io를 위한 Astro 정적 블로그입니다. 현재 112개 논리 글과
번역을 포함한 114개 글 경로를 제공하며 /posts/<slug>/ 주소를 유지합니다.
Markdown, 수식, 검색, 태그, 카테고리, 아카이브와 Giscus 댓글을 지원합니다.
사이트를 운영할 때 수정하는 영역은
config/,content/,public/images/세 곳뿐입니다.
일반 사용자는 astro.config.mjs, package.json, src/**/*.ts,
src/**/*.astro, src/content.config.ts, .github/workflows/deploy.yml을 수정하지
않아도 사이트 정보, 글, 프로젝트, 이미지와 GitHub Pages 배포를 관리할 수
있습니다.
| 경로 | 용도 |
|---|---|
config/ |
사이트 정보, 프로필, 메뉴, 카테고리 묶음, 소셜 링크, 기능 켜기/끄기 |
content/ |
게시물·프로젝트 Markdown과 각각의 전용 이미지 |
public/images/ |
프로필, favicon, manifest, 기본 OG 이미지 |
- Astro 정적 빌드와 GitHub Pages 자동 배포
- 안정적인
/posts/<slug>/주소를 사용하는 Markdown 게시물 - 카테고리, 태그, 아카이브, 페이지네이션과 Pagefind 검색
- RSS, sitemap, robots.txt, canonical, Open Graph, JSON-LD
- 한국어·영어·일본어 번역 경로와
hreflang - 다크 모드, 수식, admonition, Mermaid 다이어그램, 코드 하이라이팅, 목차와 Giscus 댓글
- 설정으로 노출을 제어하는 프로젝트 목록과 상세 페이지
config/README.md의 순서대로 다음 파일을 수정합니다.
config/site.yaml: 사이트 URL, 제목, 설명, 언어, 시간대, 작성자, 공용 이미지, Analytics·Search Console·Giscus 공개 식별자config/navigation.yaml: header, sidebar, footer 메뉴와 순서config/categories.yaml: 사이드바 카테고리 묶음, 순서, 숨김config/social.yaml: GitHub, LinkedIn, X, Facebook, 이메일 링크config/features.yaml: search, RSS, sitemap, dark mode, 목차, Mermaid, 프로젝트, 댓글config/profile.md: About 제목과 소개 Markdown
빈 선택 값은 화면에서 자동으로 숨겨집니다. 메뉴의 requiresFeature를 사용하면
기능이 꺼졌을 때 연결된 메뉴도 함께 숨길 수 있습니다. YAML과 Markdown 설정은
빌드 전에 스키마와 파일 경로를 검증합니다.
사이트의 기본 accent Hue는 config/site.yaml에서 0부터 360 사이의 값으로
설정합니다.
appearance:
accentHue: 250모든 방문자는 이 Hue로 시작하며, palette 메뉴의 세로 slider로 개인 Hue를 조정할 수 있습니다. 방문자가 조정한 값은 해당 브라우저에 저장됩니다.
사이트 전체 배경 배너는 선택 기능이며 기본값은 꺼짐입니다. 로컬 이미지를 public/에 넣은 뒤
config/site.yaml에서 활성화하고 표시 방식을 조정합니다.
appearance:
banner:
enabled: true
image: /images/site/banner.webp
position: center
height: 600
mobileHeight: 420
overlayOpacity: 0.18이미지는 공통 layout을 사용하는 모든 페이지의 기존 header와 navigation 뒤에서 viewport 전체 폭을 채우고 현재 light/dark theme 배경으로 자연스럽게 이어집니다. 프로젝트 사이트의 base path도 자동으로 적용됩니다.
---
title: 글 제목
slug: post-slug
publishedAt: '2026-07-25'
categories: blog
math: false
---- Node.js 24 이상
- npm
nvm use
npm ci
npx playwright install --only-shell chromium
npm run dev로컬 주소는 기본적으로 http://localhost:4321입니다.
npm run new질문에 답하면 content/posts/<번호-큰분류>/<대표-category>/<slug>/ 아래에
한국어는 index.md, 영어는 en.md, 일본어는 ja.md로 생성됩니다.
기존 카테고리는 해당 큰 분류를 자동으로 재사용하고, 새 카테고리일 때만
큰 분류를 묻습니다. 이 폴더 구조는 소스 정리용이며 우측 사이드바의 묶음과
순서는 config/categories.yaml에서 관리합니다. groups와 hidden 어디에도
없는 카테고리는 마지막 묶음에 자동 표시되고 검사 결과에도 출력됩니다.
hidden은 사이드바에서만 숨깁니다. 초안은 기본적으로 draft: true입니다.
확인이 끝나면 draft 줄을 제거합니다.
글 분류에는 categories만 사용합니다. description은 선택 사항이며,
생략하면 본문의 첫 번째 유효 문단이 글 목록, 검색, RSS와 SEO 설명으로
자동 사용됩니다. Tags 화면은 호환성을 위해 유지되지만 태그를 지정하지
않으면 비어 있습니다. 카테고리가 하나면 categories: blog처럼 한 줄로
쓰고, 여러 개면 YAML 목록 형식을 사용합니다. 빌드 과정에서는 두 형식
모두 항상 문자열 배열로 정규화됩니다.
수식은 Markdown 안에서 다음처럼 작성합니다.
인라인 수식: $E = mc^2$
$$
\int_0^1 x^2\,dx = \frac{1}{3}
$$Mermaid는 별도 컴포넌트 없이 mermaid fenced code block으로 작성합니다.
다이어그램 우측 상단의 코드 아이콘(</>)을 누르면 화면 중앙의 모달에서 원문을
확인하고 복사할 수 있습니다.
```mermaid
flowchart LR
A --> B
B --> C
```글 전용 이미지는 언어 파일과 같은 글 폴더에 둡니다. 본문에서 처음 사용한
로컬 이미지가 글 목록과 공유 메타데이터의 대표 이미지로 자동 선택됩니다.
다른 이미지를 대표로 지정하고 싶을 때만 cover를 추가합니다. Astro는
빌드할 때 파일 존재 여부와 이미지 정보를 검사하고 최적화합니다.
cover: ./cover.pngpublic/images/는 여러 페이지에서 공유하는 사용자 교체 이미지에 사용합니다.
프로필 이미지는 public/images/profile/, 파비콘·manifest 아이콘·기본 OG 이미지는
public/images/site/에 둡니다. 실제 파일 경로는 config/site.yaml의
author.profileImage와 branding 설정에서 지정합니다. 글 전용 이미지는 계속
각 글 폴더에 둡니다.
프로젝트는 content/projects/<project-slug>/index.md에 추가합니다. 폴더명이
/projects/<project-slug>/ URL이 됩니다.
---
title: 프로젝트 이름
description: 프로젝트를 설명하는 짧은 문장
repository: https://github.com/username/project
demo:
image: ./cover.webp
tags:
- Astro
- TypeScript
featured: true
order: 1
---
프로젝트에 관한 자세한 설명을 Markdown으로 작성합니다.
repository, demo, image는 선택 사항이며 빈 값은 화면에서 숨겨집니다.
대표 이미지와 본문 이미지는 index.md와 같은 프로젝트 폴더에 둡니다. 기존
content/projects/<project-slug>.md 형식도 URL 호환을 위해 계속 지원합니다.
featured: true인
프로젝트가 먼저 나오고, 그 안에서는 order가 작은 순서로 정렬됩니다.
공개 전에는 draft: true를 사용합니다. 프로젝트 화면을 표시하려면
config/features.yaml의 projects를 true로 바꾸면 설정된 Projects 메뉴와
목록·상세 페이지가 함께 생성됩니다.
지원 언어는 한국어(ko), 영어(en), 일본어(ja)입니다. 기존 글처럼
lang을 생략하면 한국어로 처리되므로 기존 index.md와 공개 URL은 바뀌지
않습니다.
---
title: 한국어 글
slug: sample-post
publishedAt: '2026-08-02'
categories: blog
---파일명은 언어 슬롯을 나타냅니다. 한국어는 기존 호환성을 위해 index.md,
영어는 en.md, 일본어는 ja.md를 사용합니다. npm run new에서 처음 작성할
언어를 선택하면 해당 파일을 생성합니다.
---
title: An English Post
slug: english-post
translationKey: english-post
lang: en
publishedAt: '2026-08-02'
categories: blog
---번역본은 원문과 이미지 폴더를 공유하도록 같은 글 폴더에 언어 코드 파일로
추가합니다. 원문과 모든 번역본은 같은 slug와 논리적 번역 식별자를
사용해야 합니다.
content/posts/00.blog/blog/sample-post/
├── index.md # 한국어, lang 생략 시 ko
├── en.md # 영어, lang: en
├── ja.md # 일본어, lang: ja
└── diagram.png
---
title: English Translation
slug: sample-post
translationKey: sample-post
lang: en
publishedAt: '2026-08-02'
categories: blog
---처음 작성한 언어 파일에 translationKey가 있으면 다른 언어 파일도 같은 값을
사용합니다. 생략한 경우에는 slug가 논리적 글 식별자가 됩니다. 어느 언어를
먼저 작성했는지는 라우팅에 영향을 주지 않습니다. 한국어 기본 글은 /posts/<slug>/, 영어는
/en/posts/<slug>/, 일본어는 /ja/posts/<slug>/에 생성됩니다. 실제 번역본이
두 개 이상 있는 글에서만 우상단 테마 버튼 왼쪽에 언어 선택기가 나타나며,
존재하지 않는 번역 언어는 표시하지 않습니다.
글을 완성한 뒤 Codex에 다음처럼 요청합니다.
이 글 블로그 번역 스크립트대로 번역해줘:
content/posts/.../글-slug/ja.md
Codex는 지정한 파일을 원문으로 보고 현재 폴더에 없는 나머지 두 언어 슬롯을
바로 생성합니다. 예를 들어 ja.md로 시작했다면 index.md와 en.md를
만듭니다. 작업 전에 원문 해시를 기록하고, 생성 후 코드 블록·인라인 코드·
수식·링크·이미지 경로·front matter와 원문 해시를 검사합니다. 이어서 전체
npm run check를 실행하고 번역 diff와 로컬 확인 URL을 알려줍니다.
이 과정은 번역 파일을 커밋 직전 상태까지 준비하지만 git add, 커밋, push,
배포는 실행하지 않습니다. 안내받은 한국어·영어·일본어 페이지를 로컬에서 직접
읽어본 다음 사용자가 커밋합니다. 기존 번역 파일은 사용자가 갱신을 명시적으로
요청하지 않는 한 덮어쓰지 않습니다.
수동으로 안전 검사를 실행할 때는 먼저 원문 해시를 얻고, 번역 후 그 값을 다시 전달합니다.
npm run translate:snapshot -- content/posts/.../ja.md
npm run translate:verify -- content/posts/.../ja.md --source-hash <출력된 해시>
npm run check각 언어 페이지는 자기 URL을 canonical로 사용하고 html lang, Open Graph,
Twitter, JSON-LD inLanguage, Pagefind 색인 언어를 해당 글에 맞게 생성합니다.
같은 글의 페이지들은 hreflang과 x-default로 서로 연결됩니다. 사이트맵은
Astro가 생성된 언어별 URL을 자동으로 포함합니다.
기본 홈페이지·카테고리·아카이브와 /rss.xml은 기존 동작을 보존하기 위해
한국어 글만 표시합니다. 번역 페이지는 언어별 Pagefind 색인에 포함됩니다.
Giscus는 기존 댓글을 보존하기 위해 pathname 매핑을 유지하므로 번역 URL의
댓글은 한국어 원문과 분리됩니다.
지원 언어를 늘릴 때는 config/site.yaml의 languages에 언어 코드, 표시 이름,
locale, OG locale, URL prefix를 추가합니다. 라우트와 콘텐츠 스키마는 이 설정을
공통으로 사용합니다. 기본 언어만 index.md를 사용하고 다른 언어 파일명은 언어
코드와 같아야 합니다.
npm run check다음을 한 번에 검사합니다.
- front matter, 언어별 중복 slug와 지원하지 않는 lang
- 언어 파일명, 번역본 중복, translationKey·slug와 draft 상태 불일치
- 로컬 이미지 누락
- Astro/TypeScript
- 프로덕션 빌드와 Pagefind 색인
- 생성된 내부 링크, 언어별 페이지와 상호 hreflang
- canonical, html lang과 기본 Open Graph 이미지
- RSS, sitemap, search, archive, 404와 게시물 페이지
- 공개 게시물 URL 기준선 114개
최초 한 번 GitHub 저장소의 Settings → Pages → Build and deployment →
Source를 GitHub Actions로 설정합니다. 그다음 config/site.yaml의
site.url이 실제 공개 주소인지 확인하고 main에 push합니다.
.github/workflows/deploy.yml은 다음을 자동으로 수행합니다.
- pull request: 읽기 전용 권한으로
npm ci와 전체npm run check mainpush 또는 수동 실행: 같은 검증 후 Pages artifact 생성과 배포- deploy job만
pages: write와id-token: write사용 - 모든 외부 GitHub Action을 전체 commit SHA로 고정
npm run publish
git add .
git commit -m "feat: rebuild blog with Astro"
git push origin mainnpm run publish는 실제 push를 실행하지 않고 검사와 명령 안내만 합니다.
배포가 시작되지 않으면 Pages Source가 GitHub Actions인지, Actions 탭에서
workflow 실행이 허용됐는지, 기본 브랜치가 main인지 확인합니다. URL이 잘못된
경우 config/site.yaml만 고친 뒤 다시 push합니다.
config/site.yaml의site.url을https://example.com처럼 실제 도메인으로 변경하고 push합니다.- GitHub 저장소의 Settings → Pages → Custom domain에 같은 도메인을 저장합니다.
- DNS 제공자에서 subdomain은
<username>.github.io를 향하는CNAME, apex domain은 GitHub가 안내하는A/AAAA또는ALIAS/ANAME레코드를 설정합니다. - DNS 적용 후 Enforce HTTPS를 켭니다.
GitHub Actions 방식에서는 저장소의 CNAME 파일이 필요하지 않습니다. 도메인
탈취를 막기 위해 계정의 Pages 설정에서 도메인을 검증하고 wildcard DNS는
사용하지 않는 것을 권장합니다. 자세한 절차는
GitHub Pages custom domain 문서를
따릅니다.
config/*.yaml오류: 메시지에 표시된 파일과 필드의 들여쓰기·필수값을 확인site.url오류:https://를 포함한 전체 공개 URL 사용public asset does not exist:config/site.yaml의 이미지 경로와public/images/의 실제 파일명 일치 여부 확인- 게시물 날짜 오류:
publishedAt: 'YYYY-MM-DD'형식 사용 - 중복 slug 오류: 같은 언어의 게시물마다 고유한
slug사용 - 프로젝트 URL 오류:
repository와demo에http://또는https://사용 - 빈 프로젝트 경고:
content/projects/가 비어 있고 projects 기능이 꺼진 운영 블로그에서는 정상이며 build 실패가 아님
문제를 고친 뒤 npm run check를 다시 실행하면 설정, 콘텐츠, 타입, production
build, 링크와 기능 플래그를 한 번에 재검증합니다.
config/에는 브라우저에 공개되어도 되는 값만 둡니다. Analytics 측정 ID,
Search Console verification 문자열, Giscus repository/category ID는 공개
클라이언트 설정입니다. API token, 비밀번호, private key 같은 비밀값은 절대
config/, Markdown 또는 .env.example에 실제 값으로 커밋하지 않습니다.
향후 비밀값이 필요한 자동화를 추가할 때는 GitHub Actions Secrets와 환경변수를
사용합니다.
content/posts/<ordered-group>/<category>/<slug>/— Markdown 글과 글 전용 이미지content/projects/<slug>/— 프로젝트 Markdown과 프로젝트 전용 이미지config/— 사이트, 내비게이션, 소셜 링크와 기능 설정public/images/— 프로필, favicon과 기본 OG 이미지src/components/— 공통 UIsrc/layouts/— HTML/SEO 레이아웃src/pages/— 정적 페이지와 동적 경로src/styles/global.css— 디자인 토큰과 반응형 스타일scripts/— 새 글·번역·검증·배포 안내tests/baselines/published-post-routes.txt— 공개 게시물 URL 보존 기준선
레이아웃이나 기능 자체를 바꾸려는 고급 사용자만 src/와 내부 Astro 설정을
수정합니다. 일반적인 사이트 운영에는 해당 변경이 필요하지 않습니다.
현재 개인 블로그 저장소의 코드와 콘텐츠에는 별도 재사용 라이선스가 지정되어
있지 않습니다. 공개용 astro_blog_template 저장소는 MIT 라이선스를 사용하며,
이 개인 블로그의 실제 글과 이미지는 템플릿에 포함하지 않습니다.