사이트 점검기가 멀쩡한 블로그를 ‘전체 다운’이라 외친 이유 (자기 글에 속은 오탐)

swp

저는 수학 과외를 하다가, 학생들 오답을 정리하던 습관 그대로 제 코딩 오답을 모으는 블로그를 만들고 있어요. 그래서 이 블로그엔 “사이트가 다운됐다”, “치명적인 오류가 났다” 같은 실패담이 잔뜩 쌓입니다. 그런데 어느 날, 그 실패담을 지키려고 만든 자동 점검 코드가 정작 멀쩡한 블로그를 ‘전체 다운’이라고 외치는 황당한 일이 벌어졌어요. 범인은 놀랍게도 저 자신이었습니다.

새 글을 올리고 나면 자동으로 사이트를 점검한다

저는 글을 발행하고 나면 verify.js라는 스크립트를 돌려요. 발행 직후에 사이트가 멀쩡한지, 글 본문이 제대로 올라갔는지 자동으로 확인해주는 발행후 점검 코드입니다. 사람이 매번 눈으로 확인하지 않아도 되니까, 저 같은 초보에겐 든든한 안전장치죠.

그날도 ai-read-before-edit라는 글(post 127)을 공개하고 습관처럼 점검을 돌렸습니다.

node verify.js --url https://woodpecker-ai.com/ai-read-before-edit/
⚠️ 사이트 루트에 치명 오류 배너 — 전체 다운 의심

“전체 다운 의심”이라니, 심장이 철렁했어요. 에러가 빨갛게 뜨면 일단 무섭잖아요. 저도 그래요. 사이트가 통째로 죽었나 싶어서 곧장 브라우저로 홈페이지를 열어봤습니다.

그런데 사이트는 멀쩡했다

열어보니 홈은 아주 정상이었어요. 글 목록이 제대로 나오고(article 10개), 링크도 63개가 살아 있었습니다. WordPress가 진짜로 뻗었을 때 뜨는 그 하얀 “치명적인 오류” 페이지가 전혀 아니었어요. 사이트는 멀쩡한데 점검기만 혼자 “다운!”이라고 외친 거예요.

여기서부터가 진짜 오답노트감입니다. 사이트가 죽은 게 문제가 아니라, 점검기가 헛것을 봤다는 게 문제였으니까요. 그럼 점검기는 대체 뭘 보고 “치명 오류”라고 판단했을까요?

범인은 내가 쓴 글 제목이었다

점검기 안에는 FATAL_PATTERNS라는 목록이 있어요. “이런 문구가 페이지에 보이면 사이트가 죽은 거다” 하고 미리 정해둔 위험 신호 모음이죠. 그 안에 /critical error/i(대소문자 무시하고 “critical error”)와 /치명적인 오류/가 들어 있었습니다. 점검기는 사이트 HTML 전체를 훑으면서 이 문구가 어디든 들어 있으면 다운으로 봤어요.

문제는 제 블로그의 주제였습니다. 이 블로그 이름이 “딱따구리 AI 오답노트”예요. 에러가 주제인 블로그란 말이죠. 그래서 홈페이지 글 목록에는 “치명적인 오류”·”critical error”라는 문구가 제목과 발췌에 그대로 박힌 글들이 정상 콘텐츠로 버젓이 실려 있었습니다. 워드프레스가 통째로 뻗었을 때 FTP로 복구한 이야기, 첫 발행에서 사이트를 내려버린 이야기 같은 것들이요. 저에게는 소중한 실패담인데, 점검기 눈에는 장애 신호가 사방에 널린 화면으로 보였던 거죠.

점검기 입장에선 홈 HTML을 훑다가 제 글 제목 속 “치명 오류”라는 글자를 발견하고는, 그게 진짜 장애 배너인지 그냥 글 제목인지 구분하지 못한 채 “다운이다!”라고 외친 거예요. 자기가 지키려던 글의 제목에 자기가 속은 셈입니다.

수학 과외로 비유하면 이래요. 제가 학생 오답노트(틀린 풀이를 모아 복습하는 공책)를 채점기에 넣었더니, 채점기가 노트에 적힌 “틀린 풀이”라는 글자를 보고 이 학생은 시험을 통째로 망쳤다고 판정해버린 거죠. 노트는 원래 틀린 걸 모으라고 만든 건데 말이에요.

이게 왜 위험하냐면 — ‘늑대소년’ 문제

여기서 한 발 더 들어가면 진짜 무서운 지점이 나옵니다. 오매칭된 저 에러 글들은, 홈뿐 아니라 자기 자신을 점검할 때도 똑같이 “치명 오류”로 걸릴 수 있어요. 글 본문에 “치명적인 오류”라는 단어가 당연히 들어 있으니까요.

그러면 점검기는 멀쩡한 글마다 계속 “다운!”을 외치게 됩니다. 그리고 이게 반복되면 저는 결국 그 경고를 믿지 않게 돼요. “또 오탐이겠지” 하고 넘기다가, 진짜로 사이트가 죽은 날 그 경고를 무시하게 되는 겁니다.

이게 늑대소년 문제예요. 거짓 경고(“양치기 소년의 늑대다!”)가 쌓이면, 정작 진짜 늑대가 왔을 때 아무도 안 믿는다는 그 우화요. 점검기의 생명은 ‘정확도’가 아니라 얼마나 믿을 수 있느냐에 있는데, 오탐은 그 믿음 자체를 갉아먹습니다.

해결 — ‘문구가 보이나’가 아니라 ‘구조가 없나’로 바꿨다

처음엔 “위험 문구 목록에서 ‘치명 오류’를 빼면 되지 않나?” 싶었어요. 하지만 그러면 진짜로 사이트가 그 문구를 띄우며 죽었을 때 못 잡습니다. 문구를 빼는 건 답이 아니었어요.

핵심은 판단하는 근거 자체를 바꾸는 것이었습니다. “치명 오류라는 글자가 보이나?”(내용을 보는 방식)에서, “정상 페이지라면 당연히 있어야 할 구조가 없나?”(구조를 보는 방식)로요.

생각해보면 정상 페이지와 진짜 죽은 페이지는 생김새가 다릅니다. 정상 페이지에는 글 목록이나 본문(<article> 태그나 .entry-content 영역)이 반드시 들어 있어요. 반대로 WordPress가 진짜 죽으면, 그런 본문 구조는 하나도 없이 에러 메시지만 덩그러니 남습니다.

그래서 판별 규칙을 이렇게 바꿨어요. isFatalPage라는 함수를 새로 만들어서, 치명 문구가 보이면서 동시에 정상 본문 구조(<article>.entry-content)가 하나도 없을 때만 진짜 다운으로 보게 한 거죠. 문구만으로는 판단하지 않고, “정상이라면 있어야 할 게 없다”까지 확인하는 겁니다. 이 판별식은 점검기가 쓰이는 두 군데(글 하나 점검할 때, 사이트 전체 점검할 때)에 똑같이 적용했습니다.

두 조건을 AND(둘 다 참)로 묶은 게 포인트예요. 제 글 제목에 “치명 오류”가 있어도, 그 페이지엔 멀쩡한 본문 구조가 같이 있으니 이제 다운으로 걸리지 않습니다. 반대로 진짜 죽은 페이지는 본문 구조가 없으니 여전히 정확하게 잡히고요.

고쳤으면 반드시 확인 — 세 가지로 검증했다

바이브코딩을 하면서 제일 크게 배운 게 이거예요. 고쳤다는 말은 “고쳤을 것이다”가 아니라 “고쳐진 걸 확인했다”여야 한다. 안 되던 걸 또 같은 방식으로 넘겨짚는 건, 틀린 풀이를 확인 없이 다시 제출하는 거랑 같거든요. 그래서 세 가지로 검증했습니다.

첫째, 작은 단위 테스트. isFatalPage 함수 하나만 떼어서, 정상 페이지 모양과 진짜 치명 오류 페이지 모양을 각각 넣어보고 판정이 맞는지 확인했어요.

둘째, 라이브 전수 점검. 실제로 발행돼 있는 글들을 전부 다시 점검기에 돌렸습니다. 예전에 오탐을 일으키던 바로 그 에러 주제 글들까지 포함해서요. 결과는 경고 없이 통과였습니다.

셋째, 그리고 이게 제일 중요한데 — 가짜 다운을 일부러 만들어봤어요. 본문 구조는 없고 “There has been a critical error”만 있는 가짜 페이지를 하나 만들어서 점검기에 넣었습니다. 여기서 점검기가 여전히 다운을 잡아내는지를 봐야 했거든요. 오탐만 없애려다 진짜 다운까지 못 잡으면 그건 개악이니까요. 다행히 이 가짜 페이지는 정확히 에러로 걸렸습니다. 진짜 늑대는 여전히 잡는다는 걸 확인한 거죠.

한 가지 더 — 어느 쪽 실수가 더 비싼지 먼저 정한다

이번 수리에서 제가 오래 붙잡은 질문은 “어떻게 고치지?”가 아니라 “둘 중 어느 쪽으로 틀리는 게 덜 아픈가?”였어요. 점검기가 틀리는 방식은 두 가지거든요. 멀쩡한데 장애라고 우기거나(오탐), 진짜 장애인데 조용하거나(미탐).

보통은 미탐이 더 무섭습니다. 사이트가 죽었는데 아무도 안 알려주는 거니까요. 그런데 이번 경우엔 오탐이 더 비쌌어요. 오탐이 반복되면 제가 경보 자체를 안 믿게 되고, 그러면 결국 진짜 장애도 놓치게 되거든요. 오탐을 방치하면 미탐으로 변한다 — 이게 이 사건이 준 진짜 교훈이었습니다.

그래서 판별 기준을 느슨하게 두고 “일단 많이 잡자”로 가지 않았어요. 정상 본문 구조가 없을 때만 장애로 보도록 조건을 하나 더 걸어서, 잡는 양을 줄이는 대신 잡았을 때 믿을 수 있게 만들었습니다. 자동 점검을 붙일 때는 이 질문을 먼저 하시길 권해요 — “내 경보는 틀릴 때 어느 쪽으로 틀리나?”

정리 — 점검기가 이상한 소리를 할 때

이번 오답노트의 핵심은 하나예요. 점검 도구가 다루는 콘텐츠의 주제 자체가, 점검 도구가 찾는 신호와 겹칠 수 있다. 에러를 주제로 쓰는 블로그라서, 에러를 찾는 점검기가 자기 글에 속은 거죠. 도구가 자기 도메인에 오염된 셈입니다.

혹시 여러분도 자동 점검이나 모니터링에서 이상한 경고를 받는다면, 아래를 한번 짚어보세요.

신호어떻게 판단할까액션
경고는 뜨는데 실제 화면은 멀쩡점검기가 ‘내용(문구)’만 보고 판단하는지 의심🔴 지금: 판단 근거를 ‘구조 유무’로 바꾸기
같은 오탐이 자꾸 반복됨늑대소년 위험 — 곧 진짜 경고도 무시하게 됨🔴 지금: 오탐부터 끊기
위험 문구를 목록에서 빼고 싶다진짜 장애 때 못 잡게 될 수 있음🟡 백로그: 문구 제거 대신 판별 조건 강화
오탐을 고친 뒤진짜 장애는 여전히 잡히는지 미확인🔴 지금: 가짜 장애를 만들어 회귀 테스트

한마디로 점검기가 헛것을 볼 땐 이거예요. 문구를 지우지 말고, 판단 근거를 바꿔라. 다만 근거를 바꾼 뒤엔 꼭 진짜 장애를 흉내 내 다시 걸리는지 확인해야 해요. 오탐을 없애는 것과 진짜를 못 잡게 되는 것은 종이 한 장 차이라서, 그 한 장을 확인하는 게 결국 점검기를 ‘믿을 수 있게’ 만드는 마지막 단계였습니다.


댓글 남기기