Build Log

글 한 편은 어떻게 웹페이지가 되는가 — 블로그의 구조를 만들다

N-Layer Build Log의 글 한 편이 MDX 파일에서 실제 웹페이지가 되기까지의 구조를 살펴본다. frontmatter, 이미지, 컴포넌트, 빌드와 draft 처리까지 비개발자의 관점에서 정리했다.

· N-Layer
블로그 자동화MDX빌드

1편 — 블로그를 직접 만들기로 했다 — 자동화의 시작에서 마지막에 남긴 질문은 글을 컴퓨터가 다룰 수 있는 형태로 만드는 일이었다.

사람에게 글은 문장과 사진의 묶음이다. 제목을 보고, 본문을 읽고, 사진과 표를 살펴보면 된다. 그런데 컴퓨터에게는 무엇이 제목이고 무엇이 날짜인지 알려 줘야 한다. 사진이 어느 파일인지, 이 글을 공개해도 되는지도 구분해야 한다.

블로그 서비스를 쓸 때는 이런 구분이 편집 화면 뒤에 숨어 있었다. 직접 만든 블로그에서는 그 규칙을 내가 정해야 했다.

이번에는 ‘블로그 자동화 만들기’의 두 번째 기록으로, 내가 쓴 글 한 편이 어떻게 n-layer.com/blog/... 주소를 가진 웹페이지가 되는지 안쪽을 살펴보려 한다.

왼쪽은 1편의 실제 로컬 웹페이지 화면, 오른쪽은 동일 글의 실제 MDX 원문 앞부분이다. 원문에는 제목, slug, 날짜, 설명, 태그, 공개 상태와 본문이 들어 있다.
독자에게는 하나의 글이지만, 내부에서는 제목·날짜·본문·이미지·상태가 구조화된 파일로 관리된다. 왼쪽은 로컬 렌더링, 오른쪽은 같은 글 파일의 실제 원문 발췌다.

글도 컴퓨터에게는 구조가 필요하다

글의 본문이 책의 내용이라면, frontmatter는 표지 안쪽에 붙어 있는 관리 카드에 가깝다. 제목, 날짜, 주소, 공개 여부를 본문과 따로 적어 두는 것이다.

N-Layer에서는 MDX 파일의 맨 앞, --- 사이에 그 카드를 넣는다. 1편의 실제 정보 중 일부를 꺼내면 다음과 같다.

---
title: "블로그를 직접 만들기로 했다 — 자동화의 시작"
slug: "blog-automation-01-start"
date: "2026-10-01"
description: "여러 프로젝트의 결과뿐 아니라 그 과정까지 남기기 위해 N-Layer Build Log를 만들기 시작했다. 블로그 자동화를 시작하며 사람이 해야 할 일과 반복 작업을 어떻게 나누었는지 기록한다."
published: true
---

title은 글의 이름, description은 짧은 소개다. date는 목록에 표시하고 순서를 정할 때 쓰는 날짜다. slug는 주소 끝에 붙는 이름이다. 1편의 주소에 blog-automation-01-start가 들어가는 이유도 여기에 있다.

published는 공개용 결과물에 넣을지를 정한다. 다만 이 값을 바꾼다고 지금 운영 중인 사이트가 바로 바뀌지는 않는다. 새로 빌드하고 배포해야 웹에 반영된다.

현재 관리 카드에는 카테고리, 태그와 대표 이미지 정보도 있다. 시리즈 번호를 위한 별도 필드는 아직 없어서, 1편과 2편의 연결은 본문의 문장과 링크로 표현했다.

구분사람이 보는 역할시스템에서 하는 역할
제목글의 이름목록·상세 페이지 제목
설명글의 요약목록 요약·페이지 메타 설명
날짜글에 표시된 날짜날짜 내림차순 정렬·표시
slug주소에서 확인할 수 있는 글 이름글의 URL 생성
공개 상태공개된 글만 읽게 하는 구분공개용 빌드에 포함할지 결정
본문실제 읽는 내용HTML 페이지의 콘텐츠

한 문서에 모두 들어 있어도 역할은 다르다. 이 구분이 있으면 글 목록을 만들 때 본문 전체를 읽으며 제목을 추측할 필요가 없다.

왜 Markdown이 아니라 MDX였을까

워드 파일 하나에 제목, 본문과 사진 위치가 함께 들어 있는 것처럼, MDX 파일에도 글과 웹페이지를 만드는 데 필요한 표시를 함께 적는다. 다만 여기서는 사진 자체를 문서 안에 붙이는 대신 별도 이미지 파일의 위치를 적어 둔다.

Markdown은 글의 모양을 간단한 기호로 표현하는 방식이다. 제목 앞에는 ##를 붙이고, 목록과 링크, 이미지, 코드도 텍스트로 적을 수 있다. 표는 이 블로그에 연결한 Markdown 표 지원 기능이 읽어 준다.

MDX는 여기에 미리 준비한 웹 요소를 끼워 넣을 수 있게 한다. 우리 블로그에서는 사진과 설명을 한 묶음으로 보여 주는 BlogImage, 강조할 내용을 담는 Callout이 그런 요소다.

React 컴포넌트라는 말이 낯설다면, 정해진 모양으로 출력해 주는 작은 틀이라고 생각해도 된다. 글에서는 사진 경로나 강조할 문장을 전달하고, 틀은 사이트와 어울리는 모양으로 보여 준다.

지금은 이 두 가지 틀만 등록되어 있다. 아무 코드나 본문에서 실행하도록 열어 둔 것은 아니다. 이 글의 흐름도도 새로운 도표 컴포넌트가 아니라, 기존 BlogImage로 표시하는 SVG 파일이다.

아래는 내 작업을 기준으로 선택지를 정리한 표다. 서비스와 도구마다 기능이 다르고, 작성자의 익숙함에 따라 편의성도 달라진다.

항목MarkdownMDX일반 CMS
글 작성간단한 기호로 작성같은 기호에 컴포넌트 표기 추가보통 편집 화면에서 작성
코드와 함께 관리텍스트 파일로 관리 가능텍스트 파일로 관리 가능저장·내보내기 방식에 따라 다름
Git 버전 관리파일의 변경 이력 관리 가능파일의 변경 이력 관리 가능서비스 연동 여부에 따라 다름
커스텀 컴포넌트별도 확장 필요등록된 컴포넌트 사용 가능서비스·플러그인에 따라 다름
자동화 연결파일 규칙을 정해 연결파일·컴포넌트 규칙을 정해 연결API·자동화 기능에 따라 다름
비개발자 편의성문법에 익숙해질 필요가 있음문법과 등록된 요소를 알아야 함편집 화면이 편리할 수 있음

MDX가 언제나 더 좋은 선택이라는 뜻은 아니다. 이번에는 글을 파일로 관리하고, 이미 준비한 표시 요소를 같은 방식으로 재사용할 수 있다는 점이 내 목적과 맞았다.

글 속의 사진과 표는 어디에 있을까

글과 사진은 같은 폴더에 모두 넣지 않았다. 글은 content/blog/에, 이미지는 public/blog/ 아래 글 이름과 같은 폴더에 저장한다.

1편의 글 파일은 content/blog/blog-automation-01-start.mdx다. 그 글에 들어간 홈페이지 사진은 public/blog/blog-automation-01-start/n-layer-home.webp에 있다.

본문에서는 그 파일을 웹에서 찾을 수 있는 경로로 가리킨다. 다음은 1편에 실제로 사용한 이미지 표기다.

<BlogImage src="/blog/blog-automation-01-start/n-layer-home.webp" alt="N-Layer 홈페이지의 소개 문구와 떼껄룩 프로젝트 버튼, 상단 Blog 링크가 보이는 실제 화면" caption="하나씩 흩어져 있던 실험과 제작 기록을 한곳에 모으기 위해 N-Layer 안에 Build Log를 만들기 시작했다." width="1425" height="891" />

경로는 ‘어떤 사진인가’를, alt는 사진을 보지 못하는 독자에게 필요한 설명을 알려 준다. caption은 사진 아래에 보이는 문장이다. 크기 정보는 화면에서 사진이 차지할 공간을 정하는 데 도움을 준다.

표는 별도 사진 파일이 아니다. 글 안에 줄과 칸을 텍스트로 적으면, 빌드할 때 웹페이지의 표로 바뀐다. 작은 화면에서는 표 영역 안에서 가로로 스크롤할 수 있다.

이번 글과 연결되는 실제 파일만 추려 보면 다음과 같다. 폴더 이름과 파일 이름은 현재 프로젝트에서 쓰는 이름이다.

실제 블로그 구조: content/blog에는 1편과 2편 MDX, public/blog에는 각 글 이름의 이미지 폴더, scripts/blog.ts에는 읽기·검증·BlogImage·Callout과 HTML 출력, src/blog.css에는 글 스타일이 있다.
글, 이미지, 컴포넌트가 서로 다른 위치에 있어도 일정한 규칙으로 연결되면 하나의 웹페이지가 된다. 이번 시리즈와 관련된 파일만 추린 구조다.

MDX 파일 하나가 웹페이지가 되기까지

독자에게는 ‘글쓰기 → 게시 → 웹페이지’로 보이는 일이, 안에서는 조금 더 나뉜다.

먼저 한 가지를 분명히 해야 한다. 현재 N-Layer는 Next.js 사이트가 아니다. 기존 HTML·CSS 사이트를 유지하면서, Node.js로 실행하는 빌드에 MDX 변환을 붙였다. 그래서 이 글도 Next.js의 페이지 생성 방식이 아니라, 실제로 만든 정적 블로그의 과정을 설명한다.

빌드는 MDX 파일을 읽어 관리 카드와 본문을 나눈다. 제목과 날짜가 규칙에 맞는지, 같은 주소를 쓰는 글이 있는지 확인한다. 본문은 변환 도구가 읽고, BlogImage와 Callout처럼 등록된 틀에 연결한다. 이미지 경로와 파일의 존재도 검사한다.

그다음 공개할 글만 골라 HTML 페이지를 만든다. 그 글의 이미지 폴더를 결과물에 복사하고, 기존 CSS와 함께 브라우저가 읽을 파일들을 준비한다.

여기까지가 빌드다. 그 파일을 웹에서 제공하는 곳에 올리는 배포는 별도 단계다. 배포된 뒤에야 독자는 주소로 접속해 페이지와 이미지를 볼 수 있다.

글 한 편이 웹페이지가 되는 실제 흐름: MDX 작성, Node.js 빌드에서 frontmatter 읽기와 검증, 본문 변환, 이미지·등록된 컴포넌트 확인, 공개 글의 HTML과 이미지 결과물 생성, 별도 배포, 브라우저 표시. 모바일에서도 위에서 아래로 읽는다.
글 한 편이 웹페이지가 되는 과정. 파일을 읽고 결과물을 만드는 빌드와, 그 결과물을 웹에 올리는 배포는 서로 다른 단계다.

빌드는 무엇을 하는가

MDX가 재료라면 빌드는 그 재료를 손님에게 내놓을 수 있는 형태로 조리하는 과정에 가깝다. 글과 이미지를 준비했어도 그대로 웹페이지가 되는 것은 아니다. 정해진 모양으로 바꾸고 필요한 파일을 함께 챙겨야 한다.

우리 블로그의 빌드는 npm run build로 시작한다. 결과물은 dist/라는 폴더에 생긴다. 예를 들어 1편의 웹페이지 파일은 dist/blog/blog-automation-01-start/index.html이다.

글 파일: content/blog/blog-automation-01-start.mdx
결과물: dist/blog/blog-automation-01-start/index.html
웹 주소: /blog/blog-automation-01-start/

이 결과에는 제목과 본문, 표, 이미지 위치가 이미 HTML로 들어 있다. 브라우저는 HTML을 읽고 CSS로 모양을 입히며, 표시된 경로에서 이미지를 불러온다. 글을 보여 주기 위한 별도 React 실행 파일을 독자에게 내려보내지는 않는다.

검사도 역할이 나뉜다. 빌드 안에서는 메타데이터와 본문 변환, 이미지 누락 같은 문제를 확인한다. lint, 타입 검사와 테스트는 별도 명령으로 실행한다. 빌드 하나가 모든 오류를 알아서 찾아 주는 것은 아니다.

그래서 이번 글에서는 단계별 시간을 임의의 숫자로 비교하지 않았다. 구조를 정하는 일, 내용을 쓰는 일, 파일을 연결하는 일, 페이지를 만드는 일, 검증과 공개는 서로 맡은 역할이 다르다. 앞의 흐름도가 그 차이를 설명하는 데 더 알맞았다.

초안은 왜 웹에서 보이지 않을까

작업 폴더에 글 파일이 있다는 것과 웹에 공개됐다는 것은 다르다.

현재 구조에서는 published: false인 글도 내용을 읽고 오류를 검사한다. 다만 공개용 결과물에는 그 글의 페이지와 이미지 폴더를 넣지 않는다. 목록과 sitemap, RSS에서도 빠진다.

그 결과를 배포하면 초안 주소를 직접 열어도 페이지가 없고, 그 초안의 이미지 주소도 접근할 수 없다. 1편을 준비할 때 검증했던 mdx-rendering-check가 이런 초안이다.

로컬에서는 별도의 초안 미리보기를 만들 수 있다. 이때는 공개용 dist/가 아니라 dist-preview/를 사용한다. 검토할 수 있다는 뜻이지, 외부에 게시됐다는 뜻은 아니다.

초안과 공개 준비 상태 비교. published false는 읽기·검증 후 공개 HTML·이미지·목록·피드에서 제외되며, 해당 결과 배포 후 글과 이미지 접근은 404다. published true는 검증 후 결과물과 목록에 포함되고 배포한 뒤 외부에서 접근 가능하다. 상태 변경만으로 즉시 게시되지 않는다.
자동화에서는 글을 만드는 것만큼 ‘언제 공개할 것인가’를 분리하는 것도 중요하다. published 상태 변경 뒤에도 새 결과물의 배포가 필요하다.

구조가 생기면 AI도 일을 맡을 수 있다

자유롭게 쓰는 생각에는 매번 다른 모양이 있다. 그건 그대로 두고 싶다. 다만 컴퓨터에게 넘기는 형식까지 매번 달라지면, 사람도 AI도 무엇을 어디에 넣어야 하는지 다시 판단해야 한다.

제목과 설명, 날짜, 주소 이름, 사진 폴더, 표를 적는 방식, 공개 상태가 정해져 있으면 작업 지시가 구체적이 된다.

“이 형식으로 글을 작성해라.”

“이미지는 이 글의 폴더에 저장해라.”

“초안 상태로 먼저 만들어라.”

“검증과 사람의 게시 결정이 끝난 뒤에만 공개 상태로 바꿔라.”

실제로 게시 안내에도 이런 규칙을 적어 두었다. 이제 AI는 파일 위치와 형식을 매번 추측하기보다 정해진 기준을 따라 초안을 만들 수 있다. 그렇다고 사실 확인과 글의 방향, 게시 결정까지 맡겨진 것은 아니다.

자동화는 자유를 없애는 것이 아니라, 반복되는 부분에 규칙을 만드는 일에 가까웠다.

이제 무엇을 맡길지 생각할 차례다

글을 담는 구조는 생겼다. 다음 질문은 그 안에서 누가 무엇을 하느냐는 것이다.

  • 누가 주제를 정할 것인가?
  • 누가 자료를 찾을 것인가?
  • 누가 초안을 쓸 것인가?
  • AI에게 어디까지 맡길 것인가?
  • 사람은 어디에서 개입해야 하는가?

이전 글: 1편 — 블로그를 직접 만들기로 했다 — 자동화의 시작

다음 글: 3편 — AI에게 글쓰기를 맡기면 블로그가 자동화될까?

글이 웹페이지가 되는 구조를 만들고 나니, 이제야 AI에게 무엇을 맡길 수 있는지가 보이기 시작했다.