next.js
프로젝트를 서버에 배포하고 빌드하는 과정에서 두 가지 주요 오류가 발생했다🤦♀️.
이 글에서는 위의 문제의 원인과 해결 과정을 공유하고자 한다.
next build
명령을 실행했을 때 다음과 같은 오류가 발생했다.
> Build error occurred
[Error: EACCES: permission denied, unlink '/.../.next/server/middleware-manifest.json'] {
errno: -13,
code: 'EACCES',
syscall: 'unlink',
path: '/.../.next/server/middleware-manifest.json'
}
도대체 middleware-manifest가 뭔데 여기 접근을 못하는걸까?
middleware-manifest.json
middleware-manifest.json 파일은 Next.js 빌드 시 생성되는 내부 메타데이터 파일 중 하나다.
Middleware, Edge Functions 및 관련 라우팅 정보를 Next.js 런타임에서 사용하기 위해 이 매니페스트 파일에 포함된다.
일반적으로 next build 시 자동으로 생성되며, .next/server/
디렉토리 내부에 위치한다.
여기서 에러메세지를 보면 빌드 프로세스 중에 이 파일에 접근할 수 없어서 에러가 발생했다는 뜻이다.
즉, Next.js
가 빌드 과정에서 middleware-manifest.json 파일을 삭제하거나 수정하려고 했지만, 해당 파일에 대한 충분한 권한이 없어서 build를 실패하는 것이다.
.next
디렉토리 삭제 후 다시 빌드가장 먼저 시도해 볼 수 있는 방법은 기존 빌드 결과물인 .next
디렉토리를 삭제하고 다시 빌드하는 것이다.
sudo rm -rf /경로/.next
npm run build
하지만, 이 방법으로 해결되지 않았고, 동일한 오류가 계속 발생했다.
권한
변경오류 메세지처럼 파일/디렉토리 권한 문제일 가능성이 높으므로, .next
디렉토리에 대한 권한을 변경했다.
sudo chmod -R 777 /경로/.next
npm run build
chmod -R 777은 모든 사용자에게 모든 권한을 부여하므로 보안상 권장되지 않는다.
임시적인 해결책이나 테스트 환경에서만 사용하는 것이 좋으며, 실제 운영 환경에서는 빌드를 실행하는 사용자에게 필요한 최소한의 권한만 부여하거나 파일 소유권을 올바르게 설정하는 것이 바람직하다.
(예: sudo chown -R $(whoami) /프로젝트경로/.next)
권한 문제를 해결한 후 npm run build가 성공하고 서버를 시작하려고 할 때 다음과 같은 포트 충돌 오류가 발생했다.
Browserslist: caniuse-lite is outdated. Please run:
0|ccap-admin-stg | npx browserslist@latest --update-db
0|ccap-admin-stg | Why you should do it regularly: https://github.com/browserslist/browserslist#browsers-data-updating
0|ccap-admin-stg | Error: listen EADDRINUSE: address already in use :::8090
0|ccap-admin-stg | at Server.setupListenHandle [as _listen2] (node:net:1463:16)
0|ccap-admin-stg | at listenInCluster (node:net:1511:12)
0|ccap-admin-stg | at Server.listen (node:net:1599:7)
0|ccap-admin-stg | at /경로/server.stg.js:25:6 {
0|ccap-admin-stg | code: 'EADDRINUSE',
0|ccap-admin-stg | errno: -98,
0|ccap-admin-stg | syscall: 'listen',
0|ccap-admin-stg | address: '::',
0|ccap-admin-stg | port: 8090
0|ccap-admin-stg | }
0|ccap-admin-stg | error - uncaughtException: Error: listen EADDRINUSE: address already in use :::8090
EADDRINUSE 오류는 Error: Address Already in Use의 약자로, 애플리케이션이 사용하려고 하는 네트워크 포트(이 경우 8090)를 이미 다른 프로세스가 사용하고 있음을 의미한다.
해당 프로젝트의 경우, 8090 포트는 현재 Next.js 애플리케이션(FE)이 사용하도록 설정된 포트다.
뭔가 이전에 비정상적으로 종료되었거나 다른 방식으로 실행된 동일 애플리케이션의 인스턴스가 포트를 계속 점유하고 있을 가능성이 높다.
먼저, 어떤 프로세스가 8090 포트를 사용하고 있는지, 그리고 PM2로 관리되는 관련 프로세스가 있는지 확인했다.
ss -tulpn | grep 8090
pm2 list
ss -tulpn | grep 8090
tcp LISTEN 0 511 *:8090 *:*
[서버 계정]$ pm2 list
[PM2] Spawning PM2 daemon with pm2_home=/경로/.pm2
[PM2] PM2 Successfully daemonized
┌────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │
└────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘
ss 명령어 결과, 8090 포트가 LISTEN 상태인 것을 확인했다.
하지만 pm2 list 결과에는 해당 포트를 사용하는 것으로 예상되는 PM2 프로세스가 없었다.
이는 이전 애플리케이션이 PM2를 통하지 않고 실행되었거나, PM2 프로세스가 비정상 종료되어 포트만 점유된 상태일 수 있다고 판단했다.
sudo kill -9 $(sudo fuser -n tcp 8090 2>/dev/null)
pm2 start ecosystem.stg.config && pm2 logs 0
원인 불명의 프로세스가 8090 포트를 점유하고 있으므로, 해당 프로세스를 찾아 강제로 종료했다. fuser 명령어를 사용하면 특정 포트를 사용하는 프로세스의 PID를 찾아 종료할 수 있다.