Linux 서버를 운영하다 보면 웹 서버, 데이터베이스, Docker, Kubernetes 또는 직접 개발한 서버 프로그램에서 Address already in use, EADDRINUSE, Bind failed와 같은 오류를 만나는 경우가 있습니다. 이 오류는 프로그램이 사용하려는 IP 주소와 포트가 이미 다른 프로세스에서 사용 중일 때 발생하는 대표적인 네트워크 오류입니다.
특히 웹 서버 재시작, 서비스 이중 실행, Docker 포트 매핑, 개발 환경에서 자주 발생하며 원인을 정확히 파악하면 대부분 빠르게 해결할 수 있습니다.
이번 글에서는 Address Already in Use(EADDRINUSE)의 원인과 확인 방법, 해결 방법을 실무 중심으로 자세히 알아보겠습니다.
Address Already in Use란?
TCP 서버는 서비스를 시작할 때 먼저 IP 주소와 포트를 운영체제에 등록(Bind)합니다.
동작 과정은 다음과 같습니다.
socket()
↓
bind()
↓
listen()
↓
accept()
하지만 이미 동일한 IP와 포트를 다른 프로세스가 사용하고 있다면 다음과 같은 오류가 발생합니다.
bind(): Address already in use
EADDRINUSE
즉, 커널이 동일한 주소를 중복으로 사용할 수 없다고 판단한 것입니다.
Address Already in Use가 발생하는 주요 원인
대표적인 원인은 다음과 같습니다.
- 동일한 프로그램 중복 실행
- 다른 서비스가 동일 포트 사용
- TIME_WAIT 상태
- Docker 포트 충돌
- Kubernetes NodePort 충돌
- 잘못된 Bind 설정
- systemd 중복 실행
- 종료되지 않은 프로세스
- Socket 옵션 미설정
- 애플리케이션 버그
실무에서는 포트 중복 사용이 가장 흔한 원인입니다.
1. 어떤 포트가 사용 중인지 확인하기
예를 들어 8080 포트를 확인합니다.
ss -tlnp | grep 8080
또는
lsof -i :8080
출력 예시입니다.
LISTEN 0 128 *:8080 users:(("java",pid=1523))
현재 어떤 프로세스가 포트를 사용 중인지 바로 확인할 수 있습니다.
2. 모든 Listen 포트 확인하기
현재 서버에서 열려 있는 모든 Listen 포트를 확인합니다.
ss -tlnp
또는
netstat -tlnp
불필요한 서비스가 실행 중인지 확인합니다.
3. PID 확인하기
포트를 사용하는 프로세스를 확인합니다.
lsof -iTCP -sTCP:LISTEN
또는
ps -ef | grep 프로그램명
같은 프로그램이 두 번 실행되고 있지는 않은지 확인합니다.
4. 프로세스 종료하기
불필요한 프로세스를 종료합니다.
kill PID
종료되지 않는다면
kill -9 PID
강제 종료 후 다시 서비스를 실행합니다.
5. TIME_WAIT 확인하기
서비스를 재시작했을 때 TIME_WAIT 때문에 일시적으로 발생할 수 있습니다.
ss -ant | grep TIME-WAIT
개수를 확인합니다.
ss -ant | grep TIME-WAIT | wc -l
TIME_WAIT가 많다면 잠시 기다리거나 Socket 옵션을 검토합니다.
6. SO_REUSEADDR 확인하기
서버 프로그램에서는 일반적으로 다음 옵션을 사용합니다.
예시(C)
int opt = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
이 옵션을 사용하면 TIME_WAIT 상황에서도 포트 재사용이 가능합니다.
단, 환경에 따라 동작 방식이 다를 수 있으므로 충분히 이해한 뒤 적용해야 합니다.
7. systemd 서비스 확인하기
systemd에서 중복 실행되고 있는지 확인합니다.
systemctl status 서비스명
자동 재시작 설정도 확인합니다.
systemctl cat 서비스명
Restart 정책으로 인해 프로세스가 중복 생성되는 경우도 있습니다.
8. Docker 포트 충돌 확인하기
Docker 환경에서는 포트 충돌이 자주 발생합니다.
docker ps
포트 매핑을 확인합니다.
docker port 컨테이너명
동일한 Host Port를 여러 컨테이너가 사용하지 않는지 확인합니다.
9. Kubernetes 환경 확인하기
NodePort 또는 HostPort 충돌을 확인합니다.
kubectl get svc -A
또는
kubectl get pods -A -o wide
HostNetwork 사용 여부도 함께 확인합니다.
10. 애플리케이션 로그 확인하기
로그에서 Bind 오류를 확인합니다.
Nginx
journalctl -u nginx
Tomcat
journalctl -u tomcat
대표적인 오류입니다.
bind(): Address already in use
EADDRINUSE
Address Already in Use 점검 순서
실무에서는 다음 순서대로 확인하는 것이 좋습니다.
- 사용 중인 포트 확인
- Listen 포트 확인
- PID 확인
- 프로세스 종료
- TIME_WAIT 확인
- SO_REUSEADDR 적용 여부 확인
- systemd 설정 확인
- Docker 포트 확인
- Kubernetes 설정 확인
- 애플리케이션 로그 확인
Address Already in Use 사용 시 주의사항
다음 사항을 고려해야 합니다.
- 동일한 포트를 여러 서비스에서 사용할 수 없다.
- 무조건 kill -9를 사용하지 않는다.
- TIME_WAIT는 정상적인 TCP 상태이다.
- Docker와 Kubernetes 포트도 함께 확인한다.
- SO_REUSEADDR 사용 여부를 검토한다.
- systemd 자동 재시작 정책도 확인한다.
포트 충돌을 해결하기 전에 어떤 프로세스가 포트를 점유하고 있는지 먼저 확인하는 것이 가장 중요합니다.
Address Already in Use와 Cannot Assign Requested Address의 차이
| 항목 | Address Already in Use | Cannot Assign Requested Address |
|---|---|---|
| 오류 코드 | EADDRINUSE | EADDRNOTAVAIL |
| 원인 | 포트 중복 사용 | 사용할 IP 또는 포트 부족 |
| 주요 발생 시점 | bind() | connect() |
| 해결 방법 | 포트 충돌 해결 | 포트/IP 관리 |
두 오류 모두 네트워크 관련이지만 발생 원인과 해결 방법은 다릅니다.
자주 묻는 질문
서버를 재시작했는데도 같은 오류가 발생합니다.
서비스가 정상적으로 종료되지 않았거나 systemd가 자동으로 다시 실행했을 가능성이 있습니다. 먼저 ss, lsof 명령으로 실제 포트를 점유 중인 프로세스를 확인해야 합니다.
SO_REUSEADDR을 사용하면 모든 문제가 해결되나요?
아닙니다. TIME_WAIT 상황에서는 도움이 될 수 있지만, 실제로 다른 프로세스가 해당 포트를 사용 중이라면 해결되지 않습니다.
Docker에서도 자주 발생하나요?
네. 여러 컨테이너가 동일한 Host Port를 사용하도록 설정하면 Address Already in Use 오류가 발생합니다.
마무리
Address Already in Use(EADDRINUSE)는 Linux에서 동일한 IP와 포트를 두 개 이상의 프로세스가 사용하려 할 때 발생하는 대표적인 네트워크 오류입니다. ss, lsof, systemctl, docker, kubectl 등을 활용하면 원인을 빠르게 확인할 수 있으며, 포트 점유 프로세스 확인과 서비스 설정 점검을 통해 안정적으로 문제를 해결할 수 있습니다.