왜 EC2 서버가 갑자기 응답을 멈추는가 — 그리고 Laravel 및 Node 앱을 탄탄하게 만드는 방법
Source: Dev.to
실제로 무슨 일이 있었나요?
내부 조사를 통해, 문제는 서버가 빌드를 로드하지 못하고 시스템이 멈추면서 발생한 것으로 밝혀졌습니다. 누군가가 EC2 인스턴스 안에서 npm run build 혹은 yarn build 를 직접 실행할 경우—특히 RAM이 제한된(1–2 GB) 인스턴스에서는—Node가 프론트엔드 자산을 컴파일하고 최적화하기 위해 많은 메모리를 사용합니다. 메모리 사용량이 증가하면서 서버는 다음과 같은 현상을 보이기 시작합니다:
- 스와핑을 과도하게 수행
- 프로세스 강제 종료
- PHP‑FPM 정지
- Nginx 워커 프로세스 멈춤
- SSH 접속 지연
- 모든 HTTP 요청에 응답 중단
Laravel 앱, Node 앱, 큐 워커, 소켓 서비스가 모두 같은 OS 아래에서 실행되기 때문에, 시스템 전체가 응답하지 않게 됩니다.
왜 Node 빌드가 작은 EC2 인스턴스를 멈추게 할까?
Vite, Webpack, Next.js 같은 Node.js 빌드 도구는 다음과 같은 작업을 위해 많은 메모리를 필요로 합니다:
- 큰 JS 번들 최소화
- 이미지 최적화
- TypeScript 처리
- 트리‑쉐이킹 수행
- 여러 타깃 빌드
메모리가 부족한 서버에서는 다음과 같은 연쇄 반응이 일어납니다:
1. CPU 100 % 사용
Node 컴파일러가 전력으로 실행됩니다.
2. RAM 고갈
단일 빌드에 512 MB – 2 GB 정도의 RAM이 필요할 수 있는데, 이는 작은 EC2 인스턴스에 너무 무겁습니다.
3. OOM(Out‑of‑Memory) 킬
커널이 자동으로 다른 프로세스(예: PHP‑FPM 또는 MySQL)를 Node보다 먼저 종료시킵니다.
4. Nginx 응답 중단
PHP‑FPM이 죽으면 Nginx는 502/504 오류를 반환하거나 완전히 멈춥니다.
5. SSH 지연
스와핑까지 가득 차면 OS가 작업 스케줄링을 중단해 서버에 호스팅된 모든 도메인이 다운됩니다.
앞으로 이 문제를 예방하는 방법
1. 프로덕션·테스트 서버에서 프론트엔드 코드를 절대 빌드하지 않기
- 로컬이나 CI/CD에서 빌드합니다.
- 최종
dist/혹은build/폴더만 업로드합니다. - 컴파일된 자산을 배포합니다.
이 조치만으로도 대부분의 사고를 방지할 수 있습니다.
2. 스와프 파일 추가하기
작은 EC2 인스턴스(예: t2.micro, t3.small)에서는 2 GB 스와프 파일을 생성합니다:
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo "/swapfile swap swap defaults 0 0" | sudo tee -a /etc/fstab
스와프는 메모리가 부족할 때 OS가 크래시되는 것을 방지합니다.
3. Node.js 메모리 사용 제한 (PM2 보호)
앱이 PM2로 실행된다면 메모리 보호 옵션을 적용합니다:
pm2 restart --max-memory-restart=300M
또는 모든 프로세스에 적용:
pm2 restart all --max-memory-restart=300M
이렇게 하면 단일 Node 앱이 전체 메모리를 잡아먹는 일을 방지할 수 있습니다.
4. 고부하 시 PHP‑FPM & Nginx 재시작
서버가 느려지거나 멈출 경우:
sudo systemctl restart php8.1-fpm
sudo systemctl restart nginx
대부분 즉시 서비스가 복구됩니다.
5. htop 으로 실시간 리소스 사용량 모니터링
설치 후 실행:
sudo apt install htop
htop
htop을 통해 어떤 프로세스가 CPU를 많이 쓰는지, 어느 서비스가 RAM을 잡아먹는지, 멈춘 프로세스나 좀비 프로세스가 있는지를 확인할 수 있습니다.
6. PM2 스타트업 설정으로 서버 재부팅 시 Node 앱 자동 재시작
pm2 startup
pm2 save
서버가 재부팅될 때 Node 앱이 자동으로 복구됩니다.
7. 배포 파이프라인 사용
CI/CD 솔루션(GitHub Actions, GitLab CI, Bitbucket Pipelines, Jenkins 등)을 도입해 배포 전에 자산을 빌드하고, 대상 서버에서는 빌드 작업을 절대 수행하지 않도록 합니다.
결론
여러 애플리케이션이 하나의 EC2 인스턴스를 공유할 때, Node 빌드와 같은 무거운 작업이 시스템 자원을 초과 사용하면 전체 머신이 멈추고 모든 도메인과 서비스가 동시에 다운됩니다. 이를 방지하려면 팀이 다음을 실천해야 합니다:
- 서버에서 직접 빌드하지 않기
- 스와프 메모리 추가
- Node 메모리 사용 제한
- 리소스 소비 실시간 모니터링
- CI/CD 파이프라인 활용
이러한 조치를 적용하면 안정적인 성능을 유지하고 개발·테스트·프로덕션 환경에서 갑작스러운 다운타임을 피할 수 있습니다.