목록은 되는데 글만 안 열렸다 — 4번 잘못 잡은 범인 끝에 찾은 진짜 원인

애드센스 재신청을 앞두고 홈페이지를 한 바퀴 다시 훑어보던 날이었다. 목록 페이지 (/insights)는 멀쩡했다. 카드도 잘 뜨고, 최신 글도 맨 위에 있었다. 그런데 카드 하나를 눌러서 개별 글로 들어가면 — 404였다. 이상한 건, 로컬에서 똑같은 주소로 열어보면 200으로 멀쩡히 열린다는 것이었다. 딱 프로덕션에서만, 딱 개별 글에서만 죽는 버그였다.

자동화 워크스페이스 일러스트

1번, 2번, 3번, 4번 — 전부 헛다리였다

"글 데이터에 뭔가 문제가 있나 보다"는 게 첫 직감이었다. 그래서 파일명에 한글이 섞여 있는 게 원인이라고 의심하고 content 파일명을 전부 영문으로 바꿨다. 효과 없음. 다음엔 URL 주소(slug) 자체에 한글이 들어가는 게 문제라고 의심해서 주소를 전부 로마자로 바꿨다. 효과 없음. 그다음엔 배포 컨테이너(Dockerfile)가 글 파일을 복사해가지 않는 거라고 의심해서 복사 구문을 추가했다. 효과 없음. 마지막으로 글 목록 파일(index.json) 안에 본문을 통째로 같이 넣어보기까지 했다. 그래도 여전히 404였다. 네 번 연속으로 총을 겨눴는데 네 번 다 빈총이었던 셈이다.

범인을 다시 찾은 건, 대표님이 보내준 스크린샷 한 장이었다

돌이켜보면 이 삽질에는 패턴이 있었다. 매번 "이번엔 진짜일 것 같다"는 확신으로 시작해서, 고치고, 배포하고, 3~5분을 기다려 페이지를 새로고침하고, 다시 404를 보는 순서였다. 네 번 다 똑같은 루프였다. 세 번째 시도(Dockerfile 수정) 뒤에는 "이번엔 확실하다"는 생각까지 들었는데, 배포가 끝나고 열어본 화면은 여전히 404였다. 그 순간 은근히 의심이 든 게, 혹시 빌드 자체가 조용히 실패하고 있는 게 아닐까 하는 것이었다. 그런데 로컬에서는 로그를 볼 방법이 마땅치 않았다.

네 번째 헛발질 뒤에야 방향을 바꿨다. 대표님이 배포 콘솔 화면을 캡처해서 보내줬는데, 빌드는 처음부터 끝까지 전부 초록불로 성공해 있었다. 그 순간 문제의 성격이 완전히 바뀌었다. "배포가 실패한 게 아니라, 배포는 됐는데 서빙이 안 되는 것"이었다. 그리고 다시 보니 처음부터 신호는 있었다. 글 목록(하나짜리 정적 페이지)은 되고, 글 하나하나 (주소마다 따로 만들어지는 동적 페이지)만 안 된다는 패턴 — 이건 데이터나 인코딩 문제가 아니라 라우팅/서빙 문제라는 신호였다. 그 신호를 처음부터 믿었어야 했는데, 데이터 쪽을 먼저 의심하느라 세 번을 돌아간 것이다. 개발 환경(내 컴퓨터)에서는 페이지를 요청할 때마다 그 자리에서 새로 그려주기 때문에 아무 문제가 없었고, 실제 서버 환경에서만 "미리 만들어둔 파일을 찾아서 주는" 방식이 달랐다는 게 뒤늦게 눈에 들어왔다.

목록 페이지는 정상인데 개별 글 페이지만 유령처럼 404로 사라지는 일러스트

진짜 범인: 미리 구워둔 페이지가 배달되지 않았다

이 홈페이지는 글 하나하나의 주소(/insights/[slug])를 빌드할 때 미리 페이지로 "구워두는"(정적 프리렌더) 방식으로 만들어져 있었다. 문제는 이 미리 구운 개별 페이지가, 실제로 서버가 돌아가는 방식(컨테이너 기반 런타임)에서는 배달되지 않는다는 것이었다. 목록 페이지는 애초에 미리 굽는 페이지가 하나뿐이라 문제가 없었고, 글 하나하나는 미리 구운 페이지가 여러 개라서 딱 그것만 사라진 것이었다. 해결은 허탈할 만큼 짧은 코드 한 줄이었다. 미리 굽지 말고, 요청이 올 때마다 그 자리에서 바로 만들어서 주라는 설정 한 줄. 빌드 로그에서 개별 글 표시가 "미리 구움" 표시에서 "그때그때 만듦" 표시로 바뀌는 걸 확인하고 나서야 진짜 잡았다는 걸 알았다.

헛발질도 완전히 버려지진 않았다

네 번의 오진이 전부 쓸모없었던 건 아니다. 첫 번째, 두 번째 시도 때 한글 주소를 로마자로 바꿔둔 건 원인은 아니었지만, 그 자체로 주소가 훨씬 깔끔해지는 부수 효과가 있었다. 버그를 못 잡았어도 개선은 남는 경우가 있다는 걸 다시 확인한 셈이다. 이번 사건에서 가장 크게 남은 교훈은 이거다. 프로덕션에서만 나는 문제를 만나면, 코드부터 의심하기 전에 배포 로그부터 먼저 볼 것. "빌드는 성공했는가"를 가장 먼저 확인했다면 헛발질을 세 번은 줄일 수 있었다.

지금은 artgourmet.cloud/insights의 글 전부가 프로덕션에서도 잘 열린다. 이런 삽질과 해결 과정을 하나씩 기록해두는 이유는, 1인 기업으로 AI 자동화를 굴리다 보면 이런 유령 같은 버그를 계속 만나기 때문이다. 코딩을 전혀 몰라도 이 과정을 함께 겪은 이야기는 「AI 회사를 만들었습니다 -실전편-」에도 정리해뒀다.

작성: Art Gourmet

댓글

이 블로그의 인기 게시물

프롤로그 | AI 1인 기업 창업 가이드: 코딩 없이 시작하는 IT 스타트업 20부작 로드맵

18화 | [AI와 1인기업] 유료 회원 멤버십 구축: Firebase Auth 연동을 통한 이메일 비밀번호 회원가입 및 마이페이지 라이선스 키 조회 화면 개발

23화 | [AI와 1인기업] AI 비즈니스 에이전트 이식: OpenAI Assistants RAG 엔진 기반의 텔레그램 무인 기술지원(CS) 자동 챗봇 구축