TechFeedTechFeed
개발자 작업환경

EADDRINUSE, 포트 이미 사용 중, 프로세스 종료 | 3000번이 안 죽으면 뭐부터 볼까?

EADDRINUSE address already in use는 코드가 틀린 게 아니라 쓰려는 포트를 이미 다른 프로세스가 쥐고 있어서 서버가 바인딩을 못 하는 것이다. lsof -i :3000·netstat -ano로 PID를 찾고, kill·kill -9·taskkill /F·npx kill-port로 그 하나만 종료한다. nodemon·pm2·도커가 자꾸 되살리는 경우, TIME_WAIT, PORT 환경변수와 next dev -p로 포트 옮기기, Ctrl+C 정상 종료 예방까지. 개발자, Next.js, 노드, 백엔드, 터미널 기준. 2026년 8월 Node.js·마이크로소프트 문서.

by

EADDRINUSE는 코드가 틀린 게 아니라, 쓰려는 포트를 이미 다른 프로세스가 붙잡고 있어서 서버가 그 자리에 못 앉는 상황입니다. 그러니 코드를 고칠 게 아니라 포트를 쥔 프로세스를 찾아 정리하는 게 먼저예요.


개발 서버를 껐다가 다시 켰을 뿐인데 Error: listen EADDRINUSE: address already in use :::3000이 뜨는 일, 한 번쯤 겪으셨을 겁니다. 터미널을 강제로 닫았거나, 서버가 깔끔히 안 죽었거나, 다른 창에서 같은 포트를 이미 쓰고 있을 때 흔히 나오죠.


아래에서는 이 에러가 왜 나는지, 어떤 프로세스가 포트를 잡고 있는지 찾는 법, 맥·리눅스와 윈도우에서 그 프로세스를 종료하는 명령, 죽여도 자꾸 되살아날 때 볼 자리, 그리고 Next.js 같은 개발 서버에서 실전 순서까지 짚어 봅니다. 로컬에서 혼자 여러 프로젝트를 띄워 두고 개발하시는 분이라면 자주 만나는 상황이죠. 같은 빨간 줄 앞에서 뭐부터 눌러야 할지 막막하셨다면 도움이 되실 거예요. 근거는 Node.js 공식 문서마이크로소프트 taskkill 문서에 뒀습니다.


EADDRINUSE는 왜 뜨나

EADDRINUSE는 "주소가 이미 사용 중"이라는 뜻입니다. 서버가 특정 포트에서 요청을 받으려고 listen을 부르는 순간, 운영체제가 그 포트는 이미 다른 프로세스에 배정돼 있다며 거절한 것이죠. Node.js 문서도 이 에러를 서버가 이미 점유된 주소에 바인딩하려 할 때 나는 시스템 에러로 설명합니다.


가장 흔한 경우는 같은 서버가 두 번 켜진 상황입니다. 이전에 띄운 개발 서버가 완전히 안 죽었는데 새로 npm run dev를 돌리면, 앞 프로세스가 여전히 3000번을 쥐고 있어서 뒤 프로세스가 자리를 못 잡습니다. 터미널을 강제로 닫거나 노트북이 절전에서 깨어난 뒤에 자주 생기죠.


덜 흔하지만 헷갈리는 경우도 있습니다. 도커 컨테이너나 다른 도구가 몰래 같은 포트를 열어 두었거나, 앞서 죽인 프로세스가 소켓을 TIME_WAIT 상태로 잠깐 붙들고 있는 경우예요. 그래서 "분명히 껐는데 왜 안 되지" 싶을 때는 코드가 아니라 그 포트를 누가 쥐고 있는지부터 확인해야 합니다.


먼저 읽을 것 | 에러 메시지에는 항상 막힌 포트 번호가 :::3000처럼 함께 적혀 있습니다. :::는 IPv6, 0.0.0.0:3000은 IPv4 표기예요. 어떤 포트가 문제인지 그 숫자부터 확인하면 다음 단계가 빨라집니다.


개발 서버가 이미 점유된 포트에 바인딩하려다 EADDRINUSE 에러를 내는 터미널 개념 이미지
포트를 이미 쥔 프로세스가 있으면 새 서버는 그 자리에 못 앉는다

어떤 프로세스가 포트를 잡고 있는지 찾기

포트를 쥔 프로세스를 먼저 찾아야 안전하게 종료할 수 있습니다. 무턱대고 노드 프로세스를 전부 죽이면 다른 프로젝트 서버까지 함께 꺼질 수 있으니, 문제의 포트 하나만 겨냥하는 편이 낫습니다.


맥과 리눅스에서는 lsof가 가장 빠릅니다. lsof -i :3000을 치면 그 포트를 여는 프로세스의 이름과 PID(프로세스 번호)가 나옵니다. PID만 바로 뽑고 싶다면 lsof -ti :3000을 쓰면 됩니다. 윈도우에서는 netstat -ano | findstr :3000으로 확인하는데, 줄 끝에 붙는 숫자가 PID입니다.


운영체제확인 명령보는 값
맥 · 리눅스lsof -i :3000프로세스 이름과 PID
맥 · 리눅스 (PID만)lsof -ti :3000PID 숫자만
윈도우netstat -ano | findstr :3000줄 끝 숫자가 PID
윈도우 (파워셸)Get-NetTCPConnection -LocalPort 3000OwningProcess가 PID

PID를 확인했다면 그게 정말 내 개발 서버가 맞는지 이름을 한 번 봐 두면 좋습니다. 엉뚱한 시스템 프로세스를 종료하면 다른 문제가 생길 수 있으니까요.


맥 · 리눅스에서 포트 3000 확인
# 포트 3000을 쓰는 프로세스 보기 lsof -i :3000 # 예시 출력 # COMMAND PID USER FD TYPE NODE NAME # node 48213 lee 23u IPv6 TCP *:3000 (LISTEN) # PID 숫자만 뽑기 lsof -ti :3000

포트를 쥔 프로세스를 종료하는 방법

PID를 알면 종료는 한 줄입니다. 맥·리눅스에서는 kill PID로 정상 종료를 먼저 시도하고, 그래도 안 죽으면 kill -9 PID로 강제 종료합니다. -9는 프로세스가 뒷정리할 틈 없이 곧바로 끊는 신호라, 웬만하면 먼저 일반 kill을 써 보는 편이 안전합니다.


한 줄로 찾고 죽이려면 kill $(lsof -ti :3000)처럼 묶어 씁니다. 윈도우에서는 netstat으로 PID를 확인한 뒤 taskkill /PID 2660 /F로 종료하는데, 마이크로소프트 문서 기준 /F는 강제 종료, /PID는 번호로 대상을 지정하는 옵션입니다.


명령을 외우기 번거롭다면 npx kill-port 3000 한 줄로 끝낼 수도 있습니다. npm의 kill-port 패키지는 안에서 결국 같은 lsof·kill(윈도우는 netstat·taskkill)을 대신 불러 주는 도구라, 운영체제를 안 가리고 같은 명령으로 포트를 비웁니다.


방법명령비고
맥·리눅스 정상 종료kill PID뒷정리 후 종료
맥·리눅스 강제 종료kill -9 PID즉시 끊음, 최후 수단
윈도우taskkill /PID 2660 /F관리자 권한 필요할 수 있음
운영체제 공통npx kill-port 3000패키지가 대신 처리

포트를 비우는 한 줄 명령
# 맥 · 리눅스 — 포트 3000을 쥔 프로세스 종료 kill $(lsof -ti :3000) # 안 죽으면 강제 종료 kill -9 $(lsof -ti :3000) # 윈도우 (cmd) — PID 확인 후 종료 # netstat -ano | findstr :3000 taskkill /PID 2660 /F # 운영체제 공통 — 한 줄 npx kill-port 3000
lsof로 PID를 찾아 kill로 종료하거나 npx kill-port로 포트를 비우는 명령 흐름 이미지
PID를 겨냥해 하나만 죽이면 다른 프로젝트 서버는 건드리지 않는다

죽여도 자꾸 되살아날 때 볼 자리

분명히 종료했는데 포트가 여전히 막혀 있다면 몇 가지를 의심해 볼 수 있습니다. 첫째는 자동 재시작 도구입니다. nodemon이나 pm2, 도커 컴포즈의 restart 설정처럼 프로세스가 죽으면 곧바로 다시 띄우는 감시자가 있으면, 죽여도 새 프로세스가 같은 포트를 다시 잡습니다. 이때는 그 감시자부터 멈춰야 하죠.


둘째는 도커입니다. docker ps로 3000번을 매핑한 컨테이너가 떠 있다면 docker stop으로 컨테이너를 멈춰야 포트가 풀립니다. 호스트에서 kill을 해도 컨테이너 안 프로세스는 그대로일 수 있어서예요. 셋째는 방금 죽인 소켓이 잠깐 TIME_WAIT로 남는 경우인데, 이건 몇 초 기다리면 대개 풀립니다.


가장 빠른 우회는 포트를 바꿔 버리는 것입니다. 급할 때는 PORT=3001 npm run dev처럼 다른 번호로 띄우면 충돌 자체를 피할 수 있죠. 다만 이건 임시방편이라, 근본적으로는 원래 3000번을 쥔 프로세스를 정리하는 편이 깔끔합니다.


  • [ ] nodemon·pm2·도커 restart 같은 자동 재시작이 켜져 있는지 확인했다
  • [ ] docker ps로 같은 포트를 매핑한 컨테이너가 없는지 봤다
  • [ ] 방금 죽였으면 몇 초 기다린 뒤 다시 시도했다
  • [ ] 급하면 PORT 환경변수로 다른 포트에 띄웠다
  • [ ] 정확한 PID 하나만 겨냥했는지 이름으로 확인했다

node.exe 전체 종료는 신중히 | 윈도우에서 taskkill /F /IM node.exe는 모든 노드 프로세스를 한꺼번에 끕니다. 다른 프로젝트 서버나 편집기의 노드 프로세스까지 함께 죽으니, 포트 하나만 문제일 땐 PID를 지정해 종료하세요.


Next.js·개발 서버에서 실전 순서

에러가 떴을 때 순서를 정해 두면 헤매지 않습니다. 먼저 메시지에서 막힌 포트 번호를 읽고, lsof -i :3000(윈도우는 netstat)으로 누가 쥐고 있는지 확인합니다. 그게 내 이전 개발 서버가 맞으면 PID를 겨냥해 종료하고, 그다음 다시 서버를 띄우면 됩니다.


Next.js는 다행히 이 상황을 부드럽게 처리합니다. 기본 3000번이 막혀 있으면 자동으로 3001번처럼 빈 포트를 찾아 그쪽에 띄우고 안내해 주죠. 특정 포트를 고정하고 싶으면 next dev -p 3001이나 PORT=3001 next dev로 지정할 수 있습니다. 이 방식은 Next.js CLI 문서에 정리돼 있습니다.


반복해서 겪는다면 예방이 낫습니다. 개발 서버를 끌 때 터미널 창을 강제로 닫지 말고 Ctrl+C로 정상 종료하는 습관이 프로세스를 깔끔히 정리해 줍니다. 저처럼 한국에서 여러 사이트를 한 노트북으로 돌리는 1인 개발자라면 프로젝트마다 3000, 3001, 3002처럼 포트를 미리 나눠 두는 것도 충돌을 크게 줄여 줍니다. 환경변수나 셸 설정이 얽혀 헷갈릴 때는 direnv로 폴더 환경 나누는 글이나 워크트리로 프로젝트를 분리하는 글도 함께 보시면 됩니다.


  • [ ] 에러 메시지에서 막힌 포트 번호를 먼저 읽었다
  • [ ] lsof·netstat으로 포트를 쥔 프로세스를 확인했다
  • [ ] 내 서버가 맞으면 PID를 겨냥해 종료했다
  • [ ] Next.js면 -p나 PORT로 포트를 옮길 수 있음을 확인했다
  • [ ] 서버를 끌 때 Ctrl+C로 정상 종료하는 습관을 들였다

Next.js 개발 서버가 막힌 포트를 피해 다른 포트로 자동 전환하는 실전 순서 흐름 이미지
포트를 정리하거나 다른 번호로 옮기면 개발 서버는 다시 뜬다

참고 자료


내부 연계: direnv로 폴더 환경 나누기, 깃 워크트리로 프로젝트 분리, npm ERESOLVE 충돌 풀기


인용한 명령과 옵션은 2026년 8월 공개 문서 기준입니다.


자주 묻는 질문

EADDRINUSE는 코드가 잘못돼서 나는 건가요?

아닙니다. 쓰려는 포트를 이미 다른 프로세스가 쥐고 있어서 나는 에러입니다. 코드보다 그 포트를 누가 붙잡고 있는지부터 확인해야 합니다. 대부분 이전에 띄운 서버가 완전히 안 죽은 경우예요.


어떤 프로세스가 포트를 쓰는지 어떻게 찾나요?

맥·리눅스는 lsof -i :3000, 윈도우는 netstat -ano | findstr :3000으로 확인합니다. 출력에 나오는 PID가 그 포트를 쥔 프로세스 번호이고, 이 번호로 종료 대상을 지정합니다.


kill과 kill -9는 뭐가 다른가요?

kill은 프로세스에 종료 신호를 보내 뒷정리 후 끝나게 하고, kill -9는 그 틈 없이 즉시 끊습니다. 먼저 일반 kill을 써 보고, 그래도 안 죽을 때만 -9를 쓰는 편이 안전합니다.


종료했는데도 포트가 계속 막혀요.

nodemon·pm2·도커 restart처럼 죽으면 다시 띄우는 감시자가 있는지 보세요. docker ps로 같은 포트를 매핑한 컨테이너도 확인해야 합니다. 방금 죽인 소켓이 잠깐 남는 경우면 몇 초 기다리면 풀립니다.


npx kill-port는 안전한가요?

지정한 포트를 쥔 프로세스만 종료하므로 taskkill /IM node.exe처럼 전부 죽이는 방식보다 안전합니다. 내부적으로 lsof·kill이나 netstat·taskkill을 대신 부르는 도구라, 운영체제를 안 가리고 같은 명령으로 씁니다.


그냥 다른 포트로 띄우면 안 되나요?

급할 때는 PORT=3001 npm run dev나 next dev -p 3001로 충돌을 피할 수 있습니다. 다만 원래 포트를 쥔 프로세스는 그대로 남으니, 반복되면 근본적으로 그 프로세스를 정리하는 편이 깔끔합니다.


EADDRINUSE는 결국 쓰려는 포트를 누가 이미 쥐고 있는지의 문제입니다. 메시지에서 포트 번호를 읽고, lsof나 netstat으로 PID를 찾아 그 하나만 종료하면 대부분 풀립니다. 자동 재시작이나 도커가 얽혔는지 살피고, 급할 땐 포트를 옮기면 되죠. 관련 글: direnv 폴더 환경, 깃 워크트리, npm ERESOLVE.


EADDRINUSE포트 사용 중프로세스 종료lsofnetstatkilltaskkillkill-portNext.js노드개발자터미널

관련 도구

함께 보면 좋은 문제 해결

EXPLORE / 개발자 작업환경

이어서 읽어보기

전체 토픽 둘러보기