본문 바로가기

javascript/nodejs

[npm] errno -4092 | EACCES 에러

오늘 npm을 사용했는데, 어제까지는 발생하지 않았던 에러가 발생했다. 에러 내용은 아래와 같다.

마지막 실행 시점과 변경된 코드가 하나도 없는데 대체 이러한 에러가 왜 발생하는 것일까? 이를 알아보기 위해 우선 EACCES 에러가 무엇인지 먼저 알아보자.


EACCES 에러

 특정 모듈이 거의 모든 프로젝트에서 사용되는 경우, 우리는 해당 모듈을 전역적으로 설치한다. 이때 전역 모듈들이 설치되는 폴더는 따로 변경하지 않는 한 다음과 같은 경로에 존재한다.

  • %USERPROFILE%\AppData\Roaming\npm\node_modules
  • ~\AppData\Roaming\npm\node_modules : 위의 경로와 동일하게 처리된다.

 이때 대부분의 운영체제에서는 특정 파일에 대한 접근 권한을 지정할 수 있는데, 이렇듯 특정 파일에 지정된 권한에 의해 읽기, 쓰기, 실행 등이 제한되는 경우가 존재한다. EACCES 에러는 사용자에게 지정된 접근 권한에 의해 생기는 에러로, 위 언급한 전역 모듈이 저장되는 폴더에 대해 현재 유저가 접근 권한이 없어 사용할 수 없을 때 보통 발생한다. 

 해당 에러를 수정하기 위해 npm에서는 크게 두가지 방식을 추천한다. 

  1. npm 재설치 ( 가장 간단한 방식 )
  2. 전역 모듈 폴더를 변경 ( windows 환경은 해당 안됨 )

https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally

 

Resolving EACCES permissions errors when installing packages globally | npm Docs

Documentation for the npm registry, website, and command-line interface

docs.npmjs.com


npm 재설치

 nodist / nvm 등의 프로그램을 이용하거나, nodejs 공식 홈페이지를 방문하여 nodejs 및 npm을 재설치한다. 단순히 npm을 삭제했다가 다시 설치하는 것 뿐이므로, 자세한 설명은 하지 않는다.

 

전역 모듈 폴더의 변경

 전역 모듈 폴더의 경로 자체를 변경하는 방법으로, 기본 설정을 변경하게 되므로 권장되지는 않는다. 우선 npm을 재설치를 고려하되, 재설치가 불가능할 때 사용하자. Windows는 불가능하다고 한다.

  1. mkdir ~/.npm-global  : 유저의 기본 폴더에 .npm-global 파일을 생성한다
  2. npm config set prefex '~/.npm-global'  : npm이 새로운 폴더 경로를 사용하도록 설정한다
  3. export PATH=~/.npm-global/bin:$PATH  : .profile 파일 내에 설정을 추가한다.

만약 Windows 환경에서 위 코드를 실행했다면, 아래 과정을 따라 기존 설정으로 되돌릴 수 있다.

  1. 유저 기본 폴더( C:\Users\유저이름 ) 로 이동하여 .npm-global 폴더를 삭제한다.
  2. npm config set prefix '~\AppData\Roaming\npm'  :  전역 모듈 폴더의 경로를 기존 설정으로 되돌린다.
  3. 유저 기본 폴더 내의 .profile 내에서 3의 설정을 지운다.

 


다른 해결법

 위 방법으로 문제를 해결할 수도 있겠지만, 뭔가 이상하다 싶은 점이 있다. 정말로 폴더의 권한에 문제가 있었다면 어째서 여태까지 npm이 제대로 전역 모듈 경로를 찾을 수 있었을까? 정말 권한 문제가 맞았다면 이전에도 npm의 전역 모듈 폴더에 접근할 수 없었어야 했는데, 여태까지는 별 문제가 발생하지 않았다.

 아무런 설정도 변경된 것이 없음에도 에러가 발생한 것이므로, 우선 전역 모듈 경로가 문제가 아니라는 가정 하에 해결책을 찾아 보았다. 이때 스택 오버플로우를 탐색하던 도중, 한 글을 찾게 되었다.

https://stackoverflow.com/questions/59428844/listen-eacces-permission-denied-in-windows

 

listen EACCES: permission denied in windows

Everything was worked fine before today evening after i uninstalled vscode and installed again I'm facing this issue while try to run npm run app i have no clue how to fix this i tried to run vs c...

stackoverflow.com

 해당 글의 글쓴이는 vscode을 재설치했는데, 갑자기 EACCES 에러가 발생했다고 한다. node 및 npm에는 변화가 없으며, 정상적으로 인식됨에도 불구하고 에러가 발생한 것이 나의 상황과 유사해 보인다.

이에 대해 제시된 해결책은 다음과 같았다.

  1. 관리자 권한으로 PowerShell을 연다.
  2. net stop winnat 
  3. net start winnat

문제가 발생한 원인을 알아보기 전에, 먼저 몇가지 정보를 제시한다.


winnat 는 Windows 환경에서 NAT (Network Address Translation) 기술을 지원하기 위한 드라이버이다. 

 NAT은 하나의 공인 IP 주소 및 여러개의 사설 IP 주소를 상호 변환하는 기술로, 사설 IP 주소 및 공인 IP 주소의 포트넘버를 대응시키는 테이블을 이용하여 사설망을 외부 환경과 연결해주는 역할을 한다. 따라서 이론적으로 하나의 공인 IP 주소에는 포트 넘버의 한계만큼의 사설 IP 주소를 대응시킬 수 있다. 

 PORT 넘버는 0~65535 사이의 16진수 숫자로, 특정 프로세스 혹은 네트워크 서비스를 식별하는 논리적 구성이다. 네트워크 상에서 서로 다른 컴퓨터의 서로 다른 프로세스가 소통하기 위해서는 양방향에서 자신이 통신하는 프로세스를 식별해야 하는데, IP 주소 자체는 기기의 물리적 주소를 의미하기 때문에 해당 기기 내부에서 실행중인 프로세스의 정보를 담을 수 없다. 따라서 각각의 프로세스를 구분하려는 목적으로 포트넘버가 고안되었다.

 앞서 언급한 NAT은 각 프로세스를 구분하기 위한 목적으로 고안된 포트 넘버를 내부 사설망의 IP 주소와 1대 1로 대응시켜, 포트넘버를 기준으로 각 기기를 접근할 수 있도록 만든 기술이라고 할 수 있다. 


 현재 문제는 특정 포트넘버를 더 이상 사용하지 않으나, 운영체제가 해당 포트넘버를 사용하는 프로세스가 실행되고 있다고 오인하는 상황에서 발생한다. 특정 포트 넘버가 사용중이므로, 해당 포트에 대한 접근 권한이 없게 된다.

 예를 들어 vscode 에디터에서 특정 포트 넘버에 대해 들어오는 요청을 받아 페이지를 반환하는 서버를 실행 중일때, 실수로 에디터를 실수로 꺼버리면 어떻게 될까? 보통은 node나 에디터 선에서 알아서 프로세스를 종료하고 포트 넘버를 적당히 반환하겠지만, 어떤 경우에는 오류로 인해 OS에게 해당 포트 넘버가 비어있다는 사실을 알리지 못할 수 있다. 이 경우 OS 해당 포트 넘버를 이미 종료된 프로세스에게 계속 할당해주므로, 이후 해당 포트 넘버에 대해 프로그램을 다시 실행하더라도 "점유중" 인 포트넘버에 접근할 수 없어 접근 권한 에러가 발생하는 것으로 보인다.

 생각해보니 나 역시도 이전에 서버 실행 도중 운영체제를 종료했었는데, 이때 종료가 잘못되어 포트 넘버를 OS에게 제대로 반환하지 못한 것이 원인으로 보인다. 다음부터는 서버를 제대로 종료한 후 컴퓨터를 꺼야겠다.


결론

 npm의 EACCES 에러는 보통 전역 모듈이 설치되는 폴더에 대한 접근 권한이 없어 발생한다. 이 경우 node 및 npm을 재설치하거나, 전역 모듈 폴더의 경로를 변경하면 해결된다.

 일부 상황에서 포트 넘버가 이미 사용중이어서 ( 혹은 사용중으로 인식되어서 ) 이 에러가 발생할 수도 있는데, winnat을 멈췄다가 다시 실행하면 해결된다.

 서버 작동 중에 컴퓨터를 끌 때는 서버를 먼저 직접 종료한 후 컴퓨터를 종료하도록 하자.