Jeonghwan's Blog
좀비처럼 살아 있는 포트, 한 줄의 명령어로 정리하는 방법

좀비처럼 살아 있는 포트, 한 줄의 명령어로 정리하는 방법

개발 중 로컬 서버를 재시작했는데 이런 에러 메시지 본 적 있으신가요?

Error: listen EADDRINUSE: address already in use :::3000

"엥, 서버를 분명 종료했었는데 왜 포트가 아직 사용 중이지?!😟"

이럴 땐 대부분 이전 프로세스가 완전히 종료되지 않아서 포트가 점유되고 있는 상태예요.

복잡한 커맨드 없이, 이 문제를 단숨에 해결할 수 있는 도구가 있어요. 바로 npx kill-port입니다.

npx kill-port 란?

npx kill-port는 지정한 포트 번호를 사용 중인 프로세스를 찾아서 자동으로 종료해주는 CLI 도구예요.

npx kill-port 3000

이 한 줄이면 3000번 포트를 점유하고 있는 프로세스를 찾아 바로 종료해줘요.

설치 없이 npx 로 바로 사용 가능하고, 여러 포트 동시 종료도 가능해요.

tcp, udp 방식 모두 지원하며, Window, MacOS, Linux 환경에서도 모두 사용 가능해요.

npx kill-port 명령어가 내부적으로는 어떻게 동작할까요?

npx kill-port는 OS에 따라 다른 방식으로 동작해요.

  • Mac/Linux: lsof -i :<포트번호>kill -9 <PID>
  • Windows: netstat -ano | findstr :<포트>taskkill /PID <PID> /F

하지만 이걸 직접 쓰려면 복잡하죠.

예를 들어 직접 처리하려면 아래와 같이 작성해야 해요.

lsof -i :3000
kill -9 <PID>

이 방식은 매번 PID를 찾아야 해서 번고롭고 실수도 많아요. 이걸 npx kill-port 3000으로 단축시켜 사용할 수 있는 거죠.

여러 개의 포트를 종료할 때는?

한 번에 여러 포트를 종료하고 싶을 땐, 이렇게 쓰면 돼요.

npx kill-port 3000 3001 3002 3003 3004 3005

쉼표 없이 공백으로 부분해서 여러 포트를 넘기면 됩니다.

만약 Linux나 macOS의 Bash 쉘을 사용하고 있다면 아래와 같이 작성도 가능해요.

npx kill-port $(seq 3000 3005)

위 부분은 $(...)를 사용해 쉘 명령어 치환 방식을 활용한 것이에요.

즉, seq 3000 3005 라는 명령을 먼저 실행해서 나오는 결과를 npx kill-port 뒤에 인자로 넣는 거죠.

seq 3000 3005
# 출력: 3000 3001 3002 3003 3004 3005

결과적으로 아래 명령어와 동일하게 돼요.

npx kill-port 3000 3001 3002 3003 3004 3005

하지만 위 방법은 Windows 기본 명령 프롬프트(CMD)에서는 사용 불가능해요. seq라는 명령 자체가 존재하지 않고, $(...)도 CMD에서는 전혀 인식되지 않고 그냥 문자열로 취급해버려요.

실무에서 활용 가능한 팁

개발 환경이 점점 복잡해지면서 포트를 다루는 일이 자주 발생하죠. 특히 프론트엔드 개발자라면, 모노레포 구조에서 여러 앱을 동시에 실행하거나, Storybook 같은 도구를 함께 사용할 때 다양한 포트를 병렬로 관리해야 할 일이 많죠.

이럴 땐 매번 포트를 수동으로 정리하기보단, package.json 에 스크립트를 등록해두면 훨씬 편하게 사용할 수 있어요.

1. 서버 실행 전에 자동으로 포트 정리하기

개발 서버를 켤 때마다 포트 충돌이 자주 발생한다면, 아래처럼 package.json에 스크립트를 작성해 보세요.

"scripts": {
  "dev": "npx kill-port 3000 && next dev"
}

이제 npm run dev 만 해도 먼저 3000번 포트를 비우고, 바로 서버를 실행할 수 있어요.

2. 포트 초기화 스크립트 추가

매번 npx kill-port 3000 3001 3002 6006 을 작성하여 실행시키는 것이 귀찮다면, 아래처럼 package.json에 스크립트를 작성해 보세요.

"scripts": {
  "reset-port": "npx kill-port 3000 3001 3002 6006"
}

이렇게 하면 npm run reset-port 명령어 하나로 실행 중인 여러 앱의 포트를 한꺼번에 정리할 수 있어요.

왜 이런 문제가 발생할까요?

그런데 근본적으로 왜 포트가 완전히 종료되지 않는 현상이 발생하는 걸까요?

Node.js 기반의 개발 서버들은 우리가 보통 Ctrl + C로 종료하긴 하지만, 모든 경우에 프로세스가 완전히 종료되는 건 아니에요.

특히 아래와 같은 상황에서는 포트를 점유한 채로 프로세스가 남아 있을 수 있어요.

  • 터미널에서 Ctrl + C를 눌렀지만, 서버가 종료 신호를 제대로 처리하지 못한 경우
  • 코드에 비동기 작업이나 에러가 있어서 서버가 비정상적으로 종료되었을 때
  • 서버가 백그라운드에서 실행되었을 때 (&를 붙여 실행하거나, 터미널을 닫았을 경우)

이럴 땐 사용 중이던 포트는 계속 점유된 상태로 남게 되고, 다시 같은 포트로 서버를 실행하려고 하면 이미 해당 포트가 사용되고 있다는 메시지와 함께 에러가 발생하죠.

즉, 서버는 죽었는데 포트는 살아 있는 좀비 상태가 되는 셈이죠.

마무리

개발을 하다 보면 포트 충돌은 생각보다 자주 마주치는 문제예요. 특히 여러 앱을 동시에 실행하거나, 서버가 비정상적으로 종료된 상황에서는 포트가 남아 있어서 당황하기 쉽죠.

앞으로는 npx kill-port 명령어로 포트 충돌 문제를 손쉽게 해결해 보세요. 그리고 이 글을 통해 포트 충돌의 원인을 이해하고, 효과적인 해결 방법을 배우셨기를 바래요.👋