TechFeedTechFeed
개발자 작업환경

EMFILE, too many open files, ulimit | 파일을 더 못 열면?

EMFILE은 디스크가 가득 찬 줄이 아니라 그 프로세스가 동시에 열 수 있는 파일 개수 한도를 이미 다 써서 새 파일을 못 연 줄입니다. ENOSPC 워처와 구분, ulimit, launchd, watch ignored. Node.js, Next.js, 맥, 한국 1인 개발자 기준. 2026년 9월 Node.js 에러·webpack watch 문서.

by

EMFILE은 디스크가 가득 찬 줄이 아니라, 그 프로세스가 동시에 열 수 있는 파일 개수 한도를 이미 다 써서 새 파일을 못 연 줄입니다. ENOSPC 워처 한도와 자리가 다릅니다.


넥스트 개발 서버를 켜다 Error: EMFILE: too many open files, watch가 뜨는 일, 맥에서 사이트를 여러 개 띄우면 한 번은 만납니다. 한도만 올리면 잠깐 넘어가지만, 감시 폴더를 안 줄이면 같은 줄이 돌아옵니다.


셸에서 ulimit -n을 보고, node_modules는 감시에서 빼세요. 근거는 Node.js 에러 문서getrlimit 매뉴얼에 있습니다.


EMFILE은 워처 개수 한도와 다른가

파일 디스크립터 한도가 찬 줄입니다. 노드는 파일, 소켓, 감시 핸들을 모두 이 한도 안에서 엽니다. 한 칸이 남아 있지 않으면 open이나 watch가 EMFILE을 던집니다.


Node.js 문서도 EMFILE을 "시스템에서 허용하는 파일 디스크립터를 이미 다 썼다"고 적습니다. 맥은 기본 한도가 낮은 편이라, 같은 프로젝트를 리눅스 CI에선 되고 노트북에서만 터지는 경우가 잦습니다.


ENOSPC file watchers는 리눅스 inotify 감시 개수입니다. 디스크 용량도 아니고, 파일 디스크립터도 아닙니다. 워처가 멈추면 ENOSPC 글을 보고, 여기 줄은 한도 숫자부터 보세요.


메시지한도 종류먼저 볼 것
EMFILE too many open files프로세스 파일 디스크립터ulimit -n, lsof -p PID
ENOSPC file watchers리눅스 inotify 감시 개수fs.inotify.max_user_watches
ENOSPC no space left디스크 용량df -h
heap out of memory노드 힙max-old-space-size

먼저 읽을 것 | 메시지에 watch가 있으면 감시 핸들이 한도를 채운 겁니다. open이면 파일을 한꺼번에 연 쪽입니다. 같은 EMFILE이라도 고치는 칸이 갈립니다.


터미널에 EMFILE too many open files 에러가 뜬 개발 서버 화면 개념 이미지
EMFILE은 디스크가 아니라 그 프로세스가 연 파일 개수 한도다

한도를 어디서 확인하나

소프트 한도와 하드 한도를 같이 봅니다. ulimit -n은 지금 셸의 소프트 한도, ulimit -Hn은 하드 한도입니다. 소프트를 하드보다 높게 올리면 거절됩니다.


프로세스가 실제로 연 개수는 lsof -p PID | wc -l로 셉니다. 넥스트 개발 서버 PID를 넣어 보면, node_modules 아래 파일이 대부분입니다. 감시가 그 폴더까지 따라가면 한도가 금방 찹니다.


리눅스 컨테이너는 호스트 한도와 따로 갑니다. 도커에서 ulimit -n이 1024로 고정된 이미지가 많고, 그 안에서 next dev나 테스트가 한꺼번에 파일을 열면 로컬 맥보다 먼저 죽습니다.


한도와 열린 파일 개수 확인
# 지금 셸 한도 ulimit -n ulimit -Hn # 넥스트 개발 서버가 연 파일 개수 lsof -p $(lsof -ti :3000) | wc -l # 리눅스 프로세스 한도 cat /proc/$(lsof -ti :3000)/limits | grep 'open files'

맥 launchd는 셸 ulimit을 안 물려 준다

터미널에서 ulimit -n 10240을 올려도, 도크나 런처에서 켠 노드는 예전 한도를 씁니다. 맥 GUI 앱과 launchd 작업은 로그인 셸 설정을 물려받지 않습니다.


Node.js 문서는 같은 셸에서 ulimit -n 2048을 먼저 치고 노드를 켜라고 안내합니다. 크론, launchd, VS Code 작업 패널에서 켜는 서버는 그 셸이 아니라서, plist나 서비스 환경에 한도를 따로 적어야 합니다.


리눅스는 PAM limits.confnofile이 세션에 들어갑니다. systemd 서비스는 LimitNOFILE=을 유닛에 넣지 않으면 기본 1024에 머무는 경우가 많습니다. 한국에서 1인으로 맥 개발, 우분투 CI, 버셀 빌드를 섞으면 세 환경의 숫자가 서로 다릅니다.


환경한도를 올리는 자리주의
맥 터미널ulimit -n, ~/.zshrcGUI 앱에는 안 먹힘
맥 launchdplist SoftResourceLimits셸 rc와 별개
리눅스 세션limits.conf nofile재로그인 후 적용
systemdLimitNOFILE=유닛마다 따로

ulimit과 lsof로 프로세스 파일 한도를 확인하는 터미널 장면
한도를 올린 셸에서 켠 노드만 그 숫자를 쓴다

감시 폴더를 줄이는 쪽이 먼저다

한도를 올리기 전에 감시 대상을 줄이세요. 웹팩과 넥스트는 node_modules, .git, .next까지 따라가면 파일 핸들이 수천 개로 늘어납니다. ignored를 넣으면 같은 한도에서도 버팁니다.


워치팩 문서는 watchOptions.ignored로 정규식이나 경로를 빼라고 안내합니다. 넥스트는 기본적으로 node_modules를 건너뛰지만, 모노레포에서 워크스페이스 패키지를 심링크하면 다시 따라가는 경우가 있습니다.


파일을 한꺼번에 읽는 스크립트도 같은 줄이 납니다. Promise.all로 천 개 파일을 동시에 readFile하면 한도를 순식간에 채웁니다. 동시에 열 개수를 제한하거나, 스트림으로 읽고 닫는 편이 안전합니다. 설치 트리가 어긋나 감시가 이상해진 경우는 피어 충돌과 자리가 다릅니다.


감시에서 node_modules를 빼기
// next.config.js 예시 const nextConfig = { webpack: (config, { dev }) => { if (dev) { config.watchOptions = { ignored: ['**/node_modules/**', '**/.git/**', '**/.next/**'], } } return config }, } module.exports = nextConfig
  • [ ] 메시지에 watch인지 open인지 구분했다
  • [ ] ulimit -n과 실제 lsof 개수를 비교했다
  • [ ] node_modules, .git, .next를 감시에서 뺐다
  • [ ] 크론, launchd면 그 환경 한도를 따로 올렸다
  • [ ] 파일을 한꺼번에 여는 스크립트는 동시 개수를 제한했다

실전에서 고르는 순서

메시지에 watch가 있으면 감시부터 줄입니다. 그래도 남으면 그 셸에서 ulimit -n을 올리고 서버를 다시 켭니다. 포트가 남아 서버가 안 뜨는 줄은 EADDRINUSE입니다. 모듈을 못 찾는 줄은 Cannot find module입니다.


한도를 10만으로 올리는 건 최후입니다. 핸들이 새는 스크립트를 가리면, 올린 한도도 다시 찹니다. 빌드가 메모리로 죽는 줄은 힙 부족이라 여기 숫자와 무관합니다.


한국에서 맥 한 대로 여러 넥스트 사이트를 띄우는 경우, 프로젝트마다 개발 포트를 나누고 안 쓰는 서버는 Ctrl+C로 내리는 습관이 한도를 가장 빨리 낮춥니다. 워처만 문제면 ENOSPC 글을 같이 보세요.


한 노트북에서 사이트 여러 개를 동시에 켜 두면, 감시 핸들이 사이트 수만큼 쌓입니다. 지금 손보는 프로젝트만 남기고 나머지는 내리는 편이 한도를 올리는 것보다 빠릅니다. 빌드 스크립트가 로그 파일을 닫지 않고 쌓아 두는지도 같이 보세요. 열어 둔 채 방치된 파일이 있으면 개발 서버와 합쳐져 같은 줄이 다시 납니다. 새벽에 크론이 같은 저장소를 한 번 더 열면 낮에 켠 서버와 한도를 나눠 쓰니, 그때만 죽는 증상도 이 줄로 이어집니다. 숫자를 올리기 전에 지금 무엇이 파일을 붙잡고 있는지부터 세는 편이 짧습니다. 한도 숫자만 키워 두면 원인은 남고, 다음 프로젝트에서 같은 빨간 줄이 다시 올라옵니다.


감시 폴더를 줄인 뒤 파일 한도를 확인하고 개발 서버를 다시 켜는 순서 이미지
감시 대상을 줄인 다음, 같은 셸에서 한도를 올리고 서버를 켠다

참고 자료


내부 연계: ENOSPC 워처 한도, 포트 점유, 힙 메모리, 모듈을 찾을 수 없음


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


자주 묻는 질문

EMFILE은 디스크가 가득 차서 나나요?

아닙니다. 그 프로세스가 열 수 있는 파일 개수 한도가 찬 줄입니다. 디스크 용량은 df로 보고, 워처 개수는 ENOSPC 쪽입니다. 여기 줄은 ulimit과 lsof부터 보세요.


터미널에서 ulimit을 올렸는데 도크에서 켠 서버는 그대로입니다.

맥 GUI와 launchd는 로그인 셸 한도를 안 물려받습니다. 그 앱을 끈 뒤, 한도를 올린 터미널에서 npm run dev를 다시 켜세요. 상주 작업이면 plist에 SoftResourceLimits를 적습니다.


ENOSPC file watchers와 무엇이 다른가요?

ENOSPC 워처는 리눅스 inotify 감시 개수입니다. EMFILE은 파일 디스크립터입니다. 맥에선 inotify가 없어서 ENOSPC 워처 줄이 잘 안 나고, EMFILE이 더 자주 보입니다.


graceful-fs를 넣으면 해결되나요?

open을 큐에 넣어 재시도하므로 잠깐 넘어갈 수 있습니다. 감시 핸들이 한도를 채운 watch 줄은 그대로일 수 있습니다. 감시 폴더를 줄이는 쪽이 먼저입니다.


도커 안에서만 납니다.

컨테이너 기본 nofile이 1024인 이미지가 많습니다. docker run --ulimit nofile=10240:10240 또는 compose ulimits를 넣고, 이미지 안에서도 ulimit -n을 확인해 보세요.


한도를 크게 올리면 끝나나요?

잠깐은 됩니다. 핸들이 새거나 감시가 의존성 폴더를 따라가면 큰 숫자도 다시 찹니다. 감시에서 빼는 설정과 동시 열기 제한을 먼저 넣고, 한도는 그다음에 올리세요.


EMFILE은 그 프로세스가 연 파일 개수 한도가 찬 줄입니다. watch면 감시 폴더를 줄이고, 같은 셸에서 ulimit을 확인한 뒤 서버를 다시 켜세요. 관련 글: ENOSPC 워처, 포트 점유, 힙 부족.


EMFILEtoo many open filesulimit워처넥스트노드작업환경파일 한도개발자
EXPLORE / 개발자 작업환경

이어서 읽어보기

전체 토픽 둘러보기