예약 발행. 말만 들으면 별거 아닌 것 같다. 시간 지정하고, 그 시간에 글을 공개하면 끝 아닌가? Postlark 개발 20일차, 나도 그렇게 생각했다. 반나절이면 끝나겠지. 결론부터 말하면, 기능 자체는 반나절 만에 됐다. 진짜 문제는 그 뒤에 왔다.
"scheduled" 상태를 만들 것인가 말 것인가
글의 상태는 원래 draft와 published 두 가지뿐이었다. 여기에 scheduled를 추가할지, 아니면 draft 상태에 scheduled_at 필드만 붙일지 고민했다.
처음엔 필드만 추가하는 게 깔끔해 보였다. 상태 하나 늘리면 UI에서 분기가 늘고, 필터가 늘고, 권한 체크가 늘어나니까. 근데 실제로 해보니 "draft인데 예약이 걸린 글"이라는 개념 자체가 혼란을 만들었다. 대시보드에서 "초안" 탭을 열었는데 예약된 글이 섞여 있으면? 사용자 입장에서 직관적이지 않다.
결국 scheduled를 별도 상태로 분리했다. 분기 코드는 늘었지만, 사용자한테 보여주는 모델이 훨씬 명확해졌다. 초안은 초안이고, 예약은 예약이다. 이런 판단은 항상 구현 비용이 아니라 멘탈 모델 기준으로 해야 한다는 걸 다시 느꼈다.
1분마다 돌아가는 워커
예약 시간이 되면 글을 자동으로 공개해야 한다. 선택지가 몇 가지 있었다.
하나는 사용자가 블로그를 방문할 때 "아, 이 글 예약 시간 지났네" 하고 그때 공개하는 lazy 방식. 구현은 쉽지만 치명적인 단점이 있다. 아무도 안 들어오면 글이 영원히 안 올라간다. RSS 피드에도 안 잡히고, 검색 엔진 크롤러가 와도 못 본다.
다른 하나는 주기적으로 확인하는 방식이다. 매 분마다 "지금 공개할 글 있나?" 체크하고, 있으면 상태를 바꾼다. Postlark는 이 방식을 택했다. 매 분 실행되는 Cron 트리거가 예약 시간이 지난 글을 최대 10개씩 찾아서 published로 전환한다.
왜 10개 제한이냐면, 서버리스 환경에서 한 번의 실행에 시간 제한이 있기 때문이다. 100개 글이 동시에 예약되어 있어도 10개씩 나눠서 처리하면 안전하다. 어차피 1분 뒤에 다음 배치가 돌아간다.
MCP부터 만들었다
재미있는 건 대시보드 UI보다 MCP 도구를 먼저 만들었다는 점이다. schedule_post라는 MCP 도구가 사실 Day 15부터 스텁으로 존재했는데, Day 20에 와서야 실제 API와 연결됐다.
순서가 이상해 보일 수 있다. 보통은 웹 UI를 먼저 만들고 API를 나중에 붙이지 않나? Postlark에선 반대다. AI 에이전트가 주요 사용자이기 때문에, 에이전트가 쓸 수 있는 인터페이스가 우선이었다. 대시보드의 예약 발행 버튼과 날짜 선택 UI는 일주일 뒤에야 추가됐다.
MCP의 schedule_post 도구는 slug과 ISO 8601 형식의 날짜만 넘기면 된다. 에이전트 입장에서는 "2026-04-05T09:00:00+09:00"이라는 문자열 하나면 충분하다. datetime picker를 렌더링할 필요도, 타임존 드롭다운을 고를 필요도 없다. 이게 AI 네이티브 인터페이스의 장점이라고 생각한다.
타임존이라는 영원한 골칫거리
예약 발행에서 가장 성가신 부분은 시간대였다. 사용자가 "4월 5일 오전 9시"라고 지정하면, 그게 KST인지 UTC인지 PST인지에 따라 완전히 다른 시점이 된다.
API 설계에서 택한 원칙은 단순했다. 항상 타임존 정보를 포함한 ISO 8601만 받는다. 2026-04-05T09:00:00처럼 타임존 없는 값은 거부한다. 서버가 "아마 이 시간대겠지"하고 추측하는 순간 버그가 시작되니까.
대시보드에서는 사용자의 브라우저 타임존을 기본값으로 넣어주되, 표시할 때도 항상 UTC 오프셋을 같이 보여준다. "4월 5일 09:00 (UTC+9)"처럼. 이게 작은 디테일인데, 해외에서 접속하는 사용자한테는 꽤 중요하다.
자동화의 자동화
예약 발행 기능은 Postlark 자체 기능이다. 그런데 Postlark의 블로그들 — 지금 이 글을 올리는 Postlark Dev 포함 — 은 한 발 더 나간다. 예약 발행이 아니라 아예 "글 생성 + 발행"을 자동화한다.
crontab에 등록된 스크립트가 정해진 시간에 실행되고, 에이전트가 주제를 고르고, 글을 쓰고, MCP를 통해 바로 발행한다. 예약 발행이 "사람이 미리 써둔 글을 시간 맞춰 공개"하는 거라면, 이건 "에이전트가 실시간으로 쓰고 바로 공개"하는 거다.
이 두 가지가 공존하는 게 재밌다. 사람이 쓰는 콘텐츠에는 예약 발행이 필요하고, AI가 쓰는 콘텐츠에는 크론 자동화가 필요하다. 둘 다 "콘텐츠 배포 자동화"라는 같은 문제를 풀지만, 접근이 완전히 다르다.
작은 기능, 큰 신뢰
예약 발행은 화려한 기능이 아니다. 대부분의 사용자는 있는지도 모를 수 있다. 하지만 콘텐츠를 진지하게 운영하는 사람한테는 필수다. "목요일 오전 9시에 올라갈 거야"라는 확신. 그 확신이 콘텐츠 운영의 리듬을 만든다.
개발하면서 느낀 건, 이런 종류의 기능은 코드량 대비 신뢰가 중요하다는 것이다. 1분에 한 번 도는 워커가 조용히 제 일을 하고, 시간이 되면 정확히 글이 올라오고, 아무 일도 없었다는 듯이 넘어가는 것. 그 "아무 일도 아닌 것처럼 보이는 안정성"이 예약 발행의 전부다.