Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
node_modules/
**/node_modules/

files/**
dist/**
coverage/**

REST API test/**
.env
.env.test

README.md
.gitignore
.dockerignore
.github/**
Binary file added .github/sprint-mission-11_git-action-history.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 76 additions & 0 deletions .github/workflows/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# 자동화 작업 이름
name : Panda Market CI/CD Test

# 작업 시점
on:
push : # 브랜치에 코드가 푸시될 때
branches : # 1차 : "김지선" 브랜치 / 2차(최종) : "main" 브랜치 설정
- 김지선-sprint11 # action test용
- 김지선
- main
pull_request : # 브랜치에 코드가 머지될 때
branches :
- 김지선-sprint11 # action test용
- 김지선
- main
Comment on lines +11 to +15
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위처럼 작성하면 PR이 생성될때 실행이 되는걸로 알고있었는데 아니였나보군요? 😀

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 PR로 생각 했는데, PR을 확인 한 뒤 기존 브랜치에 머지 할 때 실행되는 거라고 하네요~ 😉


# 작업 내용
jobs:

test:
# run 환경
runs-on: ubuntu-latest

# DB 환경
services:
postgres:
image: postgres:15
env:
POSTGRES_USER: ${{ secrets.TEST_DB_USER || 'postgres' }}
POSTGRES_PASSWORD: ${{ secrets.TEST_DB_PASSWORD || 'passwordnd6!' }}
POSTGRES_DB: ${{ secrets.TEST_DB_NAME || 'panda_market' }}
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

# 공통 환경변수
env:
# 테스트용 DB : 정보는 git secrets 저장
# PR 전송을 위해 테스트용 DB 연결 정보 추가
DATABASE_URL: ${{ secrets.TEST_DATABASE_URL || 'postgresql://postgres:passwordnd6!@localhost:5432/panda_market?schema=public' }}
NODE_ENV: test

# 테스트용 임시 키 설정
JWT_ACCESS_TOKEN_SECRET: "test_secret_key_12345"
JWT_REFRESH_TOKEN_SECRET: "test_secret_key_12345"

# 최종 작업에서는 git secret 사용, 현재는 규격만 맞춤
AWS_REGION: "ap-northeast-2"
AWS_ACCESS_KEY_ID: "dummy_key"
AWS_SECRET_ACCESS_KEY: "dummy_secret"
AWS_BUCKET_NAME: "test-bucket"

# test 작업 순서
steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 'lts/*'

- name: Install dependencies
run: npm install

- name: Type Check
run: npm run typecheck

- name: Run Tests
run: |
npx prisma migrate deploy
npm run test
60 changes: 60 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# 자동화 작업 이름
name : Deploy to EC2 panda-market

# 작업 시점
on:
push :
branches :
- 김지선 # 1차 : 상위 브랜치
- main # 2차 : 최종 브랜치
# pull_request :
# branches :
# - main

# 작업 내용
jobs:

deploy:
# run 환경
if: github.repository == 'KimDay366/6-sprint-mission' # 현재 개인 레포지토리에만 secret 설정이 되어있어 해당 조건을 추가하였습니다
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

우선 오류 원인을 파악하시고 if를 사용하여 대응하신게 너무 좋네요!
말씀해주신것처럼 코드잇 레포지토리의 특성상 secrets값이 팀원별로 다르기때문에 secrets값을 주입하기가 어렵긴하겠네요 🤔 이번엔 CI/CD를 해보는 경험이 목표이기 때문에 지금도 충분히 좋습니다.
현업에서는 환경별로 다른 값을 넣어주어야한다면 다음 방법을 사용하곤합니다!

secrets 이름으로 분기

각 환경에 맞는 식별자를 붙인 secrets값을 등록합니다.
(ex. KIM_SSH_HOST, KWAN_SSH_HOST)

GitHub Environments

Github 레포지토리 설정에서 Environment를 생성하고 환경별로 sercret 값을 설정하는 방법입니다.

Image

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호!!! 해당 방법도 같이 공부 해 보겠습니다~ 감사합니다 😁

runs-on: ubuntu-latest

# 환경변수
env:
# DB 정보
DATABASE_URL: ${{ secrets.DATABASE_URL }}
NODE_ENV: production

# JWT 설정
JWT_ACCESS_TOKEN_SECRET: ${{ secrets.JWT_ACCESS_TOKEN_SECRET }}
JWT_REFRESH_TOKEN_SECRET: ${{ secrets.JWT_REFRESH_TOKEN_SECRET }}

# AWS 설정
AWS_REGION: ${{ secrets.AWS_REGION }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_BUCKET_NAME: ${{ secrets.AWS_BUCKET_NAME }}

# EC2 설정
EC2_HOST: ${{ secrets.EC2_HOST }}
EC2_USER: ${{ secrets.EC2_USER }}
EC2_PRIVATE_KEY: ${{ secrets.EC2_PRIVATE_KEY }}
Comment on lines +23 to +41
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

secrets 값을 직접 주입하지않고 env섹션에서 한 번 정의해서 사용하셨네요!
저는 직접 주입을 하고있어 수정해야하는 부분이 있으면 하나하나 다 찾아야했었는데 이렇게 사용하면 유지보수 측면에서 좋겠네요 🤩 지선님 덕분에 배웠습니다. 감사합니다!



# deploy 작업 순서
steps:
- name: Deploy to EC2
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ env.EC2_HOST }}
username: ${{ env.EC2_USER }}
key: ${{ env.EC2_PRIVATE_KEY }}
port: 22
script: |
cd /home/ec2-user/6-sprint-mission
git pull origin ${{ github.ref_name }} # 최신 브랜치 자동 인식
npm install
npm run build
npm run prisma:deploy
pm2 reload panda-market || pm2 start dist/src/server.js --name "panda-market"
echo "Deployment successful!"
14 changes: 14 additions & 0 deletions .github/workflows/github_Action_workflow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
### Action push / pull_request 동작 방식

1. push : 브랜치에 코드가 푸시될 때
2. pull_request : 브랜치에 코드가 머지될 때


### 현재 구현 방식에서의 워크플로우

1. 로컬에서 git 저장 : git add . & git commit -m "..."
2. 원격 레포지토리로 로컬 저장 내용을 Push : action.yml에 설정 해 둔 "on.push"에 의해 Action이 실행
3. 공용 레포(학원 레포)로 PR 생성 : action.yml에 설정 해 둔 "on.pull_request"에 의해 Action이 실행
4. 멘토님의 PR 리뷰 후 승인 시, 공용 레포에 머지 -> deploy.yml에 설정 해 둔 "on.push"에 의해 Action이 실행


11 changes: 5 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@
node_modules/
**/node_modules/

.github/**
# .github/**
files/**

.env

dist
dist/**
coverage/**

REST API test/**
.env
.env.test
.env.test

27 changes: 27 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Base Build image

# node 버전 설정
ARG NODE_VERSION=22.19.0
FROM node:${NODE_VERSION}

# 서버 포트 설정
ENV SERVER_PORT=3000

# 디렉토리 설정
WORKDIR /app

# 복사할 작업 분할(레이어 캐싱)
# 1) package.json, package-lock.json 복사
COPY package*.json ./
RUN npm install

# 2) prisma 복사
COPY prisma ./prisma/
RUN npx prisma generate

# 3) 나머지 파일 복사 및 빌드
COPY . .
RUN npm run build

# 서버 실행 명령어
CMD ["node", "dist/src/server.js"]
61 changes: 14 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,28 @@

### [ 목표 ]

- 판다마켓 서비스를 AWS로 배포하기
- AWS S3 적용
- AWS RDS 적용
- AWS EC2에 Express 서버 배포하기
- (심화) 프로세스 매니저 적용
- (심화) 리버스 프록시 적용
- Github Actions로 테스트, 배포 자동화
- Docker 이미지 만들기


### [ 작업 내용 ]

### 1. 기본 요구사항

- [x] 프로젝트에 프로덕션 배포를 위한 환경 변수 설정
1) Github Actions 활용
- [x] 브랜치에 pull request가 발생하면 테스트를 실행하는 액션을 구현
- [x] main 브랜치에 push가 발생하면 AWS 배포를 진행하는 액션을 구현 : 현재 개발 환경을 고려하여 main 브랜치 뿐만 아니라 개별 브랜치인 "김지선" 브랜치에도 동일하게 적용
- [x] 개인 Github 리포지터리에서 Actions 동작을 확인 : ![GitHub Actions 전체 동작 내용](/.github/sprint-mission-11_git-action-history.png)

1) AWS S3 적용
- [x] AWS S3 버킷 생성 및 퍼블릭 액세스 허용
- [x] 일반 사용자가 S3 업로드된 파일에 접근할 수 있도록 S3 버킷 정책 설정
- [x] AWS EC2에서 AWS S3를 사용하기 위한 액세스 키를 AWS IAM에서 발급
- [x] 프로덕션 환경에서는 파일 업로드에 AWS S3를 사용하도록 구현 수정 : /src/controllers/image.s3.controller.ts
2) AWS RDS 적용
- [x] AWS RDS 프리티어에 해당하는 인스턴스 생성
- [x] RDS 인스턴스에 대한 보안 그룹 설정
- [x] 프로덕션 환경에서는 Prisma에 프로젝트 데이터베이스와 연결하도록 수정
3) AWS EC2에 Express 서버 배포하기
- [x] AWS EC2 프리티어에 해당하는 인스턴스 생성
- [x] SSH를 사용해 EC2 인스턴스에 접속해 Express 서버 배포
2) Docker 이미지 만들기
- [x] Dockerfile 작성
- [x] Docker의 Volume을 활용하여 파일 업로드 처리 : ![Docker Volume을 활용한 파일 업로드 처리](infra/docker/sprint-mission-11_docker_volume.png)
- [x] 데이터베이스는 Postgres 이미지를 사용해 연결 : ![Postgres 이미지 사용](infra/docker/sprint-mission-11_docker_terminal.png)
- [x] 실행된 Express 서버 컨테이너는 호스트 머신에서 3000번 포트로 접근 가능하도록 구현 : ![Express 서버 컨테이너](infra/docker/sprint-mission-11_docker_localhost.png)

### 2. 심화 요구사항

- [x] EC2 인스턴스에서 pm2 프로세스 매니저를 사용하여 애플리케이션을 실행
- [x] EC2 인스턴스에서 nginx 리버스 프록시를 80번 포트로 설정


## [제출 파일 목록]

- [x] 접속 가능한 API 엔드포인트 주소 : http://13.125.62.54
- [x] AWS S3 버킷의 정책 설정 : /infra/S3/policy.png
- [x] AWS RDS 인스턴스의 보안 그룹 설정
1. 인바운드 : /infra/RDS/secure-group-inbound.png
2. 아웃바운드 : /infra/RDS/secure-group-outbound.png
- [x] AWS EC2 인스턴스의 보안 그룹 설정
1. 인바운드 : /infra/EC2/secure-group-inbound.png
2. 아웃바운드 : /infra/EC2/secure-group-outbound.png
3. 초기 / 최종 URL 비교 : /infra/EC2/secure-group-url.png
- [x] pm2 실행 명령어 : /infra/ec2/start.sh
- [ ] pm2 실행 설정 파일 : /infra/ec2/ecosystem.config.js -> 별도의 설정 없이 실행
- [x] nginx 실행 설정 파일 : /infra/ec2/nginx.conf

<br><br><br><br>
<br>

## 멘토에게

- 이번 미션은 전적으로 AI의 도움을 받아 진행하였으며, images.s3.controller.ts 파일은 Ai가 작성하고 검토만 진행하였습니다 (파일 라우터를 초급 프로젝트 때부터 공부하고 있지만, 여전히 전체 로직이 이해가지 않습니다 😭ㅎㅎ)
- 제출 요청 파일 외에도 S3 테스트를 진행한 결과를 함께 제출합니다(자랑용입니다. 작업 도중 문제가 생겨서 좀 헤멧지만 그래도 성공 했다는게 좀 뿌듯해서요😁)
1. 터미널을 사용하여 이미지 업로드 : /infra/S3/img_test_terminal.png
2. 터미널 명령어 : /infra/S3/imgUpload.s3.sh
3. AWS S3 버킷에 업로드된 이미지 목록 : /infra/S3/img_test_s3.png
- 개인적인 일도 있고해서 미션 8,9에 대한 멘토님 코멘트를 신규 코드에 적용 할 시간이 없네요. 신경 써서 알려주셨는데 죄송합니다😢
- 미션 8, 9, 10에 대한 멘토님 코멘트를 적용하며, 전체 코드를 다시 확인하여 리팩토링 진행하였습니다 😁
- 수업을 많이 빠져서 진짜 정신없이 작업 했습니다. 특히, Docker 부분은 정말 개념만 간단히 알고 작업한거라 LMS 강의를 여러번 복습 해야할거 같습니다.
Loading