
이번엔 세 번 다 제가 쓴 코드가 문제였습니다
지난 글에서 세 번 막혔는데 세 번 다 남이 만든 코드에 답이 있었다고 썼습니다.
그 글을 올리고 며칠 지나서 또 세 번 막혔습니다. 이번에는 세 번 다 제가 쓴 코드가 문제였습니다.
앞 글이랑 짝을 이루는 것 같아 그대로 적습니다.
1. “안 되는” 게 아니라 “안 보이는” 거였습니다
글 아래에 조회수를 붙여뒀는데, 새로 올린 글 네 편에 한 줄도 안 떴습니다.
통계 서버 문제인가 싶어 주소를 직접 눌러봤습니다.
/counter/blog/korean-web-typography/.json
→ 200 {"count":"3"}
/counter/blog/comments-on-a-static-blog/.json
→ 404 {"count":"0"}
숫자가 있는 글은 200으로 잘 옵니다. 실제로 그 글에 들어가 보니 “조회 3”이 잘 떠 있었습니다.
그럼 안 뜨는 쪽은 왜 안 뜨나. 제가 쓴 코드를 봤습니다.
const n = Number(String(raw).replace(/[^0-9]/g, ''));
if (!n) return;
0이면 아무것도 안 보여주게 제가 만들어놨습니다.
이걸 만들면서 쓴 글에 제가 이렇게 적어놨더군요. “아무도 안 본 글에 조회 0을 붙여두는 건, 굳이 안 해도 되는 자기소개입니다.”
맞는 판단이었다고 아직도 생각합니다. 그런데 새 글 네 편이 전부 0이니까 네 편 다 아무것도 안 뜨는 상태가 됐고, 저는 그걸 고장으로 읽었습니다. 여기에 통계 쪽이 최대 4시간까지 캐시한다는 것까지 겹쳤고요.
고장이 아니라 제가 시킨 대로 돌아가고 있었습니다.
“안 된다”와 “안 보인다”는 다릅니다. 안 보이는 거면 먼저 “내가 숨기라고 시킨 코드가 있는지”를 봐야 합니다.
2. 고장 난 게 아니라 만든 적이 없었습니다
글 세 편을 한 번에 올리기 아까워서, 작성일을 이틀씩 앞으로 잡아뒀습니다. 예약 발행처럼 쓰려고요.
배포하고 블로그를 열었더니 세 편이 다 올라와 있었습니다.
이번에도 코드를 봤습니다. 그런데 볼 게 없었습니다.
const posts = (await getCollection('blog')).sort(
(a, b) =>
b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
가져와서 정렬만 합니다. 미래 날짜를 거르는 줄이 한 줄도 없습니다. 목록, 홈, 태그, RSS, 글 페이지까지 다섯 군데가 전부 이랬습니다.
버그를 찾고 있었는데, 그 기능은 애초에 만든 적이 없었습니다. 날짜 칸이 있으니까 당연히 그렇게 동작할 거라고 혼자 생각했던 겁니다.
안 만든 기능은 고장 나지도 않습니다. 당연한 말인데, 막상 그 상황에서는 “왜 안 되지”부터 하게 됩니다.
거르는 함수를 하나 만들어서 다섯 군데를 그걸로 바꿨습니다.
export async function getVisiblePosts() {
const all = await getCollection('blog');
const published = import.meta.env.DEV
? all
: all.filter(
(p) => p.data.pubDate.getTime() <= Date.now(),
);
return published.sort(
(a, b) =>
b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
}
개발 서버에서는 예약글도 보이게 뒀습니다. 미리 보려고요.
그리고 하나 더. 정적 사이트는 날짜가 됐다고 저절로 안 열립니다. 페이지는 빌드할 때 만들어지니까, 그날 다시 한 번 빌드해야 생깁니다. 이건 예약 발행을 붙이고 나서야 깨달았습니다.
3. 제 컴퓨터에서만 맞았습니다
예약 발행을 붙이고 나서 더 이상한 걸 발견했습니다.
작성일을 오전 10시 4분으로 잡아뒀는데, 계산해보니 실제로 열리는 시각이 저녁 7시 4분이었습니다. 9시간 차이입니다.

배포된 페이지를 열어 날짜 태그를 봤더니 답이 바로 나왔습니다.
<time datetime="2026-09-10T10:04:00.000Z">
끝에 Z. 세계 표준시라는 표시입니다. 제가 적은 건 한국 시간 오전 10시였는데요.
원인은 이렇습니다. 작성 화면은 시간대를 안 붙이고 저장합니다.
pubDate: 2026-09-10T10:04:00
그리고 YAML 규칙상 시간대가 안 붙은 날짜는 UTC로 읽습니다. 배포 서버도 UTC로 돌아가니 아무 데서도 안 걸리고 그대로 넘어갑니다. 제 컴퓨터에서만 맞아 보였던 겁니다.
같은 이유로 날짜 표시도 틀어져 있었습니다. 새벽에 올린 글이 하루 전 날짜로 찍혔습니다.
두 군데를 고쳤습니다. 시간대가 안 적힌 값은 한국 시간으로 읽게, 날짜를 화면에 찍을 때도 한국 시간으로.
date.toLocaleDateString('ko-KR', {
timeZone: 'Asia/Seoul',
year: 'numeric', month: 'long', day: 'numeric',
});
timeZone 한 줄입니다. 이 한 줄이 없어서 며칠 동안 날짜가 하루씩 밀려 있었습니다.
그래서 어떻게 구분하나
세 번을 겪고 나니 순서가 좀 잡혔습니다. 남의 코드를 열기 전에 제 코드에 물어볼 게 있습니다.
“안 된다”인가, “안 보인다”인가 — 안 보이는 거면 숨기는 조건이 어딘가 있습니다. 대개 제가 넣은 겁니다.
그 기능을 만들긴 했나 — 이게 제일 허무한데 제일 자주 걸립니다. 설정 칸이 있다고 동작이 따라오는 건 아닙니다. 코드에서 그 단어로 한 번 검색해보면 3초면 끝납니다.
내 컴퓨터에서만 맞는 건 아닌가 — 시간대, 파일 이름 대소문자, 경로 구분자. 이런 건 로컬에서 절대 안 걸립니다. 배포된 화면을 열어서 실제 값을 확인해야 합니다. 저는 <time datetime> 하나 보고 답을 찾았습니다.
남은 이야기
앞 글에서 “남의 코드를 열면 답이 있다”고 썼는데, 그건 절반만 맞았습니다.
답이 있는 쪽을 먼저 정하는 게 먼저입니다. 남의 코드를 아무리 잘 읽어도 문제가 내 코드에 있으면 안 나옵니다. 이번에 저는 통계 서버를 의심하면서 시간을 썼는데, 정작 답은 불과 며칠 전에 제가 직접 쓴 if (!n) return; 한 줄에 있었습니다.
세 번 다 고치는 데는 한 줄에서 열 줄이면 됐습니다. 오래 걸린 건 어디를 볼지 정하는 부분이었습니다.
참고한 문서
- YAML 1.1 — timestamp 타입 — 3절. 시간대가 없으면 UTC로 본다는 규칙
- js-yaml 소스 (4.3.2) — timestamp.js — 3절. 실제로 Date.UTC로 만드는 코드
- MDN — Intl.DateTimeFormat의 timeZone 옵션 — 3절. 시간대를 안 주면 실행 환경 기준
- GoatCounter 문서 — Visitor counter — 1절. 경로가 없으면 404, 최대 4시간 캐시
- Astro 문서 — 콘텐츠 컬렉션 — 2절. getCollection은 필터를 넘겨야 거름
댓글
로그인도 이메일도 필요 없습니다. 이름만 적고 편하게 남겨주세요.
지금은 댓글을 불러올 수 없습니다. 잠시 뒤에 다시 시도해 주세요. 급한 내용이면 ryuma@kakao.com로 보내주셔도 됩니다.