서버 접속이 안 될 때 확인해야 할 체크리스트

서버 접속이 안 될 때 확인해야 할 체크리스트

서버에 접속이 안 되면 머릿속이 하얘집니다. 사이트가 안 열리는 건지, SSH가 안 되는 건지, 아니면 서버 자체가 죽은 건지 구분이 안 되고 뭐부터 해야 할지 모르겠습니다. 이런 상황에서 이것저것 무작정 건드리면 오히려 문제가 커질 수 있습니다. 중요한 건 당황하지 않고 체계적으로 하나씩 확인해나가는 것입니다. 이번 글에서는 서버 접속이 안 될 때 확인해야 할 항목들을 순서대로 정리해보겠습니다. 원인을 빠르게 좁혀나갈 수 있도록 바깥쪽부터 안쪽으로 진단하는 흐름입니다.

먼저 문제의 범위를 파악하기

가장 먼저 해야 할 일은 문제가 어디에서 발생하는지 범위를 좁히는 겁니다.

내 컴퓨터에서만 안 되는 건지, 다른 사람도 안 되는 건지 확인합니다. 휴대폰 데이터로 접속해보거나, 다른 네트워크에서 접속을 시도합니다. 나만 안 된다면 내 네트워크나 DNS 캐시 문제일 가능성이 높습니다. 모든 곳에서 안 된다면 서버 쪽 문제입니다.

웹 사이트 접속이 안 되는 건지, SSH 접속이 안 되는 건지도 구분해야 합니다. 웹은 안 되는데 SSH는 되면 Nginx나 앱 서버 문제입니다. 둘 다 안 되면 서버 자체가 다운됐거나 네트워크 단에서 막히고 있는 겁니다.

외부 모니터링 서비스를 이용하는 방법도 있습니다. 웹 브라우저에서 “is it down for everyone” 같은 사이트에 내 도메인을 입력하면 전 세계 여러 지점에서 접속을 테스트해줍니다. 여기서도 안 된다고 나오면 확실히 서버 쪽 문제입니다.

1단계 — DNS 확인

도메인으로 접속하는 경우 가장 먼저 DNS를 확인합니다. 도메인이 올바른 IP를 가리키고 있는지 확인하는 겁니다.

nslookup today-play.com

결과에서 나오는 IP가 내 서버의 IP와 일치하는지 확인합니다. IP가 안 나오거나 엉뚱한 IP가 나오면 DNS 설정에 문제가 있는 겁니다.

DNS 문제일 때 확인해야 할 것들이 있습니다. 도메인 등록 기간이 만료되지 않았는지 확인합니다. 도메인이 만료되면 DNS가 풀리면서 접속이 안 됩니다. 도메인 등록업체 사이트에서 만료일을 확인합니다.

네임서버가 올바르게 설정되어 있는지 확인합니다. Cloudflare로 DNS를 관리하고 있다면 네임서버가 Cloudflare를 가리키고 있어야 합니다. 네임서버를 변경한 직후라면 전파에 시간이 걸릴 수 있습니다.

A레코드가 정확한 IP를 가리키고 있는지 확인합니다. 서버를 새로 만들면서 IP가 바뀌었는데 DNS를 업데이트하지 않은 경우가 의외로 많습니다.

구글 DNS에서도 조회해봅니다.

nslookup today-play.com 8.8.8.8

로컬 DNS에 캐시된 옛날 정보 때문에 문제가 생기는 경우도 있습니다. 구글 DNS에서 정상적으로 나오는데 로컬에서 안 된다면 내 컴퓨터나 공유기의 DNS 캐시를 초기화하면 됩니다.

도메인이 아니라 IP 주소로 직접 접속을 시도해봅니다. 브라우저에 서버 IP를 입력해서 접속이 되면 DNS 문제가 확실합니다. IP로도 안 되면 DNS가 아닌 서버 쪽 문제입니다.

2단계 — 네트워크 연결 확인

DNS가 정상이면 서버까지 네트워크가 연결되는지 확인합니다.

ping -c 5 서버IP

응답이 오면 서버까지 네트워크는 열려 있는 겁니다. 응답이 안 오면 두 가지 가능성이 있습니다. 서버가 진짜 다운됐거나, 서버나 클라우드에서 ICMP 패킷을 차단하고 있는 경우입니다. AWS 같은 클라우드에서는 보안 그룹에서 ICMP를 허용하지 않으면 ping이 안 됩니다. 그래서 ping이 안 된다고 바로 서버가 죽은 거라고 단정하면 안 됩니다.

이전 글에서 다뤘던 traceroute로 경로를 추적합니다.

traceroute 서버IP

어느 구간에서 패킷이 막히는지 확인할 수 있습니다. 내 네트워크 바로 다음 홉에서 막히면 내 ISP 문제이고, 중간 어딘가에서 막히면 경로상의 네트워크 문제이고, 마지막 홉 직전에서 막히면 서버 쪽 방화벽이나 보안 그룹 문제입니다.

특정 포트로의 연결을 직접 테스트하려면 telnet이나 nc 명령어를 사용합니다.

nc -zv 서버IP 80
nc -zv 서버IP 443
nc -zv 서버IP 22

Connection succeeded가 나오면 해당 포트가 열려 있는 겁니다. Connection refused가 나오면 포트가 닫혀 있거나 해당 포트에서 서비스가 실행되고 있지 않은 겁니다. Connection timed out이 나오면 방화벽에서 차단하고 있을 가능성이 높습니다.

3단계 — 클라우드 보안 그룹 확인

클라우드 서비스를 사용하고 있다면 보안 그룹 설정을 확인해야 합니다. 서버의 UFW에서 포트를 열어도 클라우드의 보안 그룹에서 차단하면 접속이 안 됩니다.

AWS EC2를 사용하는 경우 AWS 콘솔에서 해당 인스턴스의 보안 그룹을 확인합니다. 인바운드 규칙에 22번(SSH), 80번(HTTP), 443번(HTTPS)이 허용되어 있는지 확인합니다.

SSH가 안 되는 경우 보안 그룹의 22번 포트 소스가 0.0.0.0/0인지, 아니면 특정 IP로 제한되어 있는지 확인합니다. 집에서 작업하다가 카페로 옮겨서 접속하는데 안 된다면 보안 그룹에 집 IP만 등록되어 있기 때문일 수 있습니다. 내 현재 IP를 추가하면 해결됩니다.

탄력적 IP를 사용하고 있는지도 확인합니다. AWS EC2 인스턴스를 중지했다 시작하면 공인 IP가 바뀝니다. 탄력적 IP를 할당하지 않은 상태에서 인스턴스를 재시작했다면 IP가 변경됐을 수 있습니다. DNS에 등록된 IP와 현재 인스턴스의 IP가 다르면 접속이 안 됩니다.

4단계 — 서버 상태 확인

SSH로 서버에 접속이 가능하다면 서버 내부 상태를 확인합니다. SSH마저 안 된다면 클라우드 콘솔의 시리얼 콘솔이나 웹 터미널로 접속을 시도합니다.

서버에 접속했으면 먼저 서버가 제대로 돌아가고 있는지 기본적인 것부터 확인합니다.

uptime

서버가 최근에 재부팅됐는지 확인할 수 있습니다. 업타임이 몇 분밖에 안 된다면 서버가 재시작됐다는 뜻입니다. 클라우드에서 하드웨어 유지보수 때문에 자동 재시작되는 경우도 있습니다.

디스크 용량을 확인합니다.

df -h

디스크가 100%로 차 있으면 온갖 문제가 발생합니다. 로그를 못 쓰니까 서비스가 멈추고, 데이터베이스가 쓰기를 못 해서 죽고, 심하면 SSH 접속도 느려집니다. 이전 글에서 다뤘던 du 명령어로 어떤 디렉토리가 용량을 차지하는지 찾아서 정리합니다.

메모리 상태를 확인합니다.

free -h

스왑이 거의 다 찼거나 available 메모리가 극도로 적으면 OOM Killer가 프로세스를 종료시켰을 수 있습니다. 이전 글에서 다뤘던 것처럼 dmesg로 확인합니다.

sudo dmesg | grep -i "oom\|killed"

5단계 — 방화벽 확인

서버 자체는 살아있는데 외부에서 특정 포트로 접속이 안 되면 방화벽을 확인합니다.

sudo ufw status

이전 글에서 다뤘던 UFW 설정을 확인합니다. 필요한 포트가 허용되어 있는지 봅니다. UFW가 active 상태인데 규칙에 해당 포트가 없으면 차단되고 있는 겁니다.

실수로 규칙을 잘못 설정해서 SSH까지 차단됐다면 클라우드 콘솔로 접속한 후에 UFW를 비활성화하거나 규칙을 수정합니다.

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'

방화벽 문제인지 확인하는 빠른 방법은 UFW를 임시로 끄고 접속해보는 겁니다.

sudo ufw disable

UFW를 끄니까 접속이 된다면 방화벽 규칙에 문제가 있는 겁니다. 필요한 포트를 허용한 뒤 다시 활성화합니다. 테스트가 끝나면 반드시 다시 켜야 합니다.

sudo ufw enable

6단계 — 웹 서버 확인

SSH는 되는데 웹 사이트가 안 열리면 Nginx를 확인합니다.

Nginx가 실행 중인지 확인합니다.

sudo systemctl status nginx

active (running)이 아니면 Nginx가 꺼져 있는 겁니다. 시작합니다.

sudo systemctl start nginx

시작에 실패한다면 설정 파일에 문법 에러가 있을 수 있습니다.

sudo nginx -t

에러 메시지가 나오면 해당 파일의 해당 줄을 확인해서 수정합니다.

Nginx가 실행 중인데도 접속이 안 되면 Nginx가 올바른 포트에서 리스닝하고 있는지 확인합니다.

sudo ss -tlnp | grep nginx

80번과 443번 포트에서 리스닝하고 있어야 합니다.

에러 로그도 확인합니다.

sudo tail -50 /var/log/nginx/error.log

로그에 구체적인 에러 메시지가 있으면 원인을 더 빠르게 파악할 수 있습니다.

7단계 — 앱 서버 확인

Nginx가 정상인데 502 에러가 나오면 이전 글에서 다뤘던 것처럼 뒤쪽 앱 서버를 확인합니다.

pm2 list

앱이 online 상태인지 확인합니다. 꺼져 있으면 재시작하고 로그에서 에러 원인을 확인합니다.

pm2 logs 앱이름

앱이 실행 중이라면 올바른 포트에서 돌아가고 있는지 확인합니다.

ss -tlnp | grep node

Nginx 설정의 proxy_pass 포트와 일치하는지 확인합니다.

앱에 직접 요청을 보내서 응답하는지 테스트합니다.

curl http://localhost:3000

여기서 정상 응답이 오면 앱 자체는 문제없고 Nginx 설정 쪽을 다시 봐야 합니다. 여기서도 응답이 안 오면 앱 내부에 문제가 있는 겁니다.

8단계 — SSL 인증서 확인

HTTPS로 접속할 때만 문제가 생기고 HTTP로는 되는 경우 SSL 인증서를 확인합니다.

sudo certbot certificates

인증서의 만료일을 확인합니다. 만료됐으면 갱신합니다.

sudo certbot renew

이전 글에서 다뤘던 자동 갱신이 제대로 동작하고 있는지도 확인합니다.

sudo systemctl status certbot.timer

브라우저에서 “이 연결은 안전하지 않습니다” 같은 경고가 나온다면 인증서가 만료됐거나 인증서의 도메인이 접속하려는 도메인과 일치하지 않는 경우입니다. www를 포함하지 않고 인증서를 발급받았는데 www로 접속하면 이런 문제가 생길 수 있습니다.

9단계 — 데이터베이스 확인

사이트는 열리는데 특정 페이지에서 에러가 나거나 로딩이 안 끝나면 데이터베이스를 확인합니다.

sudo systemctl status mysql

데이터베이스가 꺼져 있으면 시작합니다.

sudo systemctl start mysql

실행 중인데 앱에서 연결이 안 되면 접속 정보를 확인합니다.

mysql -u 사용자명 -p -h localhost

직접 접속이 되면 앱의 환경 변수에 적힌 접속 정보와 비교합니다. 비밀번호가 바뀌었거나, 데이터베이스 이름이 틀렸거나, 호스트가 잘못 설정된 경우가 있습니다.

빠른 진단 체크리스트

위 내용을 상황별로 빠르게 확인할 수 있도록 정리하겠습니다.

SSH 접속이 안 될 때 확인하는 순서입니다. 서버 IP가 맞는지 확인합니다. 클라우드 보안 그룹에서 22번 포트가 열려 있는지 확인합니다. UFW에서 SSH가 허용되어 있는지 확인합니다. SSH 키 파일이 맞는지, 권한이 600인지 확인합니다. 클라우드 콘솔로 접속해서 서버가 살아있는지 확인합니다.

웹 사이트가 안 열릴 때 확인하는 순서입니다. DNS가 올바른 IP를 가리키는지 nslookup으로 확인합니다. 서버 IP로 직접 접속해봅니다. 보안 그룹에서 80번과 443번 포트가 열려 있는지 확인합니다. UFW에서 해당 포트가 허용되어 있는지 확인합니다. Nginx가 실행 중인지 확인합니다. 앱 서버가 실행 중인지 확인합니다. Nginx 에러 로그를 확인합니다.

사이트가 느리거나 간헐적으로 안 될 때 확인하는 순서입니다. 서버 리소스 상태를 htop으로 확인합니다. 디스크 용량을 df -h로 확인합니다. 앱 로그에서 에러가 반복되고 있는지 확인합니다. 데이터베이스 연결과 쿼리 상태를 확인합니다. Nginx 액세스 로그에서 비정상적인 트래픽이 있는지 확인합니다.

예방을 위해 해둘 것들

문제가 터진 뒤에 진단하는 것도 중요하지만 미리 대비해두는 게 더 좋습니다.

모니터링 알림을 설정해둡니다. 서버가 다운되면 알림을 받을 수 있도록 외부 모니터링 서비스를 연결해둡니다. UptimeRobot 같은 무료 서비스에 도메인을 등록하면 사이트가 안 열릴 때 이메일이나 슬랙으로 알림을 보내줍니다. 사용자가 알려주기 전에 내가 먼저 알 수 있습니다.

서버 접속 정보를 정리해둡니다. 서버 IP, SSH 키 파일 위치, 클라우드 콘솔 로그인 정보, 도메인 관리 페이지 접속 정보를 한곳에 정리해둡니다. 문제가 터졌을 때 이 정보를 찾느라 시간을 낭비하는 경우가 의외로 많습니다.

정기적으로 백업을 합니다. 서버가 완전히 복구 불가능한 상태가 되더라도 백업이 있으면 새 서버에 복원할 수 있습니다. 데이터베이스 백업은 이전 글에서 다뤘던 크론탭으로 자동화해두는 게 좋습니다.

마무리

서버 접속이 안 될 때 가장 중요한 건 순서대로 확인하는 것입니다. DNS부터 시작해서 네트워크, 보안 그룹, 방화벽, 웹 서버, 앱 서버, 데이터베이스 순서로 바깥에서 안쪽으로 좁혀가면 대부분의 문제를 찾을 수 있습니다. 처음에는 이 과정이 오래 걸리지만 몇 번 경험하면 몸에 익어서 빠르게 대응할 수 있게 됩니다. 이번 글에서 다룬 체크리스트를 어딘가에 저장해두고 필요할 때 꺼내 보시길 권합니다. 서버가 안 될 때 멘탈을 잡아주는 건 경험과 체크리스트입니다.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *