홈페이지에 글을 계속 올리려면 잘 쓰는 방법만큼 잘못 올렸을 때의 길도 필요하다. 오타를 고치는 것과 공개하면 안 되는 자료를 빼는 것은 긴급도가 다르다. 이전 문장이 더 나았다고 되돌리고 싶을 때도 있고, AI가 다른 원고를 수정한 사이 내가 오래된 파일을 저장하려는 경우도 있다.
나는 이번 홈페이지의 관리 API에 초안, 발행, 내리기와 수정 기록, 이전 원고 복원을 함께 붙였다. 사용자가 관리자 화면을 직접 다루기보다 AI에게 요청하는 운영을 원했기 때문이다. 관리하는 AI가 글을 올리는 방법만 알고 되돌리는 방법을 모르면 지속 발행의 책임이 남는다. 그래서 내용을 보존하고 공개 상태를 바꾸는 흐름을 따로 만들었다.
나는 삭제보다 먼저 공개를 멈추게 했다
잘못 공개한 글을 내릴 때 원고와 근거까지 없앨 필요는 없다. 이 CMS의 내리기는 저장된 내용을 지우지 않고 공개 상태를 withdrawn으로 바꾼다. 관리자에서는 원고를 읽고 미리볼 수 있지만 방문자가 여는 한영 주소는 공개 글로 응답하지 않는다.
실제 검사에서는 글을 내린 뒤 한국어와 영어 주소가 404가 되고, 모듈 목록과 사이트맵·RSS에서 빠지는 것을 확인했다. 같은 글의 정적 index.html 형태 주소로 돌아 들어오는 경우도 확인했다. 목록에서 링크 하나를 지우는 것으로 끝내지 않고, 직접 주소와 공개 파생 목록을 같이 확인한 이유다.
복원은 원고를 가져오는 일이며 공개 승인은 별도다
이전 원고를 복원하면 당시 내용이 현재 내용으로 돌아온다. 하지만 그 원고가 예전에 공개됐다는 이유로 지금도 공개해도 된다는 것은 아니다. 그 사이 연락 방식이 바뀌었거나 공개 범위가 좁아졌을 수 있다. 오래된 글에 현재 금지한 정보가 있다면 복원 단계에서도 걸러야 한다.
현재 API는 복원할 스냅샷을 해당 글의 수정 기록에서 찾고 내용을 검사한 뒤 새 초안으로 저장한다. 실제 검사에서도 복원 결과는 draft였고 한국어 원고는 선택한 이전 내용과 같았다. 나는 초안 미리보기와 공개 범위 검토를 거친 다음 발행을 따로 실행하도록 남겼다. 복원 버튼이 곧 공개 버튼이 되지 않게 한 것이다.
나는 되돌려도 버전 번호를 과거로 돌리지 않았다
원고의 내용이 이전 것으로 돌아가더라도 그것은 지금 수행한 새로운 변경이다. 버전 번호까지 옛 번호로 되돌리면 다른 작업자가 어떤 변경 뒤에 있는지 구별하기 어렵다. 이 CMS는 변경 전 스냅샷을 기록하고 현재 버전을 하나씩 증가시킨다.
저장·내리기·복원·발행 요청에는 검토한 현재 버전을 함께 보내도록 했다. 코드에서는 그 버전과 실제 저장된 버전이 같을 때만 수정 기록과 새 내용을 반영한다. 실제 검사에서 맞지 않는 버전으로 저장하려는 요청은 409로 거부됐다. 여러 편집자가 서로의 글을 덮어쓰지 않도록 현재 상태를 다시 읽는 경계다.
충돌 뒤에는 새 번호만 가져와 덮어쓰지 않는다
버전 충돌은 저장 버튼을 한 번 더 누르라는 신호가 아니다. 내가 읽은 뒤 다른 변경이 있었다는 뜻이다. 현재 원고와 내가 수정한 원고를 비교해야 한다. 빠진 문단을 복구할지, 새 문장을 유지할지, 다른 편집의 목적을 보존할지 판단이 필요하다.
그래서 내 운영 지침에는 새 버전 번호만 가져와 같은 파일을 무조건 다시 저장하지 않도록 적었다. 원고를 읽고 내용 차이를 검토한 뒤 합친 결과를 저장한다. 자동으로 재시도할 수 있는 통신 오류와, 내용 판단이 필요한 충돌을 같은 처리로 만들지 않는다. AI가 관리한다는 이유로 이 검토가 없어져서는 안 된다.
발행된 글의 저장 방식도 분명하게 남겼다
현재 CMS에서 이미 발행된 원고를 수정 저장하면 공개 내용도 바로 바뀐다. 저장이 항상 비공개 초안이라는 가정을 하면 검토 중인 문장을 방문자가 볼 수 있다. 나는 이 동작을 관리 지침에 적고, 비공개 편집이 필요하면 먼저 내리거나 별도 초안으로 작업하도록 구별했다.
발행 중인 글을 저장할 때는 검토 여부와 비공개 근거도 요구한다. 다만 reviewed 값 자체가 검토를 대신하지 않는다. 실제로 원본과 표현을 확인한 AI가 그 판단과 근거를 남기는 약속이다. 진짜 검토가 있었는지와 API가 형식상 값을 받았는지는 다른 사실로 관리한다.
나는 한영 원고와 공개 파생물을 함께 확인한다
복원할 원고는 한글 본문만이 아니라 같은 항목의 영어 원고와 모듈 자료, 비공개 검토 근거를 포함한 스냅샷이다. 현재 복원된 내용에는 현재의 공개 검사 규칙을 다시 적용한다. 이전 원고가 지금의 기준과 맞지 않으면 그대로 재발행하는 우회로가 되지 않는다.
다음은 실제 관리 CLI의 기능을 설명하는 순서 예시다. 실행 전 현재 원고와 복원할 수정 기록을 검토한다. 복원 후에는 한영 미리보기, 공개 내용 검사, 발행을 순서대로 진행한다. 실제 자격증명은 보호된 로컬 파일에서 읽고 공개 글이나 출력에 넣지 않는다.
코드와 구현 살펴보기
CLI · 원고를 보존하며 내리기·복원·검토·재발행하는 순서
# Illustrative sequence. Each command uses local protected credentials.
# Do not paste credentials into a manuscript or terminal output.
python manage.py get article-slug
python manage.py withdraw article-slug
python manage.py revisions article-slug
python manage.py restore article-slug REVISION_ID
python manage.py preview article-slug --lang ko
python manage.py preview article-slug --lang en
python manage.py check article-slug
python manage.py publish article-slug
# REVISION_ID identifies a recorded snapshot, not a new version number.
# Review the current entry and restored text before any mutation.이번에 확인한 결과와 남은 범위를 구별한다
이번 홈페이지에는 실제 HTTPS 주소에서 수행한 HTTP·API 검사 기록이 있다. 그 안에서 버전 충돌 거부, 내리기 뒤 한영 공개 주소 차단, 목록·피드·사이트맵 제거, 비공개 미리보기 유지, 수정 기록 저장, 초안 복원과 재발행을 확인했다. 원고 변경만으로 재발행할 때 사이트 전체를 다시 배포할 필요도 없었다.
이 결과는 관리자 UI 버튼을 PC·모바일에서 직접 눌러 모두 검수했다는 뜻은 아니다. 기존 브라우저 작업을 보존하는 조건에서 화면 검증은 미완료로 남겼다. 또 사이트에서 글을 내렸다고 방문자가 저장한 복사본과 외부 검색의 과거 사본까지 즉시 사라지는 것은 아니다. 나는 내가 제어한 공개 응답의 결과와 외부에 남을 수 있는 사본을 나누어 설명한다.
- 내린 원고와 수정 기록은 관리자에서 보존되는가.
- 한영 직접 주소와 목록·RSS·사이트맵에 같은 공개 상태가 적용되는가.
- 복원은 새 초안이며 현재 공개 기준으로 다시 검사되는가.
- 복원·저장·발행이 검토한 현재 버전과 맞는가.
- 충돌 뒤 현재 내용의 차이를 읽고 필요한 변경을 합치는가.
- 재발행한 한영 원고가 의도한 내용과 같은가.
나는 되돌릴 수 있는 운영을 제작 결과에 포함한다
홈페이지 제작이 공개 버튼을 누르는 순간 끝나면 이후의 실수는 운영자가 혼자 감당해야 한다. 지속적으로 글을 쓰고 AI에게 수정도 맡기려면 변경을 멈추고 이전 내용을 찾고 다시 검토할 수 있어야 한다. 그 길이 처음부터 있으면 실수 뒤의 판단을 차분하게 할 수 있다.
나는 발행과 복원을 하나의 성공 버튼으로 합치지 않았다. 내용을 보존하는 일과 지금 공개해도 되는지를 판단하는 일은 각각의 책임이 있기 때문이다. 이 구별을 코드와 관리 지침에 함께 남기는 것이 계속 자라는 홈페이지의 일부라고 생각한다.