개인 학습 기록과 지식 공유를 위한 기술 블로그 레포지토리입니다.
Next.js와 Keystatic을 기반으로 콘텐츠 관리 효율성과 구현 제어 범위를 함께 확보하는 방향으로 구성했습니다.
| 구분 | 기술 스택 |
|---|---|
| Framework | Next.js (App Router), React |
| Language | TypeScript |
| CMS | Keystatic |
| Content | MDX, Mermaid |
| Interaction | giscus |
| Metadata | RSS, Sitemap, Open Graph |
.
├── public
├── src
│ ├── app # App Router 페이지, RSS, sitemap, OG 이미지
│ ├── components # UI와 MDX 렌더링 컴포넌트
│ ├── contents # 게시글, 메모, 태그, 카테고리 원본 데이터
│ ├── keystatic # 콘텐츠 편집기와 컬렉션 설정
│ ├── libs # 콘텐츠 조회, MDX, Mermaid 관련 로직
│ └── utils # 공통 유틸 함수
├── keystatic.config.ts
└── package.json
콘텐츠는 성격에 따라 두 계층으로 나뉘어 관리됩니다.
- 게시글 (Posts): 비교적 긴 호흡의 기술 문서와 정리 글. 카테고리 기반으로 분류합니다.
- 메모 (Memos): 짧은 기록, 문제 해결 메모, 코드 스니펫. 태그 기반으로 탐색합니다.
- 메타 데이터: 태그, 카테고리, 발행일, OG 이미지, RSS, sitemap 정보를 함께 관리합니다.
- Admin UI: Keystatic을 통해 로컬과 원격 환경 모두에서 GUI 기반으로 콘텐츠를 다룰 수 있습니다.
- 하이브리드 탐색 구조: 게시글은 카테고리 기준, 메모는 다중 태그 기준으로 탐색할 수 있도록 분리했습니다.
- MDX 확장 렌더링: Mermaid와 커스텀 MDX 컴포넌트를 지원해 글 안에서 표현 범위를 넓혔습니다.
- 커스텀 주석 파서와 에디터 연동: 코드 블록 주석 정보를 별도 구조로 파싱하고, 이를 Keystatic 코드 블록 에디터와 연결해 편집 흐름 안에서 다룰 수 있게 구성했습니다.
- 콘텐츠 메타 자동화: RSS, sitemap, Open Graph 이미지와 같은 배포 메타 정보를 코드 레벨에서 함께 생성합니다.
- 콘텐츠 관리 흐름 분리: 공개 페이지와 별도로 Keystatic 관리 화면 및 preview 흐름을 구성했습니다.
코드 블록 안에서는 별도 주석 문법으로 라인 강조, wrapper, 인라인 렌더를 지정할 수 있습니다.
언어에 따라 annotation 주석 prefix가 달라집니다.
| 언어 | 주석 문법 |
|---|---|
ts, tsx, js, jsx 등 기본값 |
// @... |
python, yaml, toml, bash |
# @... |
sql |
-- @... |
postcss |
/* @... */ |
@line <name> {start-end} attr="value"
@char <name> {start-end} attr="value"
@document <name> {start-end} attr="value"@line: 줄 단위 annotation@char: 한 줄 안의 문자 범위 annotation@document: 코드 블록 전체 기준 absolute range annotation{start-end}는 닫힌 구간입니다. 예를 들어{0-4}는 내부적으로0부터4까지 포함합니다.
// @line plus
const added = 1
// @line minus
const removed = 2
// @line highlight {0-1}
const first = 1
const second = 2plus: 추가된 줄처럼 초록 강조minus: 삭제된 줄처럼 빨강 강조highlight: 중립 강조warning,error: 물결 밑줄 강조
연속 구간은 시작/종료 marker로도 쓸 수 있습니다.
// @line collapse
const first = 1
const second = 2
// @line collapse end// @char Tooltip {6-10} content="설명"
const value = hello// @document fold {0-4}
hello worldTooltip: 지정 범위를 툴팁으로 감쌉니다.fold: 지정 범위를 접힘 형태로 렌더링합니다.strong,em,del,u도 document/inline 범위에서 사용할 수 있습니다.
쉽게 말하면, 코드 안에 “이 줄은 강조해”, “이 글자는 툴팁 붙여”, “이 구간은 접어”를 주석으로 적는 방식입니다.
숫자 범위 대신 정규표현식으로 범위를 지정할 수도 있습니다.
// @char fold {re:/foo/g}
const value = "foo foo"// @document fold {re:/foo/}
foo bar foo규칙은 이렇습니다.
@char ... {re:/.../flags}: 바로 아래 한 줄에서만 매치를 찾습니다.@document ... {re:/.../flags}: 코드 블록 전체에서 매치를 찾습니다.g플래그가 없어도 내부에서 전체 매치를 모두 수집합니다.- 줄바꿈을 가로지르는 정규식도 사용할 수 있습니다.
예를 들면 JSX의 className 값만 접고 싶을 때도 이런 식으로 쓸 수 있습니다.
// @document fold {re:/(?<=className\s*=\s*")[^"]+(?=")/g}
const a = <div className="alpha beta" />
const b = <span className="gamma" />차트는 MDX에서 ```chart 코드펜스로 작성합니다.
v1에서는 bar, line, area, pie만 지원합니다.
chart bar
x month
show-values
hide-grid
hide-y-axis
y-range 0 2400
series views | 조회수 | chart-1
series likes | 좋아요 | chart-2
data
month | views | likes
Jan | 1200 | 180
Feb | 1680 | 220
Mar | 1940 | 260규칙은 이렇습니다.
- 첫 줄은
chart <type> x <field>는 필수show-values를 넣으면 각 데이터 값이 차트 위에 표시됩니다.hide-grid를 넣으면 배경 격자선을 숨깁니다.hide-y-axis를 넣으면 y축 숫자와 축 표시를 숨깁니다.y-range <min> <max>를 넣으면 y축 범위를 고정합니다.series <key> | <label> | <theme-token>은 1개 이상 필요- 빈 줄 뒤에
data - 다음 줄은 테이블 헤더
- 데이터 값은
|로 구분
색상 토큰은 chart-1부터 chart-5까지만 허용합니다.
쉽게 말하면, 기본 문법은 그대로 두고 필요할 때만 show-values, hide-grid, hide-y-axis, y-range 같은 줄을 추가해서 차트 모양을 조절하는 방식입니다.
chart pie
label browser
value visitors
data
browser | visitors
Chrome | 412
Safari | 248
Edge | 132규칙은 이렇습니다.
label <field>는 항목 이름 필드value <field>는 숫자 값 필드- 색상은 행 순서대로
chart-1~chart-5가 자동 배정 show-values,hide-grid,hide-y-axis,y-range는 pie 차트에서 지원하지 않습니다.
문법이 잘못되면 차트가 조용히 깨지지 않고, 본문과 에디터 모두에서 오류 카드가 표시됩니다.
예를 들어 이런 경우 에러가 납니다.
chart bar
x month
series views | 조회수 | chart-1
data
month | views
Jan | nope- 지원하지 않는 차트 타입
- 필수 헤더 누락
series와data헤더 불일치- 숫자 필드에 숫자가 아닌 값 입력
- 허용되지 않은 색상 토큰 사용
- pie 차트에서 cartesian 전용 옵션 사용