address already in use 완전 해결: 포트 점유 프로세스 찾아 종료하기 (EADDRINUSE)
콘솔에 빨간 줄이 떴다 — 이 에러가 의미하는 단 하나
서버를 띄우려는데 콘솔이 bind: address already in use 혹은 EADDRINUSE를 토해냈다면, 사실 메시지가 말하려는 건 단 하나입니다.
하나의 포트는 한 번에 하나의 프로세스만 점유할 수 있다.
즉 "내가 쓰려는 포트(예: 8080)를 이미 누군가 붙잡고 있다"는 뜻입니다. 범인은 셋 중 하나예요.
- 나 자신 — 좀 전에 띄운 서버가 안 죽고 살아 있음 (핫리로드 고아 프로세스가 대표적)
- 다른 프로세스 — 전혀 무관한 앱이 같은 포트를 선점
- 컨테이너 — Docker가 호스트 포트를 매핑해서 잡고 있음
이 글은 진단 → 종료 → 재발 방지 순서로 따라오면 끝나도록 구성했습니다. 위에서 아래로 복붙하며 내려오세요.
1단계 진단 — 에러 원문 패턴별 진단표
먼저 콘솔에 뜬 원문이 어떤 형태인지 보세요. 환경마다 메시지 모양이 다를 뿐, 본질은 같습니다.
| 환경 | 실제 콘솔 출력 | 가리키는 범인 | 우선 확인 명령 |
|---|---|---|---|
| Node.js | Error: listen EADDRINUSE: address already in use :::8080 | 보통 앱 자신(중복 기동/nodemon 고아) | lsof -i :8080 |
| Python | OSError: [Errno 98] Address already in use | uvicorn/flask 재시작 잔존 프로세스 | lsof -i :8000 |
| nginx | bind() to 0.0.0.0:80 failed (98: Address already in use) | 다른 웹서버/이전 nginx 인스턴스 | ss -ltnp 'sport = :80' |
| Docker | Bind for 0.0.0.0:8080 failed: port is already allocated | 호스트 포트를 잡은 다른 컨테이너 | docker ps |
표에서 자기 케이스를 찾았다면, 우선 확인 명령으로 누가 잡고 있는지 정체부터 파악합시다.
2단계 종료 — 점유 프로세스 찾고 안전하게 죽이기
아래 예시는 전부 8080 포트로 통일했습니다. 본인 포트로 바꿔서 실행하세요.
Linux / macOS
# 1) 포트를 점유한 프로세스(PID)와 이름 확인
lsof -i :8080
# 2) 대체 명령 — ss는 lsof보다 가볍고 리눅스 기본 탑재
ss -ltnp 'sport = :8080'
# 3) fuser로 한 번에 확인
fuser 8080/tcplsof -i :8080의 출력에서 PID 컬럼을 확인했다면, 종료합니다.
# 먼저 우아하게 (권장)
kill -15 <PID>
# 10초 기다려도 안 죽으면 강제 종료
kill -9 <PID>
# fuser로 한 방에 종료하고 싶다면
fuser -k 8080/tcpWindows (PowerShell / CMD)
# 포트를 점유한 PID 찾기 (맨 끝 숫자가 PID)
netstat -ano | findstr :8080
# 해당 PID 강제 종료
taskkill /PID <PID> /Fkill -15 vs kill -9, 순서가 중요하다
kill -15(SIGTERM): "정리하고 나가라"는 신호. 앱이 열린 파일을 닫고 DB 커넥션을 정리한 뒤 종료합니다. 항상 이걸 먼저 쓰세요.kill -9(SIGKILL): 프로세스를 즉사시킵니다. 무턱대고 -9를 쓰면 쓰던 데이터가 유실되거나 락 파일·임시 소켓이 잔존해 더 꼬일 수 있습니다. SIGTERM이 안 먹힐 때만 마지막 수단으로.
3단계 재발 방지 — 근본 원인별 처방
죽이고 다시 띄웠는데 또 같은 에러? 그럼 원인을 뿌리째 뽑아야 합니다.
1) TIME_WAIT 잔존 소켓 → SO_REUSEADDR
서버를 껐다 바로 켜면 방금 닫은 소켓이 TIME_WAIT 상태로 수십 초간 포트를 붙잡고 있어 EADDRINUSE가 납니다. SO_REUSEADDR 옵션을 켜면 이 상태의 포트를 재사용할 수 있습니다.
Node.js — net/http 서버는 기본적으로 SO_REUSEADDR가 켜져 있지만, 명시적으로 에러를 처리하고 재시도하도록 짜두면 좋습니다.
const server = http.createServer(app);
server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error('포트 8080 사용 중. 점유 프로세스를 먼저 종료하세요.');
process.exit(1);
}
});
server.listen(8080);Python
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # TIME_WAIT 포트 재사용
s.bind(('0.0.0.0', 8000))
s.listen()2) 핫리로드 고아 프로세스
nodemon, uvicorn --reload가 비정상 종료되면 자식 워커가 부모를 잃고 고아 프로세스로 남아 포트를 계속 잡습니다. 터미널을 닫아도 안 죽는 경우가 많으니, 2단계의 lsof로 직접 찾아 죽이는 게 확실합니다.
3) systemd · pm2 중복 기동
프로세스 매니저가 자동 재기동하도록 설정돼 있으면, 당신이 수동으로 띄운 서버와 충돌합니다.
# pm2가 같은 앱을 이미 띄워두지 않았는지 확인
pm2 list
# systemd 서비스가 포트를 잡고 있는지
systemctl status myapp.service수동 테스트 전에 pm2 stop <name> 또는 systemctl stop으로 매니저 쪽을 먼저 내려주세요.
4) Docker compose 포트 매핑 충돌
Bind for 0.0.0.0:8080 failed: port is already allocated는 호스트 포트가 겹쳤다는 뜻입니다.
# 8080을 잡고 있는 컨테이너 찾기
docker psPORTS 컬럼에서 0.0.0.0:8080->...를 잡은 컨테이너를 확인했다면, compose에서 호스트 포트만 비워 있는 값으로 바꿉니다.
services:
web:
ports:
- "8081:80" # 왼쪽(호스트)만 변경, 오른쪽(컨테이너)은 그대로실무 팁: 로컬에서 가장 흔한 원인은 "안 죽은 이전 서버"와 "compose 내림 깜빡함"입니다. 컨테이너를 쓴다면 작업 끝에
docker compose down을 습관화하고, 핫리로드가 자주 터진다면lsof -i :<port>를 셸 alias로 등록해 두세요. 진단 시간이 30초로 줄어듭니다.
결론 — 3단계 요약과 복붙 체크리스트
- 진단: 에러 원문으로 범인이 앱/다른 프로세스/컨테이너 중 무엇인지 구분
- 종료:
lsof -i :<port>(또는netstat -ano)로 PID 찾고kill -15→ 안 되면kill -9 - 재발 방지:
SO_REUSEADDR, 고아 프로세스 정리, 프로세스 매니저·compose 포트 점검
# 복붙용 한 줄 진단 (Linux/macOS)
lsof -i :8080 || ss -ltnp 'sport = :8080'자주 묻는 질문 (FAQ)
Q. 그냥 포트를 다른 번호로 바꿔도 되나요? A. 임시방편으로는 가능합니다. 하지만 포트를 옮긴다고 점유 중인 좀비/고아 프로세스가 사라지진 않으므로, 자원이 새고 있는 셈입니다. 근본 해결은 점유 프로세스를 종료하는 것입니다.
Q. 재부팅하면 해결되던데, 그게 정답인가요? A. 재부팅하면 모든 프로세스와 TIME_WAIT 소켓이 초기화돼 당연히 풀립니다. 하지만 원인은 그대로라 곧 재발합니다. 이 글의 2~3단계로 원인을 제거하세요.
Q. Permission denied로 bind가 실패하는데 이것도 포트 충돌인가요?
A. 아닙니다. 1024 미만 포트(80, 443 등)는 루트 권한이 필요해서 나는 에러입니다. sudo로 실행하거나, 8080 같은 1024 이상 포트를 쓰거나, setcap으로 권한을 부여하면 됩니다. address already in use와는 다른 문제입니다.
이 글은 AI 에이전트가 자료 조사와 1차 초안 작성을 담당하고, 사람 편집자가 사실관계·출처·톤과 맥락을 검토한 뒤 발행했습니다. 환경(OS·버전)에 따라 결과가 다를 수 있으니 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.
댓글
첫 번째 댓글을 남겨보세요.