🖥️ 로컬 서버 관리 및 종료 가이드

이런 분들을 위한 가이드

  • “포트 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 :8080

Windows (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,5000

Windows

# 포트 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 start

3. 서버 안전하게 종료

✅ 정상 종료 (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 -15kill -9
프로세스 반응정리 작업 후 종료즉시 종료
DB 연결정상 종료끊김
파일 저장완료 후 종료손실 가능
사용 시기일반적인 경우응답 없을 때

📋 권장 종료 순서

# 1단계: 정상 종료 시도
kill 12345
 
# 5초 대기
sleep 5
 
# 2단계: 아직 살아있는지 확인
ps -p 12345
 
# 3단계: 살아있으면 강제 종료
if ps -p 12345 > /dev/null; then
  echo "프로세스가 종료되지 않아 강제 종료합니다."
  kill -9 12345
fi

5. 자주 사용하는 포트 목록

📊 개발 서버 기본 포트

포트용도프레임워크/도구
3000React 개발 서버Create React App, Next.js
3001React 대체 포트CRA (포트 충돌 시)
4000GraphQLApollo Server
4200AngularAngular CLI
5000FlaskFlask 기본 포트
5173ViteVite 개발 서버
8000DjangoDjango 개발 서버
8080일반 웹 서버Tomcat, Spring Boot
8888JupyterJupyter Notebook
9000PHPPHP 개발 서버

🗄️ 데이터베이스 포트

포트데이터베이스
3306MySQL, MariaDB
5432PostgreSQL
5433PostgreSQL (대체, macOS Homebrew)
27017MongoDB
6379Redis

🔧 기타 개발 도구

포트도구
1313Hugo
2368Ghost
3333AdonisJS
4000Quartz (Static Site)
4567Sinatra
5001ASP.NET Core
8545Ganache (Ethereum)
9090Prometheus

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 -u

Windows용

# 포트 확인
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 200000

8. 자동화 스크립트

🤖 포트 종료 스크립트

📄 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

  1. 포트 확인 후 시작

    # 서버 시작 전 포트 확인
    lsof -i :3000 || npm start
  2. 환경 변수로 포트 설정

    # .env 파일
    PORT=3001
  3. 프로세스 매니저 사용

    # 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
  4. 개발 환경과 운영 환경 포트 분리

    Dev: 3000
    Staging: 3001
    Prod: 80 (nginx) → 8080 (app)
    

❌ Don’t

  1. 포트 1024 미만에서 직접 실행 금지

    # ❌ 위험
    sudo node app.js
  2. kill -9를 첫 번째 선택지로 사용 금지

    # ❌ 나쁜 습관
    kill -9 $(lsof -ti :3000)
     
    # ✅ 올바른 방법
    kill $(lsof -ti :3000)
    # 기다렸다가...
    kill -9 $(lsof -ti :3000)  # 안 될 때만
  3. pkill node 같은 광범위한 종료 금지

    # ❌ 위험: VSCode, Electron 앱까지 종료됨
    pkill node

🔗 관련 도구

📦 추천 도구

  1. htop (프로세스 모니터링)

    # macOS
    brew install htop
     
    # 실행
    htop
  2. PM2 (Node.js 프로세스 매니저)

    npm install -g pm2
     
    pm2 start app.js
    pm2 monit
  3. lsof (이미 설치됨, macOS/Linux)

  4. 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: 참고자료/서버관리