sqzass
English

배포

디렉터리 하나로 나오는 결과물과, 그걸 받아 주는 호스트들

sqzass build -i mysite

mysite/public이 사이트입니다. 파일을 서빙하는 곳에 복사하면 끝입니다. 런타임도, 서버 컴포넌트도, 남아 있는 빌드 단계도 없습니다.

호스트가 하지 않아도 되도록 sqzass가 하는 일

모든 URL이 index.html을 담은 디렉터리라서 예쁜 URL에 rewrite 규칙이 필요 없습니다. 캐시 무효화가 파일명에 들어 있어서 캐시 헤더가 필요 없습니다. 출력물 중 어느 것도 호스트 설정에 기대지 않습니다.

의도한 것이고, 이 문서 사이트를 GitHub Pages에 올려 둔 것도 그걸 정직하게 지키기 위해서입니다. Pages에는 커스텀 헤더도, 리다이렉트 규칙도, rewrite도 없으므로, 그런 것에 기대는 게 생기면 여기서 가장 먼저 깨집니다.

보상은 호스트를 옮기는 일이 복사가 된다는 점입니다. 같은 디렉터리가 Cloudflare Pages 에서도, Netlify에서도, CloudFront 뒤의 S3에서도, nginx에서도 그대로 맞습니다.

그 밖에 만들어지는 것

sitemap.xml에 모든 페이지가 들어가고, 두 개 이상의 언어에 존재하는 페이지에는 <xhtml:link> 대체 링크가 붙습니다. 이중 언어 사이트에 대해 구글이 요구하는 형태입니다. robots.txt는 전부 허용하고 sitemap을 가리킵니다.

둘 다 prioritychangefreq를 담지 않습니다. 구글이 2023년에 둘 다 무시한다고 확인했기 때문입니다. lastmod도 담지 않는데, 이건 선택입니다. 여기서 쓸 수 있는 출처가 전부 믿을 만하지 않습니다. 파일 mtime은 체크아웃 시각이라 CI에서는 모든 페이지가 "오늘 아침에 바뀌었다"고 주장하게 되고, 두 번 빌드하면 같은 바이트가 나온다는 보장도 깨집니다. git 커밋 시각은 정확하지만 전체 이력이 필요한데 actions/checkout은 기본이 얕은 클론이라, 조용히 모든 페이지에 같은 날짜를 찍게 됩니다. 구글은 한 번 믿을 수 없다고 판단하면 그 사이트의 lastmod를 통째로 무시합니다. 틀린 값이 없는 것보다 나쁘다는 뜻입니다.

llms.txt는 모든 페이지의 제목·URL·설명을 담은 평평한 목록으로, llmstxt.org가 제안한 형식입니다. 이 사이트에 대해 질문받은 언어 모델이 전체를 훑는 대신 파일 하나를 읽으면 됩니다. 제목·URL·설명이 이미 있으니 만드는 데 드는 게 없습니다.

sitemap.xml이나 robots.txt, llms.txt를 직접 static/에 넣으면 sqzass는 그 파일을 아예 만들지 않습니다. 직접 넣은 것을 덮어쓰지도, 조용히 무시하지도 않습니다.

각 안내서

전부 같은 사실 두 개입니다. sqzass build를 돌리고 public/을 발행한다. 문서가 갈리는 건 그 두 사실을 어디에 적느냐와, 각 호스트가 프리뷰 URL을 뭐라고 부르느냐뿐입니다.

경로 아래에 놓이는 사이트

https://user.github.io/repo, https://group.gitlab.io/project, https://user.codeberg.page/repo — 전부 프로젝트 사이트이고, 전부 결과물을 도메인 루트가 아니라 경로 아래에 서빙합니다. base_url에 그 전체를 적으세요.

base_url = "https://user.github.io/repo"

그러면 sqzass가 생성하는 모든 URL에 접두사가 붙습니다 — 페이지 링크도, 스타일시트 href도, 검색 색인도. 출력 디렉터리는 평평하게 남는데, 그 디렉터리가 곧 호스트가 서빙하는 루트이기 때문입니다.

경로를 빠뜨리는 건 여기서 유일하게 조용한 실수입니다. 빌드는 성공하고 페이지도 다 있는데, 모든 링크와 스타일시트가 한 단계 위를 가리킵니다.

static/은 통과 경로입니다

static/ 안의 것은 경로와 이름이 그대로 유지된 채 출력에 놓입니다. sqzass가 어떤 호스트도 알지 못한 채로 호스트별 파일이 동작하는 방식입니다.

CNAME GitHub Pages 커스텀 도메인
.domains Codeberg Pages 커스텀 도메인
_headers, _redirects Netlify, Cloudflare Pages
.well-known/* 도메인 소유 검증, security.txt

콘텐츠 해시가 붙는 건 CSS와 JavaScript뿐입니다. 이름 자체가 계약인 파일은 이름을 유지합니다.

알아 둘 파일 둘

.nojekyll은 빌드마다 출력에 들어갑니다. 없으면 GitHub Pages가 출력을 Jekyll로 한 번 더 굴려서 _로 시작하는 디렉터리를 통째로 삼킵니다.

CNAME이 필요하면 static/에 두면 이름 그대로 복사됩니다. 해시가 붙은 CNAME은 GitHub이 영영 찾지 않을 파일입니다.

빌드가 내보내는 것

전체 목록입니다. "호스트를 옮기는 일이 복사"라는 말을 믿는 대신 확인할 수 있으라고 적어 둡니다.

static/의 전부 경로와 이름 그대로. CSS와 JS에만 콘텐츠 해시
assets/highlight.<해시>.css [highlight] enabled = false가 아니면
asset-manifest.json 논리 이름 → 실제 URL, 항상
<경로>/index.html 페이지마다 하나
search-<언어>.json [search] enabled = false가 아니면 언어마다 하나
feed-<언어>.xml 날짜 있는 페이지가 있는 언어마다 하나
sitemap.xml, robots.txt 같은 이름을 static/에 두지 않았다면
llms.txt 같은 조건
404.html templates/404.html이 있을 때
alias 스텁 aliases 항목마다 하나
.nojekyll 항상. static/.nojekyll보다 이쪽이 이깁니다

그 밖엔 없고, 출력 디렉터리 밖으로는 아무것도 나가지 않습니다.

결정성

같은 입력을 두 번 빌드하면 바이트까지 같은 출력이 나옵니다. 그래서 이 빌드를 CI에서 검사로 돌려도 되고, 바뀐 게 없는 배포는 아무것도 올리지 않습니다.