[cafe24] node.js 호스팅으로 배포하기(next)

Coastby·2024년 12월 10일
0

기타

목록 보기
12/12
  1. next.js로 개발하여 배포
  2. 판매용 페이지로 추후 고객이 관리할 수 있어야 함 -> 국내 서비스 사용

언어별 호스팅 서비스 선택 이유

이러한 조건을 위해서는 주로 많이 사용하는 것이 카페24의 호스팅 서비스였다. 호스팅 서비스가 여러가지가 있었고, 여기서 우리가 사용할 next 프로젝트는 단순 웹 호스팅으로는 배포할 수 없었다. 그렇다고 서버 호스팅을 하려면 추가적인 작업이 필요하고 (docker 등 인프라 구성) 언어별 호스팅이 가격적으로 메리트가 있어보여서 선택하게 되었다. (지금와서 보니 어차피 크게 차이는 없고 제약만 더 심한거 같다.)

카페24에서 제공하는 매뉴얼이 있다. ssh키 생성 - 앱 생성 - 키 할당 - local에서 git 연결은 매뉴얼만 보아도 가능하다. 이번 포스팅에서는 그 이후에 트러블 슈팅을 하면서 기존 프로젝트를 배포하는데 필요했던 부분들을 적고자 한다.


과정

기존에 프로젝트가 없이 시작하는 과정은 다른 블로그에도 많았다. 그래서 기존 프로젝트가 있는 경우를 기준으로 한다.

1. 환경 / 의존성 모듈 버전 설정

node.js 호스팅은 최대 node 14 버전만 지원한다.
node version 변경은 nvm을 이용하면 간단하게 왔다갔다할 수 있었다. (방법)
기존에 프로젝트는 18버전 기준으로 개발하여서 node 버전은 물론, react, next 버전을 모두 변경해야 했다. 버전 변경에 따른 코드 수정도 필요했다.

// package.json 일부
"dependencies": {
    "@emotion/react": "^11.11.1",
    "@emotion/styled": "^11.11.0",
    "@mui/material": "^5.14.20",
    "@mui/x-date-pickers": "^5.0.20",
    "@tanstack/react-query": "^4.36.1",
    "@types/pg": "^8.11.10",
    "aws-sdk": "^2.1531.0",
    "axios": "^1.6.2",
    "dayjs": "^1.11.10",
    "jsonwebtoken": "^8.5.1",
    "multer": "^1.4.5-lts.1",
    "multer-s3": "^2.10.0",
    "next": "12.2.5",
    "next-swagger-doc": "^0.3.6",
    "pg": "^8.13.1",
    "react": "17.0.2",
    "react-color": "^2.19.3",
    "react-daum-postcode": "^3.1.3",
    "react-dom": "17.0.2",
    "react-icons": "^4.12.0",
    "react-slick": "^0.29.0",
    "recharts": "^2.9.0",
    "sharp": "^0.32.6",
    "styled-components": "^5.3.11",
    "swagger-ui-react": "^4.19.1",
    "winston": "^3.11.0"
  },
  "devDependencies": {
    "@types/node": "^14",
    "@types/react": "17.0.38",
    "@types/react-color": "^3.0.6",
    "@types/react-dom": "17.0.11",
    "@types/react-slick": "^0.23.10",
    "@types/styled-components": "^5.1.34",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "bcrypt": "^5.1.1",
    "eslint": "^7.32.0",
    "eslint-config-next": "12.3.4",
    "formidable": "^2.1.2",
    "slick-carousel": "^1.8.1",
    "typescript": "^4.9.5"
  },
  "engines": {
    "node": "14.x"
  }

2. web.js 생성

기존에 파일 구성은 다음과 같았고 node.js 호스팅에서는 앱 기본 실행 파일명은 web.js 이다. 그래서 root에 web.js 파일을 만들어줘야 한다.

.
├── README.md
├── logs
├── next-env.d.ts
├── next.config.js
├── node_modules
├── package-lock.json
├── package.json
├── pnpm-lock.yaml
├── public
├── src
│   ├── pages
│   │   ├── _app.tsx
│   │   └── _document.tsx
├── tsconfig.json
└── yarn.lock

이 호스팅으로 배포를 하기위해 프로젝트의 구조를 바꾸고 싶지는 않아서 web.js만 추가하였다.
로그 파일의 경우 원래 log 디렉토리를 따로 사용했으나 쓰기 권한이 없길래 root에 바로 로그 파일을 쓰도록 하였다. 나중에 따로 pull 받아서 로그를 확인해보지는 않았다.

const { createServer } = require('http');
const { parse } = require('url');
const next = require('next');
const fs = require('fs');
const path = require('path');

const dev = process.env.NODE_ENV !== 'operation';
// const dev = true;
const app = next({ 
  dev,
  dir: __dirname  // 현재 디렉토리(루트)를 기준으로 설정
 });
 const handle = app.getRequestHandler();


 // 에러 로그 파일 저장
function logError(error) {
  const timestamp = new Date().toISOString();
  const errorLog = `[${timestamp}] ${error.stack || error}\n`;
  fs.appendFileSync(path.join(__dirname, 'error.log'), errorLog);
}

// 프로세스 종료 시 에러 처리
process.on('uncaughtException', (error) => {
  logError(error);
  console.error('Uncaught Exception:', error);
  process.exit(1);
});

process.on('unhandledRejection', (error) => {
  logError(error);
  console.error('Unhandled Rejection:', error);
  process.exit(1);
});

app.prepare().then(() => {
  createServer((req, res) => {
    const parsedUrl = parse(req.url, true);
    handle(req, res, parsedUrl);
  }).listen(process.env.PORT || 3000, (err) => {
    if (err) throw err;
    console.log('> Ready on port ' + (process.env.PORT || 3000));
  });
});

3. package.json 수정

  "scripts": {
    "dev": "node web.js",
    "build": "next build",
    "start": "NODE_ENV=operation node ./web.js"
  },

올리면서 install이 되지 않는 것 같아서 "prestart": "yarn install" 같은 script도 추가했었으나, 필요 없었다.
로컬에서 테스트를 위해 dev도 수정하였다.

4. git 올릴 때 주의 점

일반적으로는 .env 파일은 git에 올리지 않으므로 gitignore에 포함되어 있는 경우가 많다. 하지만 배포를 위해서는 .env 파일도 함께 올려줘야하므로 gitignore에서 제외시키고, .env 파일도 함께 push 한다. 기존에 github 등에 코드를 올리고 있다면 같이 올라가지 않도록 주의해야 한다.


트러블 슈팅

✅ 용량 부족

internal/modules/cjs/loader.js:892
throw err;^Error: Cannot find module 'next'Require stack:- /home/hosting_users/****/apps/****/web.js

위와 같은 에러가 발생했다. 처음에는 install을 하지 않아서 발생하는 문제인 줄 알았다. 여기서부터 문제였던 것이 remote git의 master 브랜치로 push하고 나면 실제로 서버에서는 어떤 명령어를 실행하는지를 알 수가 없었다. 그래서 이를 알기위해 몇 번이나 문의를 했지만 git으로 프로젝트를 올리는 방법만을 기계적인 답만 돌아왔다.. 그래서 결국 새로 프로젝트를 파서 하나씩 올려보면서 문제점을 찾아나갔다.
새 프로젝트는 git으로 올리면 배포가 문제없이 되었고, 실제 프로젝트에도 동일하게 적용하니 똑같은 에러가 났다. 그래서 용량을 의심하게 되었고 모니터링을 확인하니 용량이 가득 찬 것을 알게되었다.
그리고 용량 사용량이 실제 프로젝트보다도 훨씬 많았고 최대 2기가였으나 제일 기본적인 테스트 프로젝트를 올려도 1.4기가나 차지하였다. 심지어 앱들을 다 지워도 1.2기가는 계속 먹고 있었고, 이 부분은 결국 또 1:1 문의를 통해 삭제가 가능했다. (어떤 파일이 공간을 차지했는지도 직접 알 수 없고, 직접 삭제도 불가능하다)

단점

  • 로그 확인이 어렵다 (에러 나거나 용량차면 로그를 볼 수 없다)
  • 메모리 확인, 안 쓰는 파일 정리 등을 하려면 1:1 문의로만 가능하다.
  • git으로 업로드 후 서버 종료 / 시작을 따로 해줘야 한다.

프로젝트를 정상적으로 올리고 보니 메모리 부족으로 계속 다운되어서 결국 가상 서버로 바꿨다..🥹

참고:
https://noworkgoodlife.tistory.com/30
https://jaebins.tistory.com/12

profile
훈이야 화이팅

0개의 댓글