2026. 7. 22.

Next.js Unable to acquire lock, 포트를 바꿔도 왜 다시 막힐까?

Next.js 16에서 Unable to acquire lock이 뜨면 포트를 바꾸거나 .next를 통째로 지우기 전에 같은 프로젝트를 실행 중인 프로세스부터 찾고 안전하게 종료해야 한다.

3 min read
Next.js Unable to acquire lock, 포트를 바꿔도 왜 다시 막힐까? 대표 이미지

npm run dev를 다시 실행했는데 Unable to acquire lock at .next/dev/lock, is another instance of next dev running?이 뜨면 포트부터 바꾸기 쉽다. 그러나 3001번이나 4000번으로 옮겨도 같은 오류가 날 수 있다. Next.js 16의 이 잠금은 포트 충돌이 아니라 같은 프로젝트의 개발 서버가 겹치는 것을 막기 때문이다.

먼저 .next 폴더를 지우지 않는다. 기존 터미널에서 개발 서버가 살아 있는지 찾고, 살아 있으면 그 터미널에서 Ctrl+C로 종료한다. 프로세스가 정말 없는데 잠금만 남았을 때만 .next/dev/lock을 처리한다. 목표는 오류를 잠깐 숨기는 것이 아니라 같은 프로젝트의 개발 서버가 하나만 실행되는 상태를 확인하는 것이다.

같은 Next.js 프로젝트를 두 터미널에서 실행해 두 번째 터미널에 잠금 오류가 나타난 상황

포트 충돌이 아니라 프로젝트 실행 잠금이다

Next.js 16 공식 업그레이드 문서는 여러 next dev 또는 next build 인스턴스가 같은 프로젝트에서 겹치지 않도록 잠금 파일을 사용한다고 설명한다. next CLI 문서에 따르면 개발 서버 출력도 기존 .next가 아니라 .next/dev에 놓인다. 그래서 next devnext build는 출력 경로가 달라 동시에 실행할 수 있지만, 같은 프로젝트에서 next dev 두 개를 여는 것은 별개의 문제다.

EADDRINUSE는 특정 포트를 이미 다른 프로세스가 쓰고 있다는 뜻이다. 이때는 3000번 포트 주인을 확인하는 순서가 맞다. 반면 Unable to acquire lock은 포트를 바꾸더라도 같은 프로젝트의 잠금이 남아 있으면 계속 나타날 수 있다. 오류 문자열과 경로를 먼저 구분해야 불필요한 포트 변경을 멈출 수 있다.

확인할 것은 두 가지다.

  • 다른 터미널에서 이 프로젝트의 next dev가 실제로 실행 중인가.
  • 실행 중인 프로세스는 없지만 비정상 종료 뒤 .next/dev/lock만 남았는가.
실행 중인 Next.js 프로세스가 있는지에 따라 정상 종료와 잔여 lock 처리로 갈라지는 판단 흐름

프로세스 이름보다 프로젝트 경로를 확인한다

가장 안전한 방법은 열어 둔 터미널을 돌아보는 것이다. Local: http://localhost:3000처럼 개발 서버 주소가 보이고 입력 대기 상태가 아니라면 그 터미널이 잠금을 가진 서버일 가능성이 높다. 브라우저에서 해당 주소를 열어 현재 프로젝트 화면인지 확인한 뒤 그 터미널에서 Ctrl+C를 누른다.

터미널을 찾지 못했다면 운영체제에서 프로세스의 명령줄을 본다. Microsoft의 Get-CimInstance 문서에 따라 Windows PowerShell에서는 다음 명령으로 실행 중인 Node 프로세스의 PID와 명령줄을 확인한다.

Get-CimInstance -ClassName Win32_Process -Filter "Name = 'node.exe'" |
  Select-Object ProcessId, CommandLine

출력에서 현재 프로젝트 경로와 next dev가 함께 들어간 행을 찾는다. 포트 3000을 쓴다고 확실하다면 Microsoft가 설명하는 Get-NetTCPConnection으로 수신 포트와 소유 PID를 보조 증거로 확인한다.

Get-NetTCPConnection -State Listen -LocalPort 3000 |
  Select-Object LocalAddress, LocalPort, OwningProcess

macOS나 lsof가 설치된 Linux에서는 lsof 프로젝트의 네트워크 소켓 조회법으로 포트 리스너를 확인한다.

lsof -nP -iTCP:3000 -sTCP:LISTEN

포트는 단서일 뿐이다. next dev -p 4000처럼 다른 포트로 실행했다면 3000번 검색에는 나오지 않는다. 그래서 PID만 보지 말고 명령줄의 프로젝트 경로까지 대조해야 한다. 이름이 node라는 이유로 모든 Node 프로세스를 종료하면 다른 개발 서버와 도구까지 함께 꺼질 수 있다.

살아 있는 서버는 종료하고, 남은 lock만 제한적으로 지운다

프로젝트를 실행 중인 터미널을 찾았다면 그 자리에서 Ctrl+C로 종료한다. 이것이 첫 선택이다. 터미널을 잃었고 정확한 PID와 프로젝트 경로를 확인했다면 Microsoft의 Stop-Process에 확인 프롬프트를 붙여 해당 PID만 종료할 수 있다.

Stop-Process -Id <확인한_PID> -Confirm

macOS나 Linux에서도 먼저 일반 종료 신호를 보낸다.

kill <확인한_PID>

즉시 -9를 붙이는 강제 종료는 첫 선택으로 두지 않는다. 종료 뒤 2~3초 기다렸다가 같은 PID가 사라졌는지 다시 확인한다.

프로세스 목록과 열어 둔 터미널 어디에도 현재 프로젝트의 next dev가 없는데 오류가 반복되면 비정상 종료 뒤 잠금 파일만 남은 상황을 의심할 수 있다. 이때도 .next 전체나 node_modules를 먼저 지우지 않는다. 현재 프로젝트 루트가 맞는지 확인한 뒤 .next/dev/lock 파일만 삭제하고 다시 실행한다.

Windows PowerShell:

Remove-Item -LiteralPath '.next\dev\lock'
npm run dev

macOS/Linux:

rm .next/dev/lock
npm run dev

이 분기는 실행 중인 프로젝트 프로세스가 없다고 확인했을 때만 쓴다. 서버가 살아 있는데 lock 파일부터 지우면 두 프로세스가 같은 개발 출력에 접근하도록 잠금의 보호를 무너뜨릴 수 있다.

개발 서버 하나와 URL 응답으로 끝낸다

재시작에 성공하면 터미널에 로컬 URL이 한 번 표시되고 입력을 기다리는 개발 서버가 하나만 남아야 한다. 브라우저에서 그 URL을 열어 현재 프로젝트의 첫 화면이나 수정한 경로가 응답하는지 확인한다. 포트를 바꿨다면 예전 탭이 아니라 새 터미널에 표시된 주소를 연다. 화면이 그대로라면 저장·서버·포트를 나눠 확인하는 순서로 이어가면 잠금 문제와 캐시·저장 문제를 섞지 않을 수 있다.

Windows와 macOS Linux에서 프로젝트 프로세스 확인부터 단일 서버 URL 검증까지 이어지는 체크리스트

마지막 확인은 짧다.

  • 현재 프로젝트 경로를 가진 next dev 프로세스가 하나인가.
  • 새 터미널에 오류 대신 로컬 URL이 표시됐는가.
  • 그 URL에서 현재 프로젝트 화면이 열리는가.
  • 다음 종료 때 터미널에서 Ctrl+C를 눌러 정상 종료했는가.

개발 서버를 여러 개 다룬다면 터미널 탭 이름에 프로젝트명을 붙이고, 서버를 닫을 때 창부터 닫지 말고 Ctrl+C 결과를 확인한다. 다음에 같은 오류가 떠도 삭제부터 하지 않고 프로세스와 프로젝트 경로부터 보는 습관이 남아야 한다.

참고 출처

이 글은 AI 코딩과 개발 학습의 일반 정보 제공 목적입니다. 도구, 모델, 커리큘럼, 요금은 버전과 시점에 따라 달라질 수 있으므로 실습이나 도입 전 공식 문서와 최신 릴리스 노트를 확인하세요.

다음으로 읽을 기사

같은 흐름으로 이어 읽기 좋은 기사만 추려 보여줍니다.

댓글 0

이 글을 읽은 독자들의 생각을 나눠보세요.

비밀번호(선택)

첫 번째 댓글을 남겨보세요

여러분의 생각이 다른 독자에게 도움이 됩니다.