
2026년 8월, 저희 사이트의 블로그 글 176개에서 상단 로고와 메뉴 링크가 전부 404였습니다. 글 자체는 200으로 잘 열렸고, 빌드도 배포도 에러 없이 성공한 상태였습니다. 이 글은 그 사고의 원인과, 같은 종류의 사고를 자기 사이트에서 30초 안에 확인하는 방법을 다룹니다.
무엇이 죽어 있었나
글 페이지에 들어온 방문자가 상단 메뉴나 하단 푸터를 누르면 전부 404 페이지로 갔습니다. 좌상단 로고도 마찬가지였습니다. 정작 글 본문은 정상이었기 때문에, 글만 열어 보면 아무 문제가 없어 보였습니다.
| 확인한 것 | 값 |
|---|---|
| 영향받은 글 | 176 / 176 (전부) |
| 죽은 링크 — 고유 주소 | 31개 (헤더 18 · 푸터 13) |
| 죽은 링크 — 실제 태그 수 | 32개 (헤더에 같은 주소가 1회 더) |
| 글 본문 자체 | 정상 (200) |
| 빌드·배포 로그 | 에러 없음 |
| 영향받지 않은 주소 | 27개 (루트에 있는 일반 페이지·영문) |
2026년 8월 27일 기준, 배포본 전수 집계입니다.
죽은 링크가 글마다 31개씩이라는 점이 중요합니다. 글 하나에 링크 하나가 깨진 것이 아니라, 사이트 안을 돌아다니는 통로가 글 페이지에서만 통째로 끊겨 있었습니다.
왜 빌드는 성공했는데 링크만 죽나
빌드 시스템은 루트 페이지(about.html)의 헤더·푸터 마크업을 읽어 글 페이지에 그대로 심습니다. 공통 요소를 한 곳에서 관리하려는 흔한 구조이고, 그 자체는 문제가 없습니다.
문제는 글 주소가 한 단계 아래라는 것입니다. 글은 /post/{슬러그}에 있으므로 기준 폴더가 /가 아니라 /post/입니다. 상대 경로는 현재 폴더를 기준으로 풀리므로, 루트에서 멀쩡하던 href="about.html"이 글 페이지에서는 /post/about.html을 가리키게 됩니다.

빌드가 이것을 잡지 못하는 이유는 단순합니다. 빌드는 문자열을 옮겨 붙일 뿐, 그 문자열이 어느 주소에서 어떻게 해석될지 알지 못합니다. 마크업은 문법적으로 완전하고, 파일도 정상적으로 생성되며, 배포도 성공합니다. 링크가 가리키는 곳에 파일이 있는지는 아무도 확인하지 않습니다.
그래서 이 사고는 로그로 잡히지 않습니다. 저희도 배포 로그와 빌드 카운트를 매번 확인해 왔지만, 이 항목은 애초에 세는 대상이 아니었습니다. 자가진단 퀴즈를 6곳에 붙일 때도 그랬듯, 페이지 하나만 열어 보고 판단하면 전체에 걸친 문제는 눈에 들어오지 않습니다.
어떻게 확인하나
배포 결과물에서 하위 폴더에 있는 페이지만 골라, 상대 경로 링크가 남아 있는지 세면 됩니다. 한 줄입니다.
grep -rlo '<a [^>]href="[a-z0-9_-]\.html"' 배포폴더/post/ | wc -l

0이 아니면 그 개수만큼의 파일에 상대 경로 링크가 남아 있다는 뜻입니다. post 자리에는 자기 사이트에서 한 단계 아래에 있는 폴더를 넣습니다.
앞부분의 <a 조건이 붙어 있는 이유가 있습니다. 이 조건 없이 href만 찾으면 본문에서 HTML을 예시로 인용한 글이 자기 문장 때문에 걸립니다. 지금 읽고 계신 이 글이 그랬습니다. 위 명령을 처음 돌렸을 때 1건이 잡혔는데, 실제 링크가 아니라 이 글 본문에 적힌 예시 문자열이었습니다. 점검 도구도 오탐을 냅니다. 걸린 것이 실제 링크인지는 한 번 열어서 봐야 합니다.
브라우저로 직접 확인하려면 글 페이지를 열고 상단 로고를 누르면 됩니다. 홈으로 가지 않고 404가 뜨면 같은 문제입니다. 주소창에 /post/index.html처럼 직접 쳐 봐도 됩니다.
- 하위 경로가 여러 개면(/post/, /blog/categories/ 등) 각각 따로 확인합니다
- 정적 사이트 생성기를 쓰든 직접 빌드하든 루트 마크업을 하위 경로에 재사용하는 구조라면 전부 해당됩니다
우리 사이트에서는 어땠나
수정 방향은 두 가지였습니다. 원본 HTML의 링크를 전부 절대 경로로 바꾸거나, 글 페이지에 심는 복사본만 바꾸는 것입니다.
저희는 두 번째를 골랐습니다. 루트 페이지에서는 상대 경로가 정상 동작하므로 원본을 건드릴 이유가 없고, 원본 13개를 손대면 그쪽에서 새 사고가 날 수 있기 때문입니다. 빌드가 글에 심을 때만 about.html을 /about으로 바꾸도록 했습니다.
| 수정 전 | 수정 후 | |
|---|---|---|
| 글 페이지의 상대 링크 | 176개 글 전부 | 0개 |
| 좌상단 로고 | index.html → 404 | / → 200 |
| 루트 페이지 원본 | 상대 경로 | 상대 경로 (그대로 둠) |
.html 확장자를 떼고 /about으로 보낸 것은 부수적인 정리입니다. /about.html도 308 리다이렉트로 같은 곳에 가지만, 리다이렉트 한 번을 아끼고 크롤러에도 주소가 하나로만 보입니다.
한 가지 분명히 해 둘 것이 있습니다. 저희는 이 사고로 유입이 얼마나 줄었는지 측정하지 않았습니다. 언제부터 죽어 있었는지도 확정하지 못했습니다. 링크가 죽어 있었다는 사실과 고친 사실까지가 저희가 말할 수 있는 전부이고, 트래픽 영향은 추정하지 않겠습니다.
자주 묻는 질문
상대 경로를 쓰면 안 되나요?
아닙니다. 같은 폴더 안에서만 쓰이는 링크라면 상대 경로가 더 안전합니다. 문제가 되는 것은 한 마크업이 서로 다른 깊이의 여러 주소에 재사용될 때입니다. 공통 헤더·푸터처럼 여러 경로에 심기는 조각은 절대 경로로 두는 편이 낫습니다.
사이트맵과 robots.txt가 정상인데도 이런 일이 생기나요?
생깁니다. 사이트맵은 어떤 주소가 존재하는지만 알려 주고, 페이지 안의 링크가 어디를 가리키는지는 다루지 않습니다. 이 사고에서도 사이트맵 203개 주소는 전부 정상이었습니다. robots.txt 역시 크롤러의 접근 허용 여부만 정할 뿐이어서, 저희가 robots.txt에서 AI 크롤러를 막아두면 생기는 일에서 다룬 것과는 층이 다른 문제입니다.
검색 순위에 영향이 있나요?
내부 링크는 크롤러가 사이트를 도는 경로이자 페이지 간 관계를 읽는 단서이므로, 끊긴 상태가 길어지면 좋을 이유는 없습니다. 다만 순위는 검색엔진 알고리즘이 정하는 것이고, 저희는 이 건의 순위 영향을 측정하지 않았습니다. 고쳐야 할 이유는 순위가 아니라 방문자가 실제로 이동하지 못한다는 사실 쪽이 더 분명합니다.
배포 로그만 봐도 되지 않나요?
이 사고에서 배포 로그는 끝까지 정상이었습니다. 빌드 성공, 파일 생성, 배포 완료가 전부 찍혔습니다. 로그는 「내가 하기로 한 일을 했는가」를 말해 줄 뿐, 「그 결과가 맞는가」를 말해 주지 않습니다.
마무리
배포가 성공했다는 신호와 사이트가 제대로 동작한다는 신호는 다릅니다. 이 둘을 같은 것으로 취급하는 순간, 로그가 세지 않는 항목은 아무리 오래 깨져 있어도 발견되지 않습니다.
점검 항목을 늘리는 것보다 먼저 물어야 할 질문은 이것입니다. 지금 우리 배포 로그가 세지 않는 것은 무엇인가.
참고: 이 글에 쓰인 수치는 2026년 8월 27일 자사 배포본 전수 집계이며, 같은 날 수정·배포를 마쳤습니다.