AWS
EC2
- 쉽게 생각해서 컴퓨터를 한 대 빌리고, 우리의 프로젝트를
npm run start
등으로 시작하듯 프로젝트를 열어놓는 것이다.
23.09.13 추가
기본 설치
- 인스턴스를 생성하였으면 연결해주고
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
명령어를 입력하여 우리가 사용한nvm
을 저장소에 받아준다.curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -E -
명령어를 입력하여 설치하는 방법도 있는데 어떠한 에러가 뜰 것이다.- 현재는 권장하지 않는 방법이라
nvm
으로 설치해주어야 한다.
. ~/.nvm/nvm.sh
명령어를 입력하여 nvm을 활성화 시킨다.nvm install --lts
으로 Node.js를 설치한다.nvm install 16, nvm install 18.17
등 원하는 버전으로 설치도 가능하다.
node -v, npm -v
로 설치된 버전을 확인할 수 있다.- 이제 본인의 레포지토리에 있는 프로젝트를
git clone
을 사용하여 가져온다. - 백엔드 코드와 프론트 엔드 코드를 2개의 인스턴스로 나눠 열어도 되지만 비용 + @의 단점으로 하나의 터미널을 사용하는 것이 좋다.
- 하나의 터미널을 사용하기 위해서 설치하는 것이
pm2
이다. sudo npm install pm2 -g
로 pm2를 글로벌로 설치하고,pm2 start, pm2 list, pm2 monit
등의 명령어를 이용해서 여러 개의 터미널을 백그라운드에서 사용할 수 있다.
- 하나의 터미널을 사용하기 위해서 설치하는 것이
23.09.14 추가
mongoDB build 시 발생할 수 있는
node 버전을 선택하여 설치했던 건 EC2에서
npm
명령어를 사용하여 프로젝트를 시작하려고 할 때 에러가 발생해서 버전을 변경하려 했다.- node 버전 문제 때문에 에러가 뜨는 경우가 있다고 한다.
- Nullish Coalescing Operator로 ECMAScript 2020부터 도입된 기능으로 node 버전이
12.
인 환경에서 실행했기 때문에18.
버전으로 업그레이드 한 후 실행했다. - 그럼에도 똑같은 에러가 발생했다.
1 2 3 4 5 6 7 8 9
> backend@1.0.0 start > sudo node src/app.js /home/ubuntu/why-chat/backend/node_modules/mongodb/lib/operations/add_user.js:16 this.options = options ?? {}; ^ SyntaxError: Unexpected token '?'
- module 자체를 손 대는 건 좋지 않은 방식임을 알고 있음에도 node 버전 업그레이드 조차도 해결되지 않아 코드 자체를 변경해봤다.
1
this.options = options || {};
- 그럼에도 비슷한 에러가 발생했는데 이렇게 직접 모듈을 손 보다가는 끝이 없을 것 같아 좀 더 근본적인 해결 방법을 찾기로 했다.
1 2 3 4 5 6 7 8
> backend@1.0.0 start > sudo node src/app.js /home/ubuntu/why-chat/backend/node_modules/mongodb/lib/error.js:627 this.code = reason.error?.code; ^ SyntaxError: Unexpected token '.'
- 버전 업그레이드가 실패했으니 그 다음 방법은
babel
을 사용하는 것이다. - 바벨은 쉽게 말해 최신 문법인 ES6로 작성된 코드를 하위버전의 코드로 변환해주는 데, 최신 브라우저에서 동작하지 않는 코드들이 동작될 수 있도록 호환성을 높여주는 것을 말한다.
- 모듈에 대한 문법을 이해하지 못 했기 떄문에 발생하는 문제였기 때문에 node버전을 수정했지만 실패, 바벨을 사용해본다.
npm install @babel/core @babel/preset-env @babel/node --save-dev
로 바벨과 필요한 플러그인들을 설치한다..babelrc
파일을 생성하여 프리셋을 설정한다.1 2 3 4
// 프리셋을 사용하여 현재 환경에서 지원되는 자바스크립트 기능만 트렌스파일 { "presets": ["@babel/preset-env"] }
그럼에도 똑같은 에러가 발생했다.
- 바벨은 프로젝트의 소스 코드만 트랜스파일하기 때문에 외부 라이브러리인 MongoDB 코드는 변환되지 않을 수 있다고 한다.
- 바벨을 사용해서 모듈 별 트랜스파일을 진행할 수 있도록 오류가 발생한
mongodb/lib
로 이동한다. npx babel src --out-dir lib
를 입력하여src
경로의 코드를lib
폴더로 트랜스파일한다.그리고 다시 프로젝트를 시작해보았지만 에러 발생
1 2 3 4 5 6 7
chat/backend/node_modules/mongoose/node_modules/mongodb$ npx babel src --out-dir lib Need to install the following packages: babel@6.23.0 Ok to proceed? (y) y npm WARN deprecated babel@6.23.0: In 6.x, the babel package has been deprecated in favor of babel-cli. Check https://opencollective.com/babel to support the Babel maintainers You have mistakenly installed the `babel` package, which is a no-op in Babel 6. Babels CLI commands have been moved from the babel package to the babel-cli package.
- 에러 내용을 보면
babel
이 아닌bable-cli
를 사용해야 된다고 나와있다. npm uninstall -g babel
을 사용해서 바벨을 삭제 후npm install --save-dev babel-cli
로 패키지를 설치한다.- 위의 8-9번 과정을 다시 실행
- 다시 에러 발생
1
2
3
4
5
6
7
8
> backend@1.0.0 start
> npx babel-node src/app.js
node:events:492
throw er; // Unhandled 'error' event
^
Error: listen EACCES: permission denied 0.0.0.0:80
- 80번 포트에서의 접근 권한 부족으로 발생한 에러였는데, 기본 포트인 80번이 아닌 8080이나 3000번 등으로 접근해보라는 해결책이 있었다.
- 왜 인지는 모르겠지만 정상적으로 실행이 됐다.
- 프론트 코드 또한 build와 start로 실행 완료.
23.09.15
기본 패키지 설치 EC2 확인 방법
- pm2가 정상적으로 실행 중인데 ip 접근이 되지 않아 새로운 인스턴스로 실험을 해보기로 했다.
- 우선 기본적인 세팅 방법으로
sudo apt update
로 패키지의 업데이트가 가능한 목록을 업데이트 해준다. - 13일 기준 세팅 방법으로 npm과 node.js 설치를 한다.
npm init -y
를 통해 기본적인 패키지 세팅을 완료한다.touch index.js
로 기본적으로 접속해줄 파일을 생성한다.- express를 설치한다.
vim index.js
로 서버 코드에서 사용할 express의 기본 코드를 작성한다.express 기본 코드
1 2 3 4 5 6 7 8
const express = require("express"); const app = express(); app.get("/", function (req, res) { res.send("Hello World"); }); app.listen(3000);
i
를 눌러 INSERT 모드에서 코드를 붙여넣기 해주고ESC => : => wq!
순으로 작성 후 저장 종료를 한다.cat index.js
로 작성된 코드 확인.- 자꾸 왜 안 들어가지나 했더니, 개방 주소에 접속 포트 번호를 작성하지 않았다.
- xx.xxx.xxx.xxx:8080 으로 접속 가능 확인
- 근데 왜 기본 프로젝트는 안 되지…
23.09.16
배포 시 메모리 이슈로 인한 EC2 멈춤 현상
- 어이없는 실수를 한 김에 추가
- 우선 pm2 list에서 자꾸 에러가 떴기에 local 환경에서 build와 start과정을 거쳐서 수정을 마쳤다.
- 코드를 올린 후 다시 EC2에서 사용을 했는데 어처구니 없는 짓을 반복하고 있었다.
- 퍼블릭 IP로 접근을 했을 때
Cannot /GET
이라는 메시지만 나와있었는데, 서버는 정상적으로 실행되고 있었고 도저히 원인을 찾을 수 없었다. - express를 사용해서인가 무언가 설정을 잘못했나 이와 관련된 에러들을 몇 시간동안 찾아봤지만 해결책을 찾을 수 없었다.
- 결론만 말하자면 서버는 정상적으로 실행되고 있는 게 맞았는데, URL이 잘못돼있었다.
- 서버는 8080포트를 사용하고 있고 로컬에서는 프론트와 서버를 따로 들어갈 일이 없기 떄문에 기본 주소인
/
에 대한 어떠한 설정도 하지 않았고, 그렇기에 어떠한 반환값도 받을 수 없었다.- 그래서 서버가 제대로 실행되고 있다고 생각을 못함…
- 프론트에서 각 페이지마다
api
요청을 자동적으로 해주고 있기 때문에 3000번 포트로 접근을 했어야 했는데 퍼블릭 IP 뒤에 서버 포트로 접근을 하려하니 아무런 반환값이 없을 수 밖에… - 어찌됐든 해결…이런 실수는 다시는 반복하지 않아야지…그리고 환경변수로 개발환경과 배포환경에서의
api
주소만 바꿔주면 되겠다.
- 프리티어로 설정 시 메모리가 부족하여
npm run build
시 인스턴스가 뻗는 경우가 자주 발생한다고 한다.
1
2
3
sudo dd if=/dev/zero of=/mnt/swapfile bs=1M count=2048
sudo mkswap /mnt/swapfile
sudo swapon /mnt/swapfile
- 위 명령어들을 사용하여 메모리의 부족한 부분을 디스크의 일부를 사용하여 대신 사용할 수 있게 해주는 기능이다.
- 메모리에 비해 디스크 속도가 느리기 때문에 스왑 사용 시 속도가 느려진다는 단점이 있다.
- 가상 메모리를 사용하면 퍼포먼스의 문제가 발생하기 떄문에 임시 방편으로 사용하는 것이 좋다.
- 아래는 스왑 메모리 해제 명령어이다.
1
2
sudo swapoff -v /mnt/swapfile
sudo rm /mnt/swapfile
23.09.17
이미 실행 중인 포트 종료
- 프로젝트 실행 시 분명 터미널을 종료했는데도 포트가 실행 중인 에러가 발생할 때가 있다.
- 이 때 포트 번호를 바꿔 사용하거나 이미 실행 중인 포트를 죽이는 방법이 있다.
- 아래와 같이 실행 중인 포트 번호를 입력하여 포트의 ID를 알아내고, 포트 ID를
kill
명령어를 사용하여 종료시킬 수 있다.
1
2
3
4
5
6
7
lsof -i :포트번호
lsof -i :8000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 1234 shaking 15u IPv4 0x1f23462a48d69d65 0t0 TCP localhost:cslistener (LISTEN)
kill -9 1234
배포 시 에러
- EC2로 배포할 시 자꾸 한 사람이 사이트에 접속하면 다음 사람이 접속을 시도했을 때 막히는 문제가 발생했다.
- 간혹 Next.js는 SSR 방식이기 때문에 사용자가 접속 했을 때 html, js 등 다시 사용자에게 보내줘야 하기 떄문에 서버 부하가 올 수 있다고 한다.
- 하지만 트래픽을 많이 잡아먹는 것도 아니었는데 근본적인 원인이 해결이 안 됐다.
- 하여 Vercel로 배포해보기로 했고, frontend에 관한 디렉토리를 선택하여 배포를 시도했다.
- build 시 에러가 뜨지 않았으며, 언어 선택과 루트 폴더를 정확하게 설정을 했는데도 404 not found라는 에러가 발생했다.
- 콘솔이나 network부분에 어떠한 에러 메시지도 주지 않았다.
- 해외 커뮤니티에 나와있는 질의들도 많았는데 이렇다 할 해결방법이 없이 계속 시도만 하다가 흐지부지된 것처럼 보였다.
- nelify로도 시도해보았으나 같은 에러가 발생…마지막으로 frontend에 관한 파일들을 새로운 레포지토리에 옮겨주었고 성공…
- 어떠한 코드 변경도 없이 파일만 옮겨서 배포를 한 것뿐인데 이상없이 동작했다.
- 이를 보면 루트 폴더 설정을 잘못했기에 발생한 에러가 아닐까 추측만 될 뿐 확신은 못 하겠다.
23.09.18
- 인스턴스의 IP는 계속 변하는 동적 IP 성격을 지녔기 떄문에 이를 고정시켜줘야 한다.
EC2 => 네트워크 및 보안 => 탄력적 IP
에서 탄력적 IP 생성 후 이를 연결할 인스턴스를 선택한다.- 그럼 탄력적 IP가 생성되는데, 이를 선택 후 우측 상단의
작업
에서 탄력적 IP 연결을 선택하여 사용하고자 하는 인스턴스를 선택 후, 인스턴스의 퍼블릭 IP를 입력해준다. - 마찬가지로 탄력적 IP를 삭제하고 싶으면 작업에서 릴리스를 선택하면 삭제된다.
- 탄력적 IP는 연결된 인스턴스 없이 유지할 경우 비용이 발생하는데, 인스턴스를 연결하면 비용이 발생하지 않으니 유의하자.