git branch로 현재 브랜치들 확인 후, git branch dev<or your branch name>으로 새 브랜치 생성
git remote로 확인 가능. git push <git remote 결과> <현재 브랜치 명>

Express 폴더) .github라는 이름의 폴더 생성 (+ 해당 강의에서 사용되는 UI extention은 Material Icon Theme).github 안에 workflows 폴더도 생성workflows 폴더 안에 test.yml 파일 생성 (+ GitHub Actions extention도 설치)name: test
on: pull_request
jobs:
test:
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Node.js setup
uses: actions/setup-node@v3
with:
node-version: "22"
- name: Install npm packages
run: npm ci
- name: Install and run redis-server
run:
sudo apt-get update
sudo apt-get install -y redis-server
redis-server --daemonize yes --requirepass test_env --port 6380
- name: Run test
run: npm run test
- name: Build test
run: npm run build
error: failed to push some refs to 'https://github.com/<username>/<reponame>.git' 오류 이슈 발생.github/workflows 디렉터리에 포함된 파일의 보안성을 보장하기 위해 추가적인 권한이 필요한데, 사용하는 인증 방법(OAuth 앱 또는 퍼스널 액세스 토큰)에 이 권한이 없다면 push가 거부된다고 함해결방법

자격 증명 관리자를 검색한 후 github 관련 자격들을 모두 삭제

Install and run redis-server 단계에서 아래와 같은 오류 발생
name: test
on: pull_request
jobs:
test:
runs-on: ubuntu-22.04
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Node.js setup
uses: actions/setup-node@v3
with:
node-version: "22"
- name: Install npm packages
run: npm ci
- name: Install and configure redis-server
run: |
sudo apt-get update
sudo apt-get install -y redis-server
# Configure Redis to run as a daemon
sudo sed -i 's/^# daemonize no/daemonize yes/' /etc/redis/redis.conf
# Set Redis password
echo "requirepass test_env" | sudo tee -a /etc/redis/redis.conf
# Set Redis port
sudo sed -i 's/^port 6379/port 6380/' /etc/redis/redis.conf
# Restart Redis to apply configurations
sudo systemctl restart redis-server
# Verify Redis is running
redis-cli -p 6380 -a test_env ping
- name: Run test
run: npm run test
- name: Build test
run: npm run build
Run test 단계에서 멈춰있음→ 이유 : test 자체는 모두 성공적으로 완료함. 그러나 다음 단계로 넘어가지 않는 이유는 로컬에서 테스트코드를 수정할 때 프로세스가 종료되지 않고 계속 실행되도록 하기 위해 jest --watchAll 로 설정해둠. 이를 통해 코드를 수정하고 저장할 때마다 테스트가 다시 실행됨. 그러나 CI 환경에서는 테스트가 끝나면 해당 프로세스가 멈춰야 함.

package.json 수정: "scripts"에 "test:ci": "jest" 추가 후 로컬에서 npm run test:ci로 실행하고 멈추는 것 확인test.yml 수정: - name: Run test
run: npm run test:ci

ssh-keygen -t rsa -b 4096 -C "github_action" -f ~/.ssh/github_id_rsacd ~/.ssh 후 ls로 조회 후, cat ~/.ssh/github_id_rsa.pub로 생성된 SSH key 복사해두기
vim ~/.ssh/authorized_keys에 들어가서 엔터치고 새로운 키 붙여넣기ssh -i ~/.ssh/github_id_rsa ubuntu@43.201.5.12


ssh -i ~/.ssh/github_id_rsa ubuntu@<publicIP>
SSH_PRIVATE_KEY를 추가하기
cat ~/.ssh/github_id_rsa (뒤에 pub이 붙지 않는 것이 private key이다)를 조회해서 복사한 후 추가 (-----END OPENSSH PRIVATE KEY----- 등도 다같이 추가)SSH_USERNAME를 추가하기SSH_PUBLIC_IP를 추가하기ssh-keyscan <publicIP>로 로컬에서 구한 내용으로 SSH_KNOWN_HOSTS를 추가하기
deploy.yml이라는 파일명으로 deploy를 위한 github actions 테스트 생성name: deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Set up SSH
run:
mkdir -p ~/.ssh/
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name: Set up known hosts
run:
echo "${{ secrets.SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: SSH and deploy
run:
ssh ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_PUBLIC_IP }} "
cd express
git pull || exit 1
npm install || exit 1
npm run build || exit 1
sudo pkill node || exit 1
sudo npm run start & npx wait-on http://localhost
exit
"

Require status checks to pass before merging: 테스트 미통과 merge 방지
Require a pull request before merging: 강제 push 방지
artillery 라는 도구 사용 예정sudo 명령어를 앞에 붙인 후 웹사이트에 안내되어있는 설치 명령어대로 설치하기 (단, window에서는 powershell을 관리자 권한으로 실행하는 것으로 충분히 설치 가능) load-test.yml 테스트파일 생성config: 어떤 url을 대상으로 테스트할 것인지(target), 몇 명의 유저들이 몇번의 부하를 주게 할 건지에 대한 내용(phases)scenario: 어떤 종류의 요청을 날릴 건지 (GET, POST, ...)config:
target: http://localhost:4000
phases:
- duration: 5 # 5초동안 지속
arrivalRate: 1000 # 1초당 1000개의 가상유저가 아래의 시나리오대로 요청을 보내는 것을 가정
scenarios:
- flow:
- get:
url: "/messages" # tab 키 안 누르면 오류남 ,,
npm run dev로 로컬에서 서버를 돌려줌 (우선은 로컬 URL로 테스트중이므로!)artillery run load-test.yml으로 테스트 실행
app.ts에 코드를 약간 추가해서 더 복잡하게 만들어보자 // recursion: 부하를 늘리기 위한 재귀함수(피보나치) 및 API endpoint 추가
function fibo (n:number):number{
if (n <= 1) return n;
return fibo(n-1) + fibo(n-2);
}
app.get("/fibo/:n", (req, res) => {
const n = parseInt(req.params.n, 10); // 10진수로 표현
const result = fibo(n); // 재귀함수 적용
res.send(`Recursion function Fibonacci(${n}) => ${result}`); // 요청 보내기
});


sudo npm run start를 해줘야 함!! n = 10
n = 35: 아예 timeout된 요청도 있고, 수행에 성공한 요청들도 비교적 긴 시간이 소요되며 완료된 것을 확인할 수 있음
node는 single thread runner라서 여러개의 CPU가 있더라도 이를 활용하지 못함.. 그래서 다른 서버의 경우도 그렇지만(서버가 다운되고 회복되는 시간에 서버다운시간이 발생하는 것을 방지하기 위해) 특히나 node의 경우에는 CPU의 개수만큼 여러개의 포트에서 서버를 여러개 띄워주는게 중요함PM2 : 원래는 개발자가 여러개의 PORT를 관리하며 각각 child process를 돌려줘야 하지만, PM2의 경우는 개발자가 기본 포트 (80)에만 실행하면 나머지는 proxy로 자체적으로 처리해줌. pm2 start build/index.js -i 3 --time: i 옵션은 몇개의 프로세스를 띄울 지 정하는 옵션임
pm2 list로 현재 실행중인 프로세스 확인 가능pm2 kill로 현재 실행중인 프로세스 중지 가능pm2 reload all로 수행 가능pm2 logs --watch로 실시간 로그 확인 가능: 코드 수정을 실시간으로 반영하므로, pm2 logs --watch 실행 후 app.ts 파일을 수정해보면 확인 가능ssh -i ~/.ssh/github_id_rsa ubuntu@<publicIP> 입력 후 SSH 터미널로 접속sudo npm i -g pm2sudo pkill node: node processor 죽이기cd express 후, sudo pm2 start build/index.js -i max --time 실행 (여기까지는 한번만 실행하면 되는 내용이므로 .yml 파일에 넣기에는 적절하지 않음)-i 옵션의 숫자는 상수에서 max로 수정해주면 PM2가 자체적으로 해당 서버의 CPU 개수에 맞춰서 프로세스 개수를 설정해서 띄워줌. 로컬에서 실행하면 각 로컬 기기의 코어 수만큼의 프로세스가 띄워짐 (내 로컬은 8코어이므로 8개의 프로세스가 실행됨)
deploy.yml 파일 다음과 같이 수정: sudo pkill node || exit 1, sudo npm run start & npx wait-on http://localhost를 삭제하고 sudo pm2 reload로 대체하기name: deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Set up SSH
run:
mkdir -p ~/.ssh/
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name: Set up known hosts
run:
echo "${{ secrets.SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
- name: SSH and deploy
run:
ssh ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_PUBLIC_IP }} "
cd express
git pull || exit 1
npm install || exit 1
npm run build || exit 1
sudo pm2 reload all
exit
"
artillery run load-test.yml로 부하를 점진적으로 주면서 sudo pm2 list --watch로 관찰하기

create new instance를 선택해서 새로운 서버 생성!




express-2 의 SSH 터미널에 들어가서 설정할 부분들 설정해주기

cd express, redis-server --daemonize yes, sudo pm2 start build/index.js -i max --time 를 실행하고 체크하면 pass로 뜸!
sudo sysctl vm.overcommit_memory=1도 실행해줌
Create instance 시 확인해보면 Region 별로 Zone이 여러개 있음. 이 때, Region은 우리가 위치한 지역을 말하고, Zone은 해당 지역 내에서 서버가 분리된 기준을 뜻함. 즉, 만약 Seoul Region에 Zone이 4개가 있다면 분리된 데이터 센터가 4개 있다고 이해해도 무방함. 이 Zone들은 분리되어있으므로 자연재해, 전쟁 등의 만일의 사태에도 모든 센터가 동시 다운되지 않도록 설정됨. 따라서, 수평 확장으로 VM 서버를 여러개 설정했다면 이 서버들의 Zone을 모두 다르게 설정해주는게 더 안정적임!
POST로 데이터를 저장한 후 조회하려고 하는데 다시 빈 배열이 돌아옴

GET 요청을 3번 정도 보내고 나서야 겨우 앞서 보낸 내용이 들어가있음 ..
redis, are u ok..?, hello 를 보냄!

GET, POST 요청이 각각 별도의 VM 서버로 Load Balancer에 의해 routing 된 것이 문제임. POST 요청에서 redis, hello 가 하나의 서버로 들어가고 are u ok..?가 또 하나의 서버로 들어가서 각각 저장된 후 GET 요청을 보낼 때마다 두 서버 중 하나씩을 가져오니까 묶음으로 해서 계속 위의 두 조합의 화면만이 나오는 것임. 결국 Redis 서버가 여러개라서 발생하는 문제이다. 


redis 동일하게 다시 설치 후 SET foo bar, GET foo 등으로 설치된 거 체크하기curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
sudo chmod 644 /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis
sudo systemctl status redis-server로 들어가고, 다시 그 안의 redis-server.service라는 파일에 접근하기 위해 cat /lib/systemd/system/redis-server.service로 들어가서 확인해본 후 그 안에 기재되어있는 redis.conf 파일을 또 확인하기 위해 sudo cat /etc/redis/redis.conf로 들어가보면 정말 많은 설정들이 있음. 우선 여기서 우리는 인프라 엔지니어가 되려는게 아니므로 좀 더 간단한 버전으로 해서 해결해보자. sudo systemctl stop redis-server로 강제종료하기sudo systemctl status redis-server로 조회해보면 inactive(dead)라고 나옴redis-server --daemonize yes --requirepass prod1234 로 설정해서 임시로 비밀번호까지 걸어서 켜주자sudo sysctl vm.overcommit_memory=1도 실행 후 다시 실행 redis-server --daemonize yes --requirepass prod1234set foo bar, get foo 등을 체크하기 전에 auth prod1234로 비밀번호를 입력해줘야 함redis-cli -h <새instance의publicIP>auth prod1234로 비밀번호를 입력하기get foo로 연결 확인redis-cli -h <새instance의privateIP>sudo systemctl stop redis-servercd express로 들어가서 vim .env로 env 파일 수정 후 cat .env로 수정한 내용이 반영되었는지 확인.env 파일의 코드: PORT=80
REDIS_URL: redis://localhost:6379
.env 파일의 코드: PORT=80
REDIS_URL: redis://:prod1234@<새로만든redis-1서버의PrivateIP>:6379
sudo pm2 reload allhttps://backend-ec2.com/messages URL로 postman에서 요청 보내가면서 테스트해보기Node.js, Redis 등을 모든 VM에 각각 설치해줘야 함vim이라는 번거로운 에디터를 사용해야 함instance 전부 삭제, snapshot도 삭제networking 전부 삭제domain은 ECS 실습 후 삭제