HOWTO · Java

Java.Net.BindException 수정: 이미 사용 중인 주소: 바인드

이 튜토리얼은 java.net.BindException: Address already in use: Java의 바인드 오류를 보여줍니다.

이 페이지의 내용

java.net.BindException: Address already in use: Bind 오류를 해결하려면 요청한 로컬 주소와 포트를 어떤 프로세스가 사용 중인지 확인하세요. 해당 프로세스가 없다면 다른 원인을 살펴보세요. 서버가 사용 가능한 포트를 쓰도록 설정하거나, 확인된 프로세스를 종료할 수 있습니다.

이 예외의 의미

java.net.BindException: Address already in use: Bind는 Java가 요청한 로컬 주소와 포트에 소켓을 바인딩하지 못했다는 뜻입니다. 이미 리스너가 해당 포트를 사용 중일 수 있지만, 이 메시지만으로 다른 애플리케이션이 원인이라고 단정할 수는 없습니다. 요청한 주소를 사용할 수 없거나 운영 체제가 바인딩을 막는 경우도 있습니다. 설정을 바꾸기 전에 시작 설정에서 정확한 주소와 포트를 확인하세요.

서버가 포트 8080에서 리스닝하도록 설정되어 있다면, 먼저 해당 포트에서 리스닝 중인 프로세스가 있는지 확인하세요. 그런 다음 서버가 다른 포트를 사용하도록 설정할지, 확인된 프로세스를 종료할지 결정하세요. 클라이언트, 프록시 또는 다른 서비스가 기존 포트에 의존한다면 그 포트를 유지하세요.

포트에서 리스닝 중인 프로세스 찾기

아래 명령에서 8080을 오류나 서버 설정에 표시된 포트로 바꾸세요. Windows에서는 명령 프롬프트나 PowerShell에서 netstat -ano | findstr :8080을 실행하세요. 상태가 LISTENING인 행을 찾습니다. 마지막 열에는 프로세스 ID(PID)가 표시됩니다. 다른 상태의 연결이 일치하더라도, 그것만으로 새 연결을 기다리는 프로세스가 있다고 볼 수는 없습니다.

macOS에서는 lsof -nP -iTCP:8080 -sTCP:LISTEN을 실행하세요. Linux에서는 sudo ss -ltnp 'sport = :8080'으로 리스닝 중인 TCP 소켓을 확인할 수 있으며, 충분한 권한이 있으면 소유 프로세스도 표시됩니다. ss를 사용할 수 없다면 lsof가 설치된 경우 sudo lsof -nP -iTCP:8080 -sTCP:LISTEN을 사용하세요. 오래된 시스템에는 netstat이 있을 수 있지만 옵션과 PID 표시 방식은 다릅니다. 유닉스 계열 시스템에서 출력 형식이 모두 같다고 가정하지 마세요.

조치하기 전에 PID를 기록하고 프로세스 이름과 명령줄을 확인하세요. 권한이 제한되어 있거나, 서비스가 이미 종료되었거나, 충돌이 다른 로컬 주소 또는 프로토콜과 관련된 경우 조회 결과에 소유 프로세스가 표시되지 않을 수 있습니다. 서버가 시작될 때만 리스너가 나타난다면 서버를 중지한 상태에서 다시 확인하세요.

해결 방법 선택

기존 리스너가 필요하거나 서버 설정을 직접 관리한다면 서버 포트를 바꾸는 것이 일반적으로 적절합니다. 프로세스가 무엇을 하는지, 누가 관리하는지, 안전하게 중지할 수 있는지 확인한 경우에만 프로세스를 종료하세요. 공유 시스템이나 운영 서버에서는 낯선 프로세스를 종료하지 말고 서비스 소유자에게 문의하세요. 프로세스가 종료된 뒤에는 PID가 재사용될 수 있으므로, 종료 명령을 보내기 직전에 프로세스가 맞는지 다시 확인하세요.

서버 포트 변경

Tomcat의 경우 server.xml에서 HTTP 커넥터를 편집하고 배포 설정에 맞는 사용 가능한 포트를 선택하세요. 예를 들어 커넥터의 port 값을 8080에서 8880으로 바꾸고 나머지 커넥터 속성은 그대로 둡니다. 설정에서 바꿀 부분은 port="8080"에서 port="8880"으로 변경하는 것입니다. 파일을 저장한 뒤 Tomcat를 다시 시작하세요. 이전 포트를 대상으로 하는 클라이언트, 리버스 프록시, 방화벽 규칙, 상태 확인 설정도 업데이트하세요.

포트를 사용하는 프로세스 중지

추측한 번호가 아니라 리스너 조회에서 확인한 PID를 사용하세요. Windows에서는 프로세스를 확인한 다음 권한이 있는 셸에서 taskkill /PID 12345를 실행하세요. 정상 종료에 실패하고 강제 종료 권한이 있는 경우에만 /F를 추가하세요. macOS 또는 Linux에서는 일반 종료 신호를 보내도록 kill 12345를 실행하세요. 프로세스가 정상적으로 종료되지 않고 그 결과를 이해한 경우가 아니라면 kill -9를 사용하지 마세요. 이 명령을 실행하려면 적절한 권한이 필요합니다. 관리 대상 서비스는 정상적으로 종료할 수 있도록 서비스 관리자를 통해 중지하는 편이 좋습니다.

수정 확인

다음 예제를 실행하세요:

이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.

import java.io.IOException;
import java.net.ServerSocket;

public class BindCheck {
    public static void main(String[] args) throws IOException {
        try (ServerSocket server = new ServerSocket(0)) {
            System.out.println("Bound to an available port.");
        }
    }
}

이 간단한 Java 예제는 운영 체제가 사용 가능한 포트를 할당하도록 요청하고, 블록이 끝나면 소켓을 닫습니다. 제공된 패킷에서는 실행되지 않았으므로 관찰된 출력은 없습니다. 서버를 수정한 뒤 실제 서비스를 시작하고 시작 로그를 확인하세요. 선택한 포트로 운영 체제별 리스너 조회를 반복해 의도한 서비스가 리스닝 소켓을 소유하는지 확인한 다음, 클라이언트가 사용하는 것과 같은 호스트 이름 및 포트로 연결하세요. 시작 로그에 여전히 바인딩 실패가 나타나면 포트뿐 아니라 설정된 로컬 주소도 확인하고, 다른 설정을 바꾸기 전에 새 오류 내용을 살펴보세요.