개발 도구 ·

개발 서버가 열리지 않을 때 프로세스와 포트와 localhost를 구분하는 법

먼저 답부터

프로세스는 실행 중인 프로그램이고, 포트는 그 프로그램이 연결을 기다리는 문이며, localhost는 지금 브라우저를 연 컴퓨터 자신을 가리키는 이름입니다. 서버가 안 열리면 먼저 터미널의 실제 주소와 오류를 읽고 해당 포트를 누가 쓰는지 확인하세요. 정체를 모르는 프로세스를 바로 종료하거나 외부 공개 주소로 바꾸지 않는 것이 안전합니다.

개발 서버가 열리지 않을 때 프로세스와 포트와 localhost를 구분하는 법 대표 이미지

개발 서버를 켰는데 브라우저가 열리지 않거나, 방금 고친 화면 대신 다른 화면이 나타날 때가 있습니다. 이때 무작정 명령을 다시 실행하면 같은 서버가 여러 개 생기거나 이미 하던 작업을 끊을 수 있습니다.

한 건물 안에 여러 작업실이 있고 각 작업실로 들어가는 문이 따로 있다고 생각해 보세요. 실행 중인 프로그램은 작업실에서 일하는 사람, 포트는 손님을 받는 문, localhost는 그 건물 자체의 주소입니다. 세 가지를 나누면 어디를 먼저 확인해야 하는지 보입니다.

프로세스는 지금 실행 중인 프로그램이다

프로세스는 컴퓨터 메모리에서 실제로 실행되고 있는 프로그램 한 건입니다. 코드 파일이 저장돼 있어도 실행하지 않았다면 프로세스가 아니고, 개발 서버 명령을 실행해 계속 요청을 기다리는 동안에는 서버 프로세스가 살아 있습니다. 운영체제는 각 프로세스를 구분하는 번호인 PID를 붙입니다.

터미널 창을 닫지 않았거나 도구가 백그라운드 실행을 유지하면 이전 프로세스가 남아 있을 수 있습니다. 반대로 터미널에 명령을 입력했어도 오류로 바로 끝났다면 기다리는 서버 프로세스는 생기지 않았을 수 있습니다. 먼저 “명령을 쳤는가”보다 “지금도 실행 중인가”를 확인해야 합니다.

포트는 한 컴퓨터 안에서 프로그램을 찾아가는 문이다

포트는 네트워크 요청을 어느 프로그램이 받을지 구분하는 번호입니다. 같은 컴퓨터에서도 웹 서버, 데이터베이스, 메일 도구가 서로 다른 포트에서 연결을 기다릴 수 있습니다. 브라우저 주소 http://localhost:5173에서 5173이 포트입니다.

Node.js 공식 문서의 server.listen(port, host)는 지정한 호스트와 포트에서 TCP 연결을 기다리게 합니다. 같은 주소와 포트를 다른 서버가 이미 사용하면 EADDRINUSE, 즉 주소가 이미 사용 중이라는 오류가 날 수 있습니다. 이는 코드 전체가 망가졌다는 뜻이 아니라 먼저 그 문을 쓰는 프로세스가 있다는 단서입니다.

localhost는 인터넷 사이트가 아니라 내 컴퓨터를 가리킨다

localhost는 지금 주소를 입력한 컴퓨터 자신을 가리키는 특별한 이름입니다. RFC 6761은 localhost 이름이 IPv4와 IPv6의 루프백 주소, 다시 말해 요청이 같은 컴퓨터 안으로 돌아오는 주소로 해석된다고 설명합니다. 그래서 내 노트북의 localhost와 다른 사람 노트북의 localhost는 같은 서버가 아닙니다.

휴대전화에서 노트북의 개발 서버를 보려고 localhost:5173을 입력하면 휴대전화 자신을 찾게 됩니다. 이 문제를 해결하려고 서버를 모든 네트워크 주소에 공개하면 같은 와이파이의 다른 기기에서도 접근할 수 있을 수 있지만, 방화벽과 인증 상태를 확인하지 않은 채 공개 범위를 넓혀서는 안 됩니다.

터미널에 찍힌 실제 주소와 오류부터 읽는다

Vite는 기본 개발 포트로 5173을 사용하지만 이미 사용 중이면 다음 빈 포트를 자동으로 시도할 수 있습니다. 따라서 습관대로 5173만 열지 말고 실행 직후 터미널이 보여 준 실제 Local 주소를 확인해야 합니다. strictPort 설정이 켜져 있으면 빈 포트로 옮기지 않고 종료하므로 같은 상황에서도 결과가 다를 수 있습니다.

$ npm run dev
Local: http://localhost:5174/

브라우저에 입력할 주소: http://localhost:5174/

위 예시는 원래 기대한 포트가 아니라 5174에서 서버가 시작된 상황입니다. 반대로 EADDRINUSE 뒤에 명령 프롬프트가 바로 돌아왔다면 서버 시작이 실패했을 가능성이 큽니다. 브라우저의 “연결 거부”와 터미널의 “포트 사용 중”을 같은 오류로 뭉뚱그리지 말고 두 화면을 함께 읽습니다.

포트 충돌은 종료보다 정체 확인이 먼저다

포트를 쓰는 프로세스를 발견해도 바로 종료하지 않습니다. 다른 프로젝트의 개발 서버, 데이터베이스, 동료가 연결한 원격 작업일 수 있습니다. 먼저 PID, 실행 명령, 시작 시각, 작업 폴더를 확인하고 내가 시작한 작업인지 판단합니다.

macOS나 Linux에서는 다음처럼 해당 TCP 포트에서 연결을 기다리는 항목을 읽기 전용으로 볼 수 있습니다. 운영체제와 설치 도구에 따라 명령이 다르므로 모르면 실행하지 말고 작업 관리자나 개발자에게 확인하세요.

lsof -nP -iTCP:5173 -sTCP:LISTEN

출력에 명령 이름과 PID가 보이면 그것을 현재 터미널과 프로젝트 경로에 대조합니다. 아무 결과가 없는데 브라우저가 계속 실패하면 주소 오타, 서버 종료, IPv4와 IPv6 연결 차이, 방화벽, 컨테이너나 원격 환경처럼 다른 범위를 살펴봅니다.

다른 화면이 보이면 주소와 프로세스를 함께 의심한다

페이지가 열렸다는 사실만으로 내가 방금 시작한 서버라고 단정할 수 없습니다. 같은 포트에서 오래된 프로젝트가 이미 실행 중이면 브라우저에는 정상 페이지가 보이면서 수정 내용만 반영되지 않을 수 있습니다. Vite 문서도 localhost의 주소 해석 순서나 모든 주소에서 기다리는 서버 때문에 예상한 서버와 다른 응답을 받을 수 있다고 안내합니다.

브라우저 주소창의 포트, 터미널의 Local 주소, 포트를 점유한 프로세스의 작업 폴더를 한 줄에 적어 비교합니다. 세 값이 맞으면 그다음에 브라우저 캐시나 코드 빌드 문제를 살핍니다. 일치하지 않으면 캐시를 지우기 전에 먼저 올바른 서버로 접속해야 합니다.

공개 범위와 비밀값과 실제 데이터 경계를 지킨다

--host 0.0.0.0처럼 모든 네트워크 인터페이스에서 요청을 받도록 바꾸면 localhost 안에만 있던 개발 서버가 주변 네트워크에 노출될 수 있습니다. 개발 화면에 환경 변수, 테스트 계정, 관리자 기능이 보인다면 공개 범위를 넓히지 않습니다. 비밀키와 토큰을 터미널 출력이나 화면 캡처에 남기지도 마세요.

정체를 확인하지 않은 프로세스에 강제 종료 명령을 쓰거나, 관리자 권한으로 포트를 빼앗거나, 방화벽을 끄는 행동도 피합니다. 결제, 삭제, 실제 고객 데이터가 연결된 서버라면 로컬 점검이라고 생각하지 말고 별도 시험 환경과 담당자 승인을 확인합니다. 종료가 필요하면 내가 시작한 프로세스인지와 저장되지 않은 작업이 없는지를 먼저 확인합니다.

오늘 바로 해볼 작은 실습

실제 서버 설정을 바꾸지 않고 10분 동안 현재 개발 주소를 읽어 봅니다.

  1. 프로젝트의 package.json에서 개발 서버 명령 이름만 확인합니다.
  2. 이미 실행 중인 서버가 있다면 새로 켜지 말고 터미널의 Local 주소를 적습니다.
  3. 주소를 호스트 localhost와 포트 번호로 나눠 적습니다.
  4. 브라우저 주소창의 포트가 터미널에 나온 포트와 같은지 비교합니다.
  5. 허용된 환경이면 읽기 전용 포트 조회로 명령 이름과 PID를 확인합니다.
  6. 프로세스의 작업 폴더가 현재 프로젝트와 같은지 확인합니다.
  7. 다른 화면이 보이면 캐시 삭제보다 주소와 작업 폴더 비교를 먼저 기록합니다.
  8. API 키, 쿠키, 토큰, 개인정보가 출력되면 복사하거나 공유하지 않습니다.
  9. 정체를 모르는 프로세스 종료, 방화벽 해제, 외부 공개 설정은 하지 않습니다.
  10. 실제 결제나 삭제 기능이 연결돼 있다면 서버 조작 없이 담당자에게 확인합니다.

마지막으로 “어떤 프로그램이 어느 포트에서 기다리고 있고, 이 localhost는 어느 컴퓨터인가”를 한 문장으로 설명해 보세요. 세 가지 중 하나라도 확인되지 않으면 새 명령을 반복하거나 프로세스를 종료하지 않고, 터미널의 오류와 현재 상태를 함께 보여 주며 도움을 요청하는 편이 안전합니다.

확인한 자료

함께 읽기

  • Git 커밋과 브랜치를 게임 저장 지점처럼 이해하기

    Git 커밋은 지금 파일 상태를 다시 찾을 수 있게 남기는 저장 지점이고, 브랜치는 원본 흐름을 건드리지 않고 다른 수정을 시험하는 별도 길입니다. AI에게 코드를 맡기기 전에 커밋을 만들면 문제가 생겨도 바뀐 부분을 비교하고 안전하게 되돌리기 쉽습니다.

  • 파일 경로를 집 주소처럼 읽고 터미널에서 길을 잃지 않는 법

    파일은 내용을 담은 문서이고 폴더는 파일을 묶는 공간입니다. 절대경로는 출발점부터 적은 전체 주소, 상대경로는 현재 폴더를 기준으로 적은 길 안내입니다. 터미널에서는 먼저 `pwd`로 현재 위치를 확인한 뒤 `ls`로 목록만 읽으면 엉뚱한 곳을 바꾸는 실수를 줄일 수 있습니다.

  • npm 패키지와 의존성을 장보기 목록처럼 읽는 법

    npm 패키지는 프로젝트에서 다시 쓸 수 있게 묶은 코드이고, 의존성은 내 프로젝트가 작동하려고 기대는 패키지입니다. package.json은 필요한 이름과 허용 버전을 적은 목록이며 package-lock.json은 실제 설치된 전체 버전을 기록하므로 둘을 함께 보관해야 같은 환경을 재현하기 쉽습니다.