ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [TIL] 스파르타) Ch.3 개인 과제 리뷰, Node 강의 수강
    TIL-sparta 2024. 5. 17. 19:29

     > 과제 피드백 이후 버그 수정 및 강의 수강으로 새롭게 알게된 PM2 패키지를 설치하여 서버에 적용해보았다. 강사님 피드백 내용에서 Error 클래스에 대한 언급이 있었는데, 여러개의 클래스를 생성하는 대신 하나의 클래스에서 관리하는 방법을 강구해보라고 하셨다. DI를 적용하라는 말씀이신 것 같은데 당장은 어떤식으로 구현해야 깔끔하게 만들 수 있을지 구체적인 형태가 떠오르지 않아서 이 부분은 차근차근 고민해보도록 해야겠다.

     

    학습 키워드: validation, pm2, sudo, npm, yarn

     

    1. Validation / ReferenceError

    1) What is it?:

     이번 과제에서 가장 부족했던 부분은 validation이었다고 생각하는데, 걸러주지 못 한 케이스들과 Joi schema 설정 미숙, key 값의 이름을 잘 못 적은 등의 실수가 많이 있었다. 이 중에서 서버의 crash를 유발했던 마지막 케이스에 대해 정리해봤다.

     

    2) Problem (ReferenceError):

    // items-validator.middleware.js
    
    const itemValidatorJoi = {
      
      ...
      
      itemStatValidation: async function (req, res, next) {
        const validation = itemStatSchema.validate(req.body);
    
        if (validation.error) {
          console.log("itemStatValidation: ", validation.error.message);
          let msg = `Invalid item_stat: ${item_stat}`; // item_stat -> req.body.item_stat
          return res.status(400).json({ errorMessage: msg });
        }
    
        next();
      },
    }

      이미지는 bash에 출력되었던 오류 메세지의 일부다. /api/items/:item_code URI로 put method 요청을 처리할 때 body에서 item_stat 키 이름 item_stat.abc 같은 형태로 전달하면서 ReferenceError가 발생했다.

     

     결론부터 말하면 단순히 item_stat이 정의되어있지 않은 기초적인 reference 문제였다. 코드 블럭에서 msg가 정의된 위치를 보면 template literal로 끝 부분에 item_stat을 사용한다. 여기서 item_stat은 req.body.item_stat에 정의되어있는데 req.body 없이 호출하는 바람에 not defined 에러가 출력됐는데, Joi schema의 validate method안에서 에러가 처리되기 때문에 이 부분에서는 에러가 발생할 일이 없을거라고 생각하여 try catch문을 빼주었는데 작은 실수로 인해 에러 케이스가 생겨서 서버가 crash된 것이다.

     

     제출 당일에 Joi의 validate를 validateAsync로 바꿀 수 있는지 알아보는 과정에서 try catch의 반복적인 사용을 줄이기 위해 validation 미들웨어들을 try catch wrapper 같은 형태로 감싸는 방법을 고려하다가 보류하고 넘어갔는데, 추후에 있을 비슷한 사태에 대비하여 해당 기능을 추가할 방법을 미리 생각해두는 것이 좋겠다.

     


    2) Reason & Solution:

     기존에는 item_stat 값을 따로 뽑아두고 썼다가 Joi를 사용하도록 바꾸면서 스크립트 수정을 거쳤는데, req.body를 통째로 validate에 넣어주도록 변경하는 과정 중에 다른 곳에선 다 해놓고 item stat validation method에서만 쏙 빼먹었다. 테스트를 다 했다고 생각했는데 착각을 했었나보다. Insomnia(테스팅용 앱)에 에러 케이스를 모두 추가해주지 않아서 생긴 문제라고 생각한다. 주석에 적힌대로 req.body.item_stat으로 변경하여 해결했다.

     

    2. Server crash / PM2 package

    1) What is it?:

     강사님께서 과제 피드백을 위해 테스트를 하시던 도중에 앞선 ReferenceError 때문에 서버가 종료되었었다. 문제는 이렇게 되면 내가 직접 서버를 다시 켜지 않으면 안되기 때문에 잠시 호출이 있었다. 에러 핸들링을 다 해줬다고 생각했지만 실제로 서버가 crash되는 케이스에서 자동으로 재시작을 해야한다는데 까지는 생각이 미치지 못했다.

     

     PM2는 production 단계에서 Node 프로세스가 오류 등의 이유로 종료되었을 때를 대비해 프로그램의 자동 재실행을 설정해줄 수 있는 NPM 패키지다. 이번에 과제를 진행할 때 뒷 부분에 있는 AWS EC2 서버와 배포에 관련된 강의를 스크립트 작성이 끝난 이후에 들으려고 했었는데, 막상 배포할 때가 되어서 잊어버리는 바람에 검색하면서 하나하나 알아보며 해결하느라 시간을 좀 썼다. 강의에서 다뤄진 내용을 기반으로 서버에서 부족했던 부분을 보완해봤다.

     

     

    2) How does it work?:

    # Linux의 관리자 계정으로 전환합니다.
    sudo -s
    
    # pm2 라이브러리를 global로 설치합니다.
    yarn global add pm2
    
    # pm2 로 app.js 파일을 실행합니다.
    pm2 start app.js

     위의 두 개 명령어를 실행하여 pm2 패키지를 global로 설치해주고, 프로젝트의 디렉토리로 이동하여 마지막 명령어를 실행해주면 되는 간단한 구조로 이루어져있다. 그런데 현재 서버의 구성으로 위의 두 줄을 실행했더니 sudo 모드에서 yarn 명령어가 인식되지 않는 문제가 있었다. 그래서 일반 모드에서 yarn global으로 pm2를 설치했더니 이번엔 pm2 명령어가 인식이 되지 않았다. 그래서 결국 npm i -g pm2를 사용하여 설치를 진행했더니 pm2가 정상적으로 동작했다.

     

     서버 재부팅을 해줘도 sudo에서 nvm npm yarn이 모두 동작하지 않았다. 짐작하기로는 처음에 nvm이나 npm을 설치할 때 관리자 권한인 sudo를 이용하지 않은 것이 원인일 듯 하다. 이 문제는 추후 발제되는 프로젝트에서 서버 설정을 해주면서 자세히 알아봐야겠다.

     

     추가 내용: PATH 설정이 되어있지 않아서 생기는 문제라고 한다. 자세한 내용은 영상 링크 참고하자.

     

     아무튼 PM2로 app.js를 실행하면 이후 killall nodefuser -k 등의 명령어를 입력해도 종료된 프로세스가 자동으로 재실행 되는 것을 볼 수 있다. PM2로 실행된 프로세스는 아래 적어둔 pm2 delete [id or name] 명령어로 중지할 수 있다. [id or name] 은 pm2 list를 입력하여 출력된 표에서 id와 name column을 통해 확인할 수 있다. 

    출력된 표 예시

     

    3) Why use it?:

     - 앞서 언급했듯이 실제 프로덕션 단계에서 예기지 않은 오류로 서버가 종료되었을 때 매 번 SSH를 통해 다시 실행 시켜주는 것은 번거롭고, 또한 유저 입장에서도 서버가 다운되어있는 시간이 길어지면 서비스 이용을 할 수 없으며 서비스 제공자의 입장에서도 그 만큼의 시간을 손해보는 등 여러모로 불편을 야기한다. 이러한 경우를 대비해 즉시 서비스를 재실행하도록 설정해두면 관리 및 유지/보수가 수월해진다. PM2 외에도 비슷한 기능을 해주는 forevernodemon이 있으므로 참고하자.


    4) Useful PM2 commands:

    # Show list of running pm2 services
    pm2 list
    
    # Restart a pm2 service
    pm2 restart [id or name from the list]
    # ex) pm2 restart app
    
    # End a running pm2 service
    pm2 delete [id or name]
    
    # Print logs for the running pm2 services 
    pm2 log
    
    # Print logs for the specific pm2 service
    pm2 log [id or name]
    
    # Prints specific number of most recent logs
    pm2 logs --lines [number]

     

     - 이 외에도 로그 백업이나 로드밸런싱 기능도 지원한다. 자세한 사항은 공식 문서를 참고하자.

     - pm2는 로그 백업을 서버의 로컬 파일에 생성해준다. 그런데 이렇게 하면 로그가 쌓일수록 서버의 용량이 불어나는 단점이 있다. 피드백 내용 중 log 내용을 DB에 저장한다는 내용이 있는데, 이렇게 로깅된 파일을 주기적으로 끊어서 로컬 파일을 삭제하면서 내용만 DB로 보내주고, node app이 실행되는 시점에도 똑같이 한 번 저장하여 crash 이후 자동 재부팅으로 로그가 저장되게 만들어 crash 시점의 로그를 볼 수 있도록 설계하는게 어떨까 하는 생각이 들었다.

     

     

    --

     

     

    REFERENCES:

     

     

    2.11 AWS 배포하기 | Notion

    <Goal> 1. AWS EC2를 대여하여 Node.js 서버를 배포할 수 있습니다. 2. AWS의 방화벽 역할을 담당하는 보안 그룹을 설정할 수 있습니다. 3. 배포한 Node.js 서버와 도메인을 연결할 수 있습니다.

    teamsparta.notion.site

     > 강의 노트, "AWS 배포하기"

     

    GitHub - donkim1212/ch3-item-simulator: Chapter3 개인 과제

    Chapter3 개인 과제. Contribute to donkim1212/ch3-item-simulator development by creating an account on GitHub.

    github.com

     > 프로젝트 Repo, 배포된 branch (master)

     

    PM2 - Quick Start

    Advanced process manager for production Node.js applications. Load balancer, logs facility, startup script, micro service management, at a glance.

    pm2.keymetrics.io

     > PM2 documentation

     

    yarn command not found after installing via npm

    As per the yarn installation for yarn v2, they want you to install using npm install -g yarn. So I ran sudo npm install -g yarn on Ubuntu 20.04. But after I do that, it says command not found. ❯ ...

    stackoverflow.com

     

    728x90
Designed by Tistory.