
npm run dev를 실행했는데 "Error: listen EADDRINUSE: address already in use :::3000" 메시지가 뜨면서 서버가 켜지지 않나요. 스프링 부트라면 "Port 8080 was already in use", 파이썬이라면 "Address already in use"로 보이는데요. 메시지만 다를 뿐 원인은 모두 같습니다. 그 포트를 이미 다른 프로그램이 붙잡고 있다는 뜻이고, 누가 쓰는지 찾아서 끄거나 포트를 바꾸면 바로 해결됩니다.
■ 한눈에 보는 결론
가장 흔한 원인은 예전에 띄운 개발 서버가 다른 터미널이나 백그라운드에 그대로 살아 있는 경우입니다. 윈도우는 netstat -ano로 PID를 찾아 taskkill로 끄고, 맥과 리눅스는 lsof -i로 찾아 kill로 끄면 됩니다. 끄기 곤란한 프로그램이라면 내 서버의 포트 번호를 3001이나 8081처럼 바꿔 실행하는 편이 더 빠릅니다.
■ 이 오류가 생기는 이유
하나의 포트에는 한 번에 한 프로그램만 접속을 기다릴 수 있습니다. 그래서 이미 누군가 3000번을 쓰고 있으면 새 서버는 자리를 얻지 못하고 바로 종료됩니다. 터미널 창만 닫고 서버는 남아 있는 경우, Ctrl+Z를 눌러 서버를 끈 줄 알았지만 실제로는 일시정지만 된 경우, 도커 컨테이너가 같은 포트를 열어 둔 경우가 대표적입니다. 의외의 범인도 있는데요. 맥에서는 AirPlay 수신 모드가 5000번과 7000번 포트를 쓰기 때문에 Flask 기본 포트인 5000번과 자주 부딪힙니다.

■ 1. 윈도우에서 포트 쓰는 프로세스 끄기
명령 프롬프트나 PowerShell을 열고 아래처럼 포트 번호로 검색합니다. 결과 줄 맨 끝 숫자가 PID입니다.
netstat -ano | findstr :3000
taskkill /PID 12345 /F
PID 자리에는 방금 확인한 숫자를 넣습니다. 접근이 거부되면 관리자 권한으로 터미널을 다시 열어 실행하세요. 작업 관리자의 세부 정보 탭에서 같은 PID를 찾아 작업 끝내기를 눌러도 결과는 같습니다.
■ 2. 맥·리눅스에서 포트 쓰는 프로세스 끄기
터미널에서 lsof로 해당 포트를 쓰는 프로그램과 PID를 확인한 뒤 kill로 종료합니다.
lsof -i :3000
kill 12345
일반 kill로 꺼지지 않을 때만 kill -9를 쓰세요. 다른 사용자나 시스템이 띄운 프로세스라면 앞에 sudo가 필요합니다. 리눅스에서는 sudo ss -ltnp | grep :3000으로도 같은 정보를 볼 수 있고, 맥이라면 시스템 설정의 일반 메뉴에 있는 AirDrop 및 Handoff에서 AirPlay 수신 모드를 끄면 5000번 충돌이 사라집니다.
■ 3. 끄기 어렵다면 포트 번호 바꾸기
다른 프로젝트 서버를 함께 켜 둬야 하거나 시스템 프로그램이 쓰는 포트라면 내 쪽 포트를 옮기는 것이 깔끔합니다. Next.js는 next dev -p 3001, 스프링 부트는 application.properties에 server.port=8081, Flask는 flask run --port 5001처럼 지정하면 됩니다. Vite는 기본 포트가 사용 중이면 다음 번호로 알아서 넘어가는데, 반드시 같은 포트를 써야 한다면 strictPort 옵션을 켜 두세요.
■ 4. 도커 컨테이너도 확인하기
프로세스 목록에 node나 java가 보이지 않는데도 포트가 막혀 있다면 도커를 의심해 보세요. docker ps로 실행 중인 컨테이너의 PORTS 칸을 보고, 같은 포트를 연 컨테이너가 있으면 docker stop으로 멈춥니다. docker compose로 띄웠다면 해당 폴더에서 docker compose down을 실행하면 한 번에 정리됩니다.
■ 운영체제별 명령 정리표
| 환경 | 포트 사용 프로세스 찾기 | 종료 명령 |
| 윈도우 | netstat -ano | findstr :3000 | taskkill /PID 번호 /F |
| 맥 | lsof -i :3000 | kill 번호 |
| 리눅스 | sudo ss -ltnp | grep :3000 | kill 번호 |
| 도커 | docker ps | docker stop 컨테이너명 |
■ 실무에서 자주 놓치는 팁
개발 서버는 Ctrl+C로 끄는 습관을 들여보세요. 맥과 리눅스에서 Ctrl+Z는 프로그램을 멈춰 둘 뿐이라 포트를 계속 잡고 있고, jobs로 확인한 뒤 fg로 다시 불러와 Ctrl+C를 눌러야 완전히 꺼집니다. VS Code 터미널 패널을 닫을 때도 휴지통 아이콘으로 터미널을 종료해야 안의 서버가 함께 꺼집니다. 이 작업이 자주 반복된다면 npx kill-port 3000처럼 포트 번호만으로 정리해 주는 도구를 써도 편합니다. 프로젝트마다 포트를 3000, 3001, 8080처럼 미리 나눠 두면 여러 서버를 동시에 켜도 충돌이 줄어듭니다.

■ FAQ
Q. PID를 찾았는데 System이나 svchost로 나와요.
A. 윈도우 시스템 서비스가 쓰는 포트일 가능성이 큽니다. 억지로 끄면 다른 기능이 멈출 수 있으니 내 서버의 포트 번호를 바꾸는 쪽을 추천합니다.
Q. netstat 결과가 아무것도 안 나오는데 오류가 나요.
A. 윈도우에서는 Hyper-V나 WSL이 일부 포트 구간을 예약해 두기도 합니다. netsh interface ipv4 show excludedportrange protocol=tcp로 예약 구간을 확인하고, 그 범위를 피해 포트를 고르세요.
Q. kill로 껐는데 서버가 다시 살아나요.
A. nodemon, pm2, 도커 재시작 정책처럼 프로세스를 자동으로 다시 띄우는 도구가 있는지 확인하세요. 그 도구를 먼저 멈춰야 포트가 비워집니다.
Q. 재부팅하면 해결되나요.
A. 대부분 해결되지만 원인을 모르면 같은 일이 반복됩니다. 위 명령으로 어떤 프로그램이 포트를 잡는지 한 번 확인해 두는 편이 장기적으로 시간을 아낍니다.
■ 같이 보면 좋은 글
관련: VS Code Git not found 해결과 git.path 설정
관련: pip externally-managed-environment 오류 해결
관련: 도커 컨테이너 포트 매핑 기초 정리
정리하면 포트 충돌은 누가 그 포트를 쓰는지 확인하고, 끄거나 내 포트를 옮기는 두 가지로 끝납니다. 명령 두 줄만 기억해 두면 다음부터는 1분 안에 해결할 수 있습니다.