[Node.js] 시놀로지 Docker + Node.js 서버 [Error: ENOENT: no such file or directory, open '***'] 오류 해결


Node.js + Vue.js 로 만든 프로젝트 완성 후 제대로 작동하는걸 확인해 시놀로지 NAS로 서버를 옮기는 작업을 했습니다.

첫번째로 한 작업은 Node.js 와 Vue.js 프로젝트를 코드 하나로 통합하는 작업이였습니다.

 

프론트엔드단 Vue Cli로 생성한 Vue.js 코드는 웹 서버가 내장되어 있어서 8080 포트로 따로 돌아가고, 백엔드단 Node.js는 Express 프레임워크를 이용해서 API 서버를 제작했는데 3000번 포트로 돌아가게 됩니다.

 

프론트엔드단과 백엔드단이 깔끔하게 분리되어 제작된 바람직한 코드지만 웹 서버도 실제로 2개나 돌아가서 배포할때는 비효율적인 구조입니다. 그래서 Vue.js 에서 WebPack 을 이용해 빌드 과정을 거쳐서 HTML CSS JS 로 통합 파일을 생성한다음에 만들어진 index.html 을 Node.js Express 루트 라우터 ("/") 에 제공해주면

 

Node.js Express 웹 서버와 Vue 프로젝트가 통합되게 됩니다.

이제 Node.js Express 서버만 키면 Vue에서 만든 프론트엔드단 화면하고 뒤에서 돌아가는 백엔드단 코드까지 통합되어 돌릴 수 있는 것이죠.

 

시놀로지에서 Docker을 킨다음에 Node.js 이미지를 설치하고 만든 Node.js 서버 JS 코드(api-server.js)를 실행시켜 주었습니다.

잘 될것이라는 기대와는 반대로 다음과 같은 오류를 만났습니다.

 

[Error: ENOENT: no such file or directory, open './json_data/data.json'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: './json_data/data.json'
}

 

이 오류는 단순히 말해서 ./json_data/data.json 경로에 있는 파일을 읽어낼 수 없다는 뜻입니다. 분명 윈도우에서 VSCode로 개발할땐 "코드를 실행한  경로를 기준"으로 상대 경로로 잘 찾아냈지만, Docker로 생성한 가상 환경의 경우 상대 경로의 기준점이 실행한 JS 파일의 위치가 아니라는 문제점을 알아냈습니다.

 

해결 방법을 생각해보자면 저 파일 경로를 잡을때 현재 실행한 js 파일의 경로와 저 상대 경로 ./json_data 부분을 합쳐주면 됩니다. 

 

그래서 코드를 아래와 같이 수정했습니다.

 

// 출처 : https://inpa.tistory.com/entry/NODE-%F0%9F%93%9A-Path-%EB%AA%A8%EB%93%88-%F0%9F%A7%B7-%EA%B2%BD%EB%A1%9C-%EC%A0%9C%EC%96%B4
// path 모듈은 운영체제별로 경로 구분자가 달라 생기는 문제를 쉽게 해결하기 위해 등장했다.
// 윈도우 : 경로 구분에 역슬래시 이용
// 리눅스 : 경로 구분에 슬래시 이용

// path 모듈을 사용하면 폴더와 파일의 경로를 쉽게 조작할 수 있어 위와 같은 경로 구분자 이슈를 쉽게 해결하고,
// 이외에 파일명에서 파일명, 확장자를 별도로 때어서 활용할 수 있 수 있다.

//path 모듈 추가
const path = require("path");

//경로를 아래와 같이 수정
const excel_path = path.resolve(__dirname, "./excel_files"); //엑셀 파일 경로
const json_path = path.resolve(__dirname, "./json_data", "data.json"); //DB 대신에 저장용 파일 시스템 경로

path 모듈을 추가하고 기존에 문자열로 단순히 "./json_data" 라고 처리되었던 경로를 path.resolve 함수를 통해서 __dirname 과 합쳐줍니다.

 path.resolve 함수를 이용하면 인자값으로 들어온 경로를 잘 합쳐서 절대 경로로 반환해줍니다.

 

저렇게 하면 실행 중인 폴더 경로 + 상대 경로랑 잘 합쳐서 절대 경로가 만들어져서 파일을 어디에 옮기던지 폴더 경로를 잘 찾아낼 수 있고, path 모듈을 사용했기 때문에 운영체제가 상이해서 경로 구분자가 다른 (슬래시, 역슬래시) 문제도 해결해줍니다.

 

* path 모듈을 사용하는 이유는 위에 4줄 주석에 잘 적어놨습니다.

__filename : 현재 실행 중인 파일 경로

__dirname : 현재 실행 중인 폴더 경로

 

사람들이 경로 적어줄 때 그냥 ./경로로 안적고 __dirname 이랑 왜 합쳐서 만드는지 했는데 환경에 따라 이런 문제가 생길 수 있기 때문이였습니다..!

 

사실 처음에는 당연히 ./ 경로는 실행한 JS 파일 경로일 줄 알았는데 Docker은 가상 환경이라 다르게 나온다는 점을 ./ 경로를 console.log 로 찍어서 로그로 보기전까지 깨닫지 못했습니다 ㅎㅎ;;

 

어쨌던 이번에도 배워가네요. 혹시 Node.js 로 프로젝트 진행하시다가 잘 작동하는 코드가 Docker + Node.js 환경으로 옮겼을때 파일 못찾는 문제가 발생하면 해당글 참고해보세요! 감사합니다.

COMMENT WRITE