점검 페이지 뒤에서 앱이 995만 번 재시작하고 있었다
홈페이지에 접속하면 모든 주소에서 「점검중」 화면만 나오는 상태였습니다. 응답 코드는 503이었고, 검색엔진에는 색인하지 말라는 표시까지 붙어 있었습니다. 점검을 하려고 일부러 막아 둔 것인지, 앱이 죽어서 대체 화면이 나오는 것인지는 바깥에서는 구별할 수 없습니다. 두 설정은 응답이 똑같기 때문입니다. 그래서 서버 안으로 들어가 확인했습니다. 점검 모드가 아니었다 서버의 프로세스 관리자(PM2)를 보니 홈페이지 앱이 약 995만 번 재시작된 상태였고, 가동 시간은 0초였습니다. 로그에는 한 줄만 반복되고 있었습니다. You are using Node.js 16.20.2. For Next.js, Node.js version = v18.17.0 is required. 사이트가 쓰는 Next.js 버전은 Node.js 18.17 이상이 필요했는데, 서버에 깔린 Node.js는 16.20.2였습니다. 앱은 뜨자마자 종료되고, 프로세스 관리자는 그것을 다시 띄우고, 앞단의 웹 서버(nginx)는 연결이 안 되니 점검 화면을 내보내고 있었습니다. 점검 화면이 「정상 동작하는 대체 페이지」 역할을 해서 문제가 겉으로 드러나지 않았던 셈입니다. 복구한 순서 재시작 루프부터 멈췄습니다. 죽는 앱을 계속 다시 띄우면 로그와 CPU만 소모합니다. 서버 전체의 Node.js를 올리지 않고, 계정 홈 디렉터리에 Node.js 20.10.0 바이너리를 따로 설치했습니다. 같은 서버에서 Node 16으로 정상 동작하던 다른 서비스를 건드리지 않기 위해서입니다. 새로 빌드하기 전에, 기존 빌드 결과물을 Node.js 20으로 띄워 응답을 확인했습니다. 정상 응답이 나와 재빌드가 필요 없다는 것을 먼저 확인했습니다. 프로세스 관리자에서 앱을 삭제하고 Node.js 20 실행 경로를 명시해 다시 등록한 뒤 설정을 저장했습니다. 저장하지 않으면 서버를 재부팅할 때 이전 상태로 돌아갑니다. 바깥 인터넷에서 홈페이지가 200으로 응답하는지, 모바일 화면과 문의 페이지가 열리는지 확인했습니다. 복구 후에는 앱이 online 상태이고 재시작 횟수가 0으로 유지되는 것까지 확인했습니다. 같은 원인의 서비스가 더 있었다 같은 서버의 다른 서비스 네 개도 같은 Node.js 버전 문제로 재시작을 반복하고 있었습니다. 두 개는 같은 방법으로 복구했습니다. 다른 하나는 Node.js 버전이 아니라, 프로세스 관리자가 재부팅하면 사라지는 임시 경로를 실행 파일로 붙잡고 있는 것이 원인이어서 설정을 새로 만들어 다시 등록했습니다. 겉으로는 같은 증상이어도 원인이 다를 수 있다는 예입니다. 자동화 도구 한 개는 일부러 켜지 않고 정지 상태로 남겼습니다. 오래 멈춰 있던 자동화 도구를 켜면 잠들어 있던 워크플로가 한꺼번에 실행될 수 있기 때문입니다. 활성 상태였던 워크플로 목록을 먼저 읽기 전용으로 정리하고, 켤 것을 하나씩 정해서 개별로 켜는 순서로 정했습니다. 남긴 교훈 - 503 점검 화면은 「점검 중」의 증거가 아닙니다. 앱이 죽었을 때도 똑같이 보입니다. 서버 안의 프로세스 상태를 봐야 구별됩니다. - 재시작 횟수가 수백만 번까지 쌓이는 동안 알아채지 못했다는 것은, 재시작 횟수에 대한 알림이 없었다는 뜻입니다. - 프레임워크를 올릴 때는 서버의 런타임 버전을 같이 확인해야 합니다. 프로젝트에는 이미 요구 버전(의 20.10.0)이 적혀 있었습니다.
2 days ago