🖥️ 로컬 서버 관리 및 종료 가이드
이런 분들을 위한 가이드
- “포트 3000이 이미 사용 중입니다” 에러를 본 적이 있다면
- 서버를 끄고 싶은데 터미널을 닫아버렸다면
- 어떤 프로세스가 포트를 점유하고 있는지 모르겠다면
📑 목차
1. 실행 중인 서버 확인
🔍 모든 실행 중인 개발 서버 확인
macOS / Linux
# 방법 1: 프로세스 이름으로 찾기
ps aux | grep -E "(node|npm|python|django|flask|rails|quartz)" | grep -v grep
# 방법 2: 포트로 찾기 (LISTEN 상태)
lsof -i -P | grep LISTEN
# 방법 3: 특정 포트만 확인
lsof -i :3000
lsof -i :8080Windows (PowerShell)
# 포트로 찾기
netstat -ano | findstr "LISTENING"
# 특정 포트
netstat -ano | findstr ":3000"📊 출력 결과 읽는 법
# macOS/Linux lsof 출력 예시
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 12345 a1234 23u IPv6 0x123456789abcdef 0t0 TCP *:3000 (LISTEN)
python 67890 a1234 4u IPv4 0xfedcba987654321 0t0 TCP *:8000 (LISTEN)읽는 법:
COMMAND: 프로세스 이름 (node, python 등)PID: 프로세스 ID (종료할 때 필요!)USER: 실행한 사용자*:3000: 모든 인터페이스에서 포트 3000 수신LISTEN: 연결 대기 중
2. 포트별 프로세스 찾기
🎯 특정 포트 점유 프로세스 찾기
macOS / Linux
# 포트 3000 사용 중인 프로세스 찾기
lsof -i :3000
# 간단한 버전 (PID만)
lsof -ti :3000
# 여러 포트 동시 확인
lsof -i :3000,8080,5000Windows
# 포트 3000 사용 중인 프로세스 찾기
netstat -ano | findstr ":3000"
# PID로 프로세스 이름 확인
tasklist | findstr "12345"🔍 실전 예제
문제 상황:
$ npm start
> my-app@1.0.0 start
> react-scripts start
? Something is already running on port 3000.
Would you like to run the app on another port instead? › (Y/n)해결:
# 1. 어떤 프로세스가 3000번 포트를 쓰고 있는지 확인
lsof -i :3000
# 출력:
# COMMAND PID USER
# node 12345 a1234
# 2. 해당 프로세스 종료 (방법은 다음 섹션 참고)
kill 12345
# 3. 다시 서버 시작
npm start3. 서버 안전하게 종료
✅ 정상 종료 (Graceful Shutdown)
방법 1: 터미널에서 실행 중인 경우
# Ctrl + C 누르기
# (대부분의 서버는 이 신호를 받아서 정리 작업 후 종료)
# 터미널 출력 예시:
^C
Shutting down server...
Closing database connections...
Server stopped gracefully.방법 2: PID를 알고 있는 경우
# SIGTERM (정상 종료 신호)
kill 12345
# 또는 명시적으로
kill -15 12345
kill -TERM 12345방법 3: 프로세스 이름으로 종료
# pkill (이름으로 종료)
pkill node # 모든 node 프로세스 종료 (주의!)
pkill -f "npm" # npm 관련 프로세스 종료
# 특정 프로세스만 안전하게 종료
pkill -f "my-app"⚠️ 주의사항
# ❌ 위험: 모든 node 프로세스 종료
pkill node
# 문제: 다른 node 앱까지 모두 종료됨!
# 예: VSCode Extension, Electron 앱 등
# ✅ 안전: 특정 프로세스만 종료
kill 12345 # PID로 정확히 지정4. 강제 종료
💥 SIGKILL (강제 종료)
언제 사용하나?
- 정상 종료(
kill)가 먹히지 않을 때- 프로세스가 멈춰서 응답하지 않을 때 (Hang)
- 최후의 수단! 데이터 손실 가능
macOS / Linux
# 방법 1: kill -9
kill -9 12345
# 방법 2: kill -KILL
kill -KILL 12345
# 방법 3: pkill -9
pkill -9 -f "my-app"Windows
# 프로세스 강제 종료
taskkill /PID 12345 /F
# 프로세스 이름으로 강제 종료
taskkill /IM node.exe /F🔄 정상 종료 vs 강제 종료
| 항목 | 정상 종료 (SIGTERM) | 강제 종료 (SIGKILL) |
|---|---|---|
| 신호 | kill or kill -15 | kill -9 |
| 프로세스 반응 | 정리 작업 후 종료 | 즉시 종료 |
| DB 연결 | 정상 종료 | 끊김 |
| 파일 저장 | 완료 후 종료 | 손실 가능 |
| 사용 시기 | 일반적인 경우 | 응답 없을 때 |
📋 권장 종료 순서
# 1단계: 정상 종료 시도
kill 12345
# 5초 대기
sleep 5
# 2단계: 아직 살아있는지 확인
ps -p 12345
# 3단계: 살아있으면 강제 종료
if ps -p 12345 > /dev/null; then
echo "프로세스가 종료되지 않아 강제 종료합니다."
kill -9 12345
fi5. 자주 사용하는 포트 목록
📊 개발 서버 기본 포트
| 포트 | 용도 | 프레임워크/도구 |
|---|---|---|
| 3000 | React 개발 서버 | Create React App, Next.js |
| 3001 | React 대체 포트 | CRA (포트 충돌 시) |
| 4000 | GraphQL | Apollo Server |
| 4200 | Angular | Angular CLI |
| 5000 | Flask | Flask 기본 포트 |
| 5173 | Vite | Vite 개발 서버 |
| 8000 | Django | Django 개발 서버 |
| 8080 | 일반 웹 서버 | Tomcat, Spring Boot |
| 8888 | Jupyter | Jupyter Notebook |
| 9000 | PHP | PHP 개발 서버 |
🗄️ 데이터베이스 포트
| 포트 | 데이터베이스 |
|---|---|
| 3306 | MySQL, MariaDB |
| 5432 | PostgreSQL |
| 5433 | PostgreSQL (대체, macOS Homebrew) |
| 27017 | MongoDB |
| 6379 | Redis |
🔧 기타 개발 도구
| 포트 | 도구 |
|---|---|
| 1313 | Hugo |
| 2368 | Ghost |
| 3333 | AdonisJS |
| 4000 | Quartz (Static Site) |
| 4567 | Sinatra |
| 5001 | ASP.NET Core |
| 8545 | Ganache (Ethereum) |
| 9090 | Prometheus |
6. 치트시트 (명령어 모음)
🚀 빠른 참조
실행 중인 서버 확인
# macOS/Linux
lsof -i -P | grep LISTEN
# 특정 포트
lsof -i :3000
# PID만 추출
lsof -ti :3000서버 종료
# 정상 종료
kill $(lsof -ti :3000)
# 강제 종료
kill -9 $(lsof -ti :3000)
# 모든 node 프로세스 종료 (주의!)
pkill node포트 사용 현황
# 모든 LISTEN 포트
lsof -i -P | grep LISTEN
# 특정 프로세스의 포트
lsof -Pan -p 12345 -i
# 사용 중인 모든 포트 번호만
lsof -i -P | grep LISTEN | awk '{print $9}' | cut -d: -f2 | sort -uWindows용
# 포트 확인
netstat -ano | findstr "LISTENING"
# 특정 포트
netstat -ano | findstr ":3000"
# 프로세스 종료
taskkill /PID 12345
taskkill /PID 12345 /F # 강제7. 트러블슈팅
🔥 문제 1: “Address already in use”
에러 메시지:
Error: listen EADDRINUSE: address already in use :::3000
원인:
- 다른 프로세스가 이미 3000번 포트를 사용 중
해결:
# 1. 어떤 프로세스가 사용 중인지 확인
lsof -i :3000
# 2-A. 해당 프로세스 종료
kill $(lsof -ti :3000)
# 2-B. 또는 다른 포트 사용
PORT=3001 npm start🔥 문제 2: “Permission denied” (포트 1024 미만)
에러 메시지:
Error: listen EACCES: permission denied 0.0.0.0:80
원인:
- 1024번 미만 포트는 관리자 권한 필요
해결:
# ❌ 나쁜 방법: sudo 사용
sudo node app.js # 보안 위험!
# ✅ 좋은 방법: 1024번 이상 포트 사용
PORT=8080 node app.js
# ✅ 또는 리버스 프록시 사용 (nginx)
# nginx가 80번 포트를 듣고, 8080으로 프록시🔥 문제 3: 좀비 프로세스 (Zombie Process)
증상:
- 프로세스가 종료되지 않음
ps aux에서<defunct>또는Z상태
해결:
# 1. 좀비 프로세스 확인
ps aux | grep defunct
# 2. 부모 프로세스 찾기
ps -o ppid= -p 12345
# 3. 부모 프로세스 종료
kill 67890 # 부모 PID🔥 문제 4: 터미널을 닫았는데 서버가 계속 돌아감
원인:
- 백그라운드에서 실행됨
nohup,screen,tmux등 사용
해결:
# 1. 실행 중인 프로세스 찾기
ps aux | grep node
# 2. 종료
kill 12345
# 또는 포트로 찾아서 종료
kill $(lsof -ti :3000)🔥 문제 5: “Too many open files”
에러 메시지:
Error: EMFILE: too many open files
원인:
- 시스템의 파일 디스크립터 제한 초과
해결:
# macOS: 현재 제한 확인
ulimit -n
# 임시로 늘리기 (현재 세션만)
ulimit -n 4096
# 영구 설정 (macOS)
sudo launchctl limit maxfiles 65536 2000008. 자동화 스크립트
🤖 포트 종료 스크립트
📄 kill-port.sh (macOS/Linux)
#!/bin/bash
# 사용법: ./kill-port.sh 3000
if [ -z "$1" ]; then
echo "Usage: $0 <port>"
echo "Example: $0 3000"
exit 1
fi
PORT=$1
# 해당 포트를 사용하는 프로세스 찾기
PID=$(lsof -ti :$PORT)
if [ -z "$PID" ]; then
echo "✅ 포트 $PORT 는 사용 중이 아닙니다."
exit 0
fi
# 프로세스 정보 출력
echo "🔍 포트 $PORT 를 사용하는 프로세스:"
lsof -i :$PORT
# 종료 확인
read -p "⚠️ 위 프로세스를 종료하시겠습니까? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
# 정상 종료 시도
echo "📡 정상 종료 신호 전송..."
kill $PID
sleep 2
# 아직 살아있는지 확인
if ps -p $PID > /dev/null 2>&1; then
echo "⚠️ 프로세스가 종료되지 않아 강제 종료합니다..."
kill -9 $PID
fi
echo "✅ 프로세스 종료 완료!"
else
echo "❌ 취소되었습니다."
fi사용법:
# 실행 권한 부여
chmod +x kill-port.sh
# 포트 3000 종료
./kill-port.sh 3000🤖 모든 개발 서버 확인 스크립트
📄 check-dev-servers.sh
#!/bin/bash
echo "🔍 실행 중인 개발 서버 확인..."
echo ""
# 개발 서버 프로세스 찾기
PROCESSES=$(ps aux | grep -E "(node|npm|python|django|flask|rails|quartz)" | grep -v grep | grep -v "$0")
if [ -z "$PROCESSES" ]; then
echo "✅ 실행 중인 개발 서버가 없습니다."
else
echo "📊 실행 중인 개발 서버:"
echo "$PROCESSES" | awk '{printf " PID: %-6s User: %-10s Command: %s\n", $2, $1, substr($0, index($0,$11))}'
fi
echo ""
echo "🔌 사용 중인 포트:"
lsof -i -P | grep LISTEN | awk '{print " Port: " $9 " Process: " $1 " (PID: " $2 ")"}' | sort -u사용법:
chmod +x check-dev-servers.sh
./check-dev-servers.sh🤖 포트별 일괄 종료 스크립트
📄 kill-all-dev-servers.sh
#!/bin/bash
echo "⚠️ 모든 개발 서버를 종료합니다."
read -p "계속하시겠습니까? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "❌ 취소되었습니다."
exit 0
fi
# 개발 포트 목록
DEV_PORTS=(3000 3001 4000 5000 8000 8080)
for PORT in "${DEV_PORTS[@]}"; do
PID=$(lsof -ti :$PORT)
if [ ! -z "$PID" ]; then
echo "🔪 포트 $PORT (PID: $PID) 종료 중..."
kill $PID
fi
done
echo "✅ 완료!"🤖 서버 상태 모니터링 (실시간)
📄 monitor-ports.sh
#!/bin/bash
# 모니터링할 포트
PORTS=(3000 5000 8000 8080)
echo "📊 포트 모니터링 시작... (Ctrl+C로 종료)"
echo ""
while true; do
clear
echo "=== 포트 상태 모니터링 ==="
echo "시간: $(date '+%Y-%m-%d %H:%M:%S')"
echo ""
for PORT in "${PORTS[@]}"; do
PID=$(lsof -ti :$PORT)
if [ -z "$PID" ]; then
echo "❌ 포트 $PORT: 사용 안 함"
else
PROCESS=$(ps -p $PID -o comm= 2>/dev/null)
echo "✅ 포트 $PORT: $PROCESS (PID: $PID)"
fi
done
sleep 2
done💡 베스트 프랙티스
✅ Do
-
포트 확인 후 시작
# 서버 시작 전 포트 확인 lsof -i :3000 || npm start -
환경 변수로 포트 설정
# .env 파일 PORT=3001 -
프로세스 매니저 사용
# PM2 (Node.js) pm2 start app.js --name my-app pm2 stop my-app pm2 list # systemd (Linux) sudo systemctl start my-service sudo systemctl stop my-service -
개발 환경과 운영 환경 포트 분리
Dev: 3000 Staging: 3001 Prod: 80 (nginx) → 8080 (app)
❌ Don’t
-
포트 1024 미만에서 직접 실행 금지
# ❌ 위험 sudo node app.js -
kill -9를 첫 번째 선택지로 사용 금지# ❌ 나쁜 습관 kill -9 $(lsof -ti :3000) # ✅ 올바른 방법 kill $(lsof -ti :3000) # 기다렸다가... kill -9 $(lsof -ti :3000) # 안 될 때만 -
pkill node같은 광범위한 종료 금지# ❌ 위험: VSCode, Electron 앱까지 종료됨 pkill node
🔗 관련 도구
📦 추천 도구
-
htop (프로세스 모니터링)
# macOS brew install htop # 실행 htop -
PM2 (Node.js 프로세스 매니저)
npm install -g pm2 pm2 start app.js pm2 monit -
lsof (이미 설치됨, macOS/Linux)
-
netstat (네트워크 통계)
netstat -an | grep LISTEN
📚 참고 자료
🎯 요약
기본 3단 콤보
# 1. 어떤 프로세스가 포트를 쓰는지 확인
lsof -i :3000
# 2. 정상 종료
kill <PID>
# 3. (안 되면) 강제 종료
kill -9 <PID>원라이너 (한 줄로 종료)
# 정상 종료
kill $(lsof -ti :3000)
# 강제 종료
kill -9 $(lsof -ti :3000)Created: 2025-12-31 Tags: server process port troubleshooting devops Category: 참고자료/서버관리