2026-07-13 · 바이브코딩

AI 블로그 자동화에서 멱등 발행 루틴을 지키는 법

Futory의 Next.js Markdown 운영에서 같은 날 크론이 여러 번 실행되어도 글은 하나만 만들고, 검증과 재시작은 안전하게 이어 가는 멱등 발행 루틴을 정리했습니다.

요약

Futory처럼 평일마다 AI가 Markdown 글을 만들고 Next.js 빌드, PM2 재시작, 공개 검증까지 이어 가는 블로그에서는 멱등성이 매우 중요합니다. 멱등 발행이란 같은 작업이 여러 번 실행되어도 최종 결과가 흔들리지 않는다는 뜻입니다. 크론이 하루에 여러 번 깨어나고, 네트워크나 빌드 상황 때문에 재시도가 생겨도 오늘의 글은 하나만 존재해야 합니다.

좋은 멱등 루틴은 복잡한 잠금 시스템보다 먼저 단순한 기준을 세웁니다. KST 날짜를 기준으로 오늘 글이 이미 있는지 frontmatter와 파일명에서 확인하고, 없을 때만 새 파일을 만듭니다. 파일을 만들기 전에는 posts 디렉터리를 백업하고, 만든 뒤에는 콘텐츠 테스트와 테마 테스트, 빌드, 산출물 확인, PM2 재시작, 공개 URL 검증을 같은 순서로 진행합니다. 이 흐름이 반복되면 자동화는 빠르면서도 중복에 강해집니다.

멱등성이 발행 자동화의 기본인 이유

블로그 발행 자동화는 한 번만 실행된다고 가정하면 쉽게 만들 수 있습니다. 하지만 실제 운영에서는 크론이 여러 시간대에 실행되고, 선택된 시간에만 발행하며, 실패 후 같은 날 다시 실행될 수 있습니다. 이때 멱등성이 없으면 같은 날짜 글이 둘 이상 생기거나, 이미 공개된 글을 다시 빌드하면서 원인을 알기 어려운 상태가 됩니다.

오늘의 기준점을 하나로 만든다

Futory의 기준점은 date: "YYYY-MM-DD"가 들어간 Markdown 파일입니다. 오늘 날짜의 글이 발견되면 자동화는 새 글을 쓰지 않고 SKIP해야 합니다. 이 규칙은 단순하지만 강력합니다. 파일이 이미 있다는 것은 오늘의 원천 콘텐츠가 정해졌다는 뜻이고, 이후 문제는 새 글 작성이 아니라 빌드, 런타임, 캐시, 공개 검증의 문제로 나누어 봐야 합니다.

재시도를 안전하게 만든다

재시도는 자동화의 정상적인 일부입니다. SSH 재시작이 잠깐 실패하거나 공개 사이트가 캐시 때문에 늦게 반영될 수 있습니다. 하지만 재시도할 때마다 새 slug를 만들면 운영자는 어떤 글이 진짜 오늘 글인지 판단하기 어려워집니다. 멱등 루틴은 재시도가 글 생성을 반복하지 않도록 막고, 이미 정해진 파일과 slug를 기준으로 다음 단계를 다시 확인하게 만듭니다.

Futory에 맞는 멱등 발행 순서

Futory의 콘텐츠 원천은 /opt/futory/content/posts입니다. 이 디렉터리에 새 파일 하나를 추가하는 일이 발행의 시작이고, 기존 파일을 건드리지 않는 것이 안전한 기본값입니다. 운영자는 매일 같은 순서가 지켜졌는지만 확인하면 됩니다.

1. KST 날짜와 선택 시간을 먼저 확인한다

UTC 기준 크론이 실행되더라도 글의 날짜는 한국 독자를 기준으로 KST를 사용합니다. 오늘이 평일인지 확인하고, deterministic random seed로 선택된 14시부터 18시 사이의 한 시간인지 확인합니다. 선택 시간이 아니면 아무 파일도 만들지 않습니다. 이 단계는 발행 빈도를 제어하고, 여러 실행 중 하나만 실제 작업을 하게 만드는 첫 번째 안전장치입니다.

2. 오늘 날짜 중복을 검사한다

선택 시간이 맞더라도 바로 글을 쓰면 안 됩니다. 먼저 content/posts 안에서 오늘 날짜가 frontmatter나 파일명에 있는지 확인합니다. 발견되면 기존 파일명과 제목을 보고하고 멈춥니다. 이 중복 검사는 빌드 성공 여부와 별개로 작동해야 합니다. 그래야 앞선 실행이 빌드에서 실패했더라도 오늘의 원천 파일을 또 만들지 않습니다.

3. 백업 후 새 파일 하나만 추가한다

중복이 없을 때만 posts 디렉터리를 timestamp가 붙은 tar.gz로 백업합니다. 그다음 새 Markdown 파일을 하나 생성합니다. 기존 글을 수정하지 않는 이유는 실패 범위를 작게 유지하기 위해서입니다. 새 글에 문제가 있으면 새 파일과 이번 실행 로그만 보면 되고, 오래된 글이나 목록 구조를 의심할 필요가 줄어듭니다.

검증 단계는 같은 입력을 바라봐야 한다

파일을 만든 뒤에는 검증 순서가 흔들리지 않아야 합니다. 콘텐츠 테스트는 frontmatter, 제목, 날짜, 본문 구조가 규칙을 만족하는지 확인합니다. 테마 테스트는 사이트가 기대하는 카테고리와 렌더링 조건을 확인합니다. 빌드는 이 두 테스트를 통과한 동일한 파일 상태를 입력으로 사용해야 합니다.

빌드 산출물 확인의 의미

npm run build가 성공해도 새 slug가 산출물에 포함되었는지 확인하는 것이 좋습니다. 산출물 확인은 “파일은 있었지만 실제 공개 경로에는 들어가지 않았다” 같은 애매한 상태를 줄입니다. .next 안에서 slug가 발견되면 PM2 재시작은 검증된 빌드 결과를 런타임에 반영하는 단계가 됩니다.

공개 검증은 상세와 목록을 나눈다

상세 URL /posts/<slug>가 200을 반환하는 것과 홈 또는 /posts 목록에 보이는 것은 별도 신호입니다. 상세가 200이면 글 자체의 공개 가능성은 높습니다. 목록에 slug나 날짜가 보이면 독자가 탐색 경로에서도 글을 찾을 수 있습니다. 캐시 우회 쿼리와 Cache-Control: no-cache를 사용해 확인하면 오래된 응답 때문에 잘못 판단할 가능성이 줄어듭니다.

운영 보고를 멱등하게 쓰는 법

멱등 발행은 실행 자체뿐 아니라 보고 방식에도 필요합니다. 성공 보고에는 제목, 날짜, slug, 파일 경로, 백업 경로, 테스트와 빌드 상태, PM2 재시작 상태, 공개 검증 결과가 들어가야 합니다. 실패 보고에는 첫 실패 단계와 오류를 정확히 남기고, 뒤 단계는 실행하지 않았다고 써야 합니다.

다음 실행이 같은 결론에 도달하게 한다

보고를 읽은 다음 실행이나 운영자가 같은 판단을 할 수 있어야 합니다. 오늘 글이 이미 있으면 왜 SKIP했는지, 새 글을 만들었다면 어떤 URL이 기준인지, 공개 목록이 늦다면 상세는 정상인지가 드러나야 합니다. 이런 보고는 자동화의 신뢰를 높이고 불필요한 수동 개입을 줄입니다.

자주 묻는 질문

멱등성을 위해 별도 lock 파일이 꼭 필요한가요?

반드시 필요하지는 않습니다. Futory처럼 하루에 하나의 글만 만드는 구조에서는 KST 날짜 frontmatter와 파일명 검사가 가장 단순한 잠금 역할을 할 수 있습니다. 다만 여러 프로세스가 완전히 동시에 같은 디렉터리에 쓸 가능성이 크다면 원자적 파일 생성이나 별도 lock을 추가로 고려할 수 있습니다.

빌드가 실패한 파일도 중복 검사 대상인가요?

네. 오늘 날짜 파일이 만들어졌다면 그것이 오늘의 원천 기준입니다. 빌드가 실패했다고 새 글을 하나 더 쓰면 중복이 생깁니다. 실패한 파일을 기준으로 오류를 고치고 테스트부터 다시 진행하는 편이 안전합니다.

공개 목록에 늦게 보이면 새 글을 다시 만들면 되나요?

아닙니다. 상세 URL과 빌드 산출물이 정상이라면 새 글 생성 문제가 아니라 런타임 반영이나 캐시 문제일 가능성이 큽니다. 이때는 PM2 재시작 결과, 목록 페이지 응답, 캐시 우회 요청을 확인해야 합니다.

결론

AI 블로그 자동화에서 멱등성은 중복을 막는 기술 규칙이자 운영자가 안심하고 재시도할 수 있게 만드는 약속입니다. Futory의 Next.js Markdown 발행 흐름에서는 KST 날짜와 선택 시간을 먼저 확인하고, 오늘 날짜 글이 없을 때만 백업 후 새 파일 하나를 추가하며, 테스트와 빌드, 산출물, PM2 재시작, 공개 검증을 같은 순서로 진행하는 것이 핵심입니다.

바이브코딩은 빠르게 만들고 개선하는 힘을 주지만, 반복 발행에서는 같은 실행을 여러 번 해도 결과가 흔들리지 않아야 합니다. 오늘의 기준 파일과 slug가 하나로 유지될 때 자동화는 조용해지고, 재시도는 안전해지며, Futory의 매일 발행 루틴은 더 신뢰할 수 있는 운영 시스템으로 자리 잡습니다.