TechFeedTechFeed
개발자 작업환경

EACCES, permission denied, EPERM | 권한이 없다고 나오면?

EACCES는 문법이 틀린 게 아니라 그 포트나 파일을 열 권한이 프로세스에 없어 운영체제가 거절한 줄입니다. 80번 listen, npm 전역 prefix, 도커 uid. Node.js, npm, 맥, 한국 1인 개발자 기준. 2026년 9월 Node.js 시스템 에러·npm EACCES 문서.

by

EACCES는 문법이 틀린 게 아니라, 그 포트나 파일을 열 권한이 지금 프로세스에 없어서 운영체제가 거절한 줄입니다. permission deniedEPERM도 같은 칸에 가깝고, 코드를 고치기 전에 누가 그 자원을 소유했는지부터 봅니다.


개발 서버를 80번에 띄우거나, npm을 전역으로 깔다가, 도커가 만든 파일을 맥에서 지우려다 자주 만납니다. 에러 메시지 끝의 경로와 포트 숫자를 먼저 읽으세요.


sudo로 덮기 전에 소유자와 모드를 맞추는 편이 안전합니다. 크론이 홈이 아닌 경로에 쓰다가 같은 줄이 나기도 합니다. 근거는 Node.js 시스템 에러npm EACCES 문서에 있습니다.


EACCES는 코드가 아니라 권한 줄이다

운영체제가 그 동작을 막아서입니다. 노드는 파일을 열거나 포트에 listen할 때 커널에 부탁하고, 커널이 거절하면 EACCES를 그대로 올립니다. 패키지 버전이 아니라 uid와 모드 문제입니다.


메시지에 경로가 있으면 그 파일이나 디렉터리의 소유자를 보고, :80이나 :443이 있으면 특권 포트를 의심합니다. 유닉스에서 1024 미만 포트는 root만 열 수 있는 경우가 많습니다. 개발 중 next start -p 80을 치면 여기로 떨어집니다.


EPERM은 조금 더 강한 거절입니다. 권한 비트가 맞아 보여도 커널 정책이나 macOS TCC가 막을 때 납니다. 둘 다 "그 프로세스에게 허용되지 않았다"는 뜻이라, 코드를 리팩터하기 전에 실행 사용자부터 확인하세요.


경로와 포트 숫자부터 | EACCES: permission denied, open '/usr/local/lib/...' 면 전역 npm이고, listen EACCES: permission denied 0.0.0.0:80이면 포트입니다. 같은 코드라도 고치는 칸이 다릅니다.


프로세스가 파일이나 특권 포트를 열려다 운영체제가 EACCES로 거절하는 개념 이미지
권한이 없으면 커널이 시스템 호출을 거절한다

포트 1024 미만과 파일 권한을 나누기

숫자 포트와 디스크 경로는 처방이 다릅니다. 표를 먼저 보고 자기 메시지에 맞는 칸만 고치세요.


메시지원인먼저 할 일
listen EACCES ... :80특권 포트3000번으로 올리거나 리버스 프록시
open '.../node_modules/.bin'디렉터리 쓰기 권한소유자·모드 확인 후 chmod
mkdir '/usr/local/lib/node_modules'전역 npm 경로prefix를 홈으로 옮기기
unlink '.../public/uploads'도커가 root로 만든 파일컨테이너 user와 볼륨 uid
EPERM fchmod파일시스템 정책, 불변 플래그chflags·마운트 옵션

포트가 이미 사용 중인 줄과 섞지 마세요. EADDRINUSE는 누가 앉아 있다는 뜻이고, EACCES는 앉을 자격이 없다는 뜻입니다. 점유는 포트 점유 글에서 다룹니다.


포트와 파일 소유자 확인
# 특권 포트인지 # 80, 443이면 일반 사용자 listen이 거절될 수 있다 PORT=3000 npm run dev # 경로 소유자 ls -ld node_modules public/uploads id # 맥에서 잠긴 플래그 ls -lO some-file

npm 전역 설치에서 자주 나는 이유

전역 prefix가 root 소유라서입니다. npm install -g/usr/local에 쓰려다 막히면 sudo를 붙이고 싶어지지만, 그다음부터 폴더 소유자가 root로 굳습니다.


npm 공식 문서는 prefix를 홈 디렉터리로 옮기라고 안내합니다. mkdir ~/.npm-global 뒤에 npm config set prefix ~/.npm-global을 하고, PATH에 ~/.npm-global/bin을 넣으면 됩니다. nvm이나 mise를 쓰면 전역 설치 자체가 사용자 폴더 안에서 끝나 이 줄을 피할 수 있어요. 버전 관리기는 mise·nvm 글을 참고하세요.


이미 sudo로 깔아 버린 node_modules가 있으면 그 폴더를 지우고 일반 사용자로 다시 설치하는 편이 낫습니다. root로 남은 바이너리는 나중에 크론·launchd가 다른 uid로 실행할 때 또 EACCES를 냅니다.


전역 prefix를 홈으로
mkdir -p "$HOME/.npm-global" npm config set prefix "$HOME/.npm-global" export PATH="$HOME/.npm-global/bin:$PATH" # ~/.zshrc 에도 같은 PATH를 넣는다 # 이미 root 소유면 ls -ld /usr/local/lib/node_modules # sudo chown -R "$(whoami)" 는 최후. prefix 이전이 먼저
npm 전역 prefix를 홈 디렉터리로 옮겨 EACCES를 피하는 설정 흐름 이미지
전역 설치 경로를 홈으로 두면 sudo가 필요 없다

도커·맥에서 소유자가 어긋날 때

컨테이너가 root로 파일을 만들면 호스트 uid와 안 맞습니다. 바인드 마운트한 public/uploads나 빌드 산출물이 대표적이에요. 호스트에서 지울 때 permission denied가 납니다.


compose에 user: "1000:1000"을 두거나 이미지에서 비root 유저를 쓰는 방법이 있습니다. 개발용으로만 급하면 호스트에서 해당 폴더 소유자를 맞추되, 습관적으로 chmod 777은 피하세요. 넥스트 크론이 같은 폴더에 쓰면 다음 작업이 또 막힙니다.


노드 20+의 권한 모델로 스크립트가 파일 접근을 거절하는 줄은 시스템 EACCES와 다릅니다. --permission 플래그 쪽은 노드 권한과 크론 글을 보세요. 시스템 줄은 ls -l로 설명이 되고, 권한 모델 줄은 플래그 허용 목록으로 설명이 됩니다.


  • [ ] 메시지에서 포트 숫자와 파일 경로를 구분했다
  • [ ] 80·443이면 개발 포트를 3000대로 옮겼다
  • [ ] npm 전역이면 prefix를 홈으로 옮겼다
  • [ ] 도커 볼륨 파일은 컨테이너 user와 uid를 맞췄다
  • [ ] chmod 777과 sudo 상시 실행은 쓰지 않았다

sudo npm은 임시 덮개 | root로 설치한 트리는 다음 명령이 일반 사용자로 실행될 때 다시 막힙니다. prefix를 옮기거나 버전 관리기 안의 글로벌을 쓰세요.


고치는 순서

메시지 분류, 소유자 확인, 포트 변경 또는 prefix 이전 순입니다. 한 번에 sudo를 붙이면 원인 칸이 가려집니다.


개발 서버는 3000대를 쓰고, 80·443은 엔진엑스나 클라우드 로드밸런서에 맡기는 구성이 흔합니다. 파일 쪽은 ls -ld로 소유자를 본 뒤 필요한 디렉터리만 고칩니다. 모듈을 못 찾는 줄과 같이 오면, 설치가 root로 되어 일반 사용자가 node_modules를 못 읽는 경우입니다. 그때는 모듈 탐색 글보다 권한을 먼저 맞추세요.


한국에서 넥스트를 혼자 맥에 두고 도커로 DB만 띄우는 구성이면, 업로드 폴더 uid 불일치가 가장 자주 반복됩니다. 한 번 소유자를 맞춘 뒤 compose user를 고정해 두는 편이 낫습니다.


특권 포트와 파일 소유자를 나눠 EACCES를 고치는 실전 순서 이미지
포트 숫자와 경로를 나눈 뒤에 처방이 갈린다

참고 자료


내부 연계: 포트 점유, 노드 권한과 크론, 노드 버전 관리


인용한 동작은 2026년 9월 공개 문서 기준입니다.


자주 묻는 질문

sudo로 서버를 띄우면 해결되나요?

80번을 잠깐 열 수는 있습니다. 산출물과 로그 소유자가 root가 되어 다음 명령이 또 막힙니다. 개발은 3000대를 쓰고 앞단에 프록시를 두는 편이 안전합니다.


EPERM과 EACCES는 어떻게 나누나요?

EACCES는 권한 비트로 설명이 되는 거절이 많고, EPERM은 연산 자체가 정책으로 막힌 때에 가깝습니다. 실무에서는 둘 다 실행 사용자와 경로부터 확인하고, 맥이면 TCC와 파일 플래그까지 봅니다.


npm install만 하면 납니다.

전역 prefix나 예전에 sudo로 만든 node_modules입니다. 프로젝트 폴더 소유자를 whoami와 비교하고, 전역이면 prefix를 홈으로 옮기세요. 설치 트리 피어 충돌은 ERESOLVE 칸입니다.


도커 올린 파일을 맥에서 못 지웁니다.

컨테이너가 root로 써서 호스트 uid와 다릅니다. compose user를 맞추거나, 그 작업만 컨테이너 안에서 지우세요. 777은 다음 크론까지 문제를 미룹니다.


윈도우에서도 같은 줄인가요?

메시지는 EPERM이나 액세스 거절로 나옵니다. 관리자 권한 터미널, 백신 잠금, 다른 프로세스가 파일을 연 상태를 봅니다. 포트 80은 IIS나 월드 와이드 웹 게시 서비스와 겹치기도 합니다.


크론에서만 권한이 없다고 합니다.

크론 사용자는 로그인 셸과 다를 수 있습니다. 작업 디렉터리, 로그 경로, npm prefix를 그 사용자 기준으로 두세요. 노드 권한 플래그를 켠 스크립트면 허용 경로도 같이 확인합니다.


EACCES는 그 프로세스에게 포트나 파일이 허용되지 않았다는 뜻입니다. 메시지에서 숫자 포트와 경로를 나누고, sudo 대신 소유자와 prefix를 맞추세요. 관련 글: 포트 점유, 노드 권한, 모듈을 찾을 수 없음.


EACCESpermission deniedEPERM포트npm도커권한노드작업환경개발자

함께 보면 좋은 문제 해결

EXPLORE / 개발자 작업환경

이어서 읽어보기

전체 토픽 둘러보기