Skip to content

Commit cdaec43

Browse files
authored
Merge pull request #43 from ije90s/dev
프로젝트 정리
2 parents 827717d + 4b8f6ab commit cdaec43

5 files changed

Lines changed: 178 additions & 96 deletions

File tree

README.md

Lines changed: 75 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,77 @@
1-
<p align="center">
2-
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="120" alt="Nest Logo" /></a>
3-
</p>
4-
5-
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
6-
[circleci-url]: https://circleci.com/gh/nestjs/nest
7-
8-
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
9-
<p align="center">
10-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
11-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
12-
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
13-
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
14-
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
15-
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
16-
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
17-
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg" alt="Donate us"/></a>
18-
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
19-
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow" alt="Follow us on Twitter"></a>
20-
</p>
21-
<!--[![Backers on Open Collective](https://opencollective.com/nest/backers/badge.svg)](https://opencollective.com/nest#backer)
22-
[![Sponsors on Open Collective](https://opencollective.com/nest/sponsors/badge.svg)](https://opencollective.com/nest#sponsor)-->
23-
24-
## Description
25-
26-
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
27-
28-
## Project setup
29-
30-
```bash
31-
$ npm install
32-
```
33-
34-
## Compile and run the project
35-
36-
```bash
37-
# development
38-
$ npm run start
39-
40-
# watch mode
41-
$ npm run start:dev
42-
43-
# production mode
44-
$ npm run start:prod
45-
```
46-
47-
## Run tests
48-
49-
```bash
50-
# unit tests
51-
$ npm run test
52-
53-
# e2e tests
54-
$ npm run test:e2e
55-
56-
# test coverage
57-
$ npm run test:cov
58-
```
59-
60-
## Deployment
61-
62-
When you're ready to deploy your NestJS application to production, there are some key steps you can take to ensure it runs as efficiently as possible. Check out the [deployment documentation](https://docs.nestjs.com/deployment) for more information.
63-
64-
If you are looking for a cloud-based platform to deploy your NestJS application, check out [Mau](https://mau.nestjs.com), our official platform for deploying NestJS applications on AWS. Mau makes deployment straightforward and fast, requiring just a few simple steps:
65-
66-
```bash
67-
$ npm install -g @nestjs/mau
68-
$ mau deploy
1+
## Challenge API
2+
3+
### 개요
4+
- Challenge API는 챌린지 기능을 관리하는 NestJS 기반 REST API입니다.
5+
- 단일 EC2 환경에서 **API 개발부터 CI/CD 파이프라인 구성, 서버 배포까지의 전체 흐름을 경험**하는 것을 목표로 개발했습니다.
6+
- CI/CD 자동화, 마이그레이션 실행 전략, 헬스 체크 기반 배포 검증 등
7+
**운영 관점에서의 의사결정과 구조 설계**에 중점을 두었습니다.
8+
- 현재 서버는 종료된 상태입니다. (2025.12.30 기준)
9+
10+
### 기술 스택
11+
| 구분 | 기술 |
12+
| --- | --- |
13+
| Programming Language | Node.js 20.15.1 |
14+
| Framework | NestJS 11.0.6 |
15+
| Database | MariaDB 10.6 |
16+
| ORM | TypeORM |
17+
| Testing | Jest |
18+
| Version Control | Git |
19+
| Cloud | AWS (EC2, RDS, S3, CodeDeploy, Parameter Store) |
20+
| CI/CD | GitHub Actions, CodeDeploy |
21+
| Process Manager | PM2 |
22+
| API | RESTful API |
23+
24+
25+
### 시스템 구성
26+
- EC2 단일 인스턴스 환경
27+
- RDS(MariaDB) 사용
28+
- GitHub Actions → S3 → CodeDeploy 기반 배포
29+
30+
### CI/CD 파이프라인
31+
- **배포 방식**: All-at-Once
32+
- **배포 검증**: `/health` 엔드포인트 기반 상태 확인
33+
- 개인 프로젝트 특성상 단일 서버 환경으로 운영하여 **마이그레이션은 CD 단계에서 실행**하도록 구성
34+
- SCP, CodeDeploy 두가지 방식으로 연습했으며, 이에 대한 내용은 [scp](/anything/cicd_scp.md), [codeDeploy](/anything/cicd_codedeploy.md)에 기재
35+
36+
```text
37+
GitHub Actions
38+
├─ Test, Build
39+
├─ S3에 빌드 파일 업로드
40+
└─ CodeDeploy 실행
41+
├─ ApplicationStop
42+
│ └─ PM2 프로세스 중지
43+
├─ BeforeInstall
44+
│ └─ AWS Parameter Store 기반 환경 변수 생성
45+
├─ AfterInstall
46+
│ ├─ 패키지 설치
47+
│ └─ TypeORM 마이그레이션 실행
48+
├─ ApplicationStart
49+
│ └─ PM2 startOrReload
50+
└─ ValidateService
51+
└─ /health 엔드포인트 호출
6952
```
7053

71-
With Mau, you can deploy your application in just a few clicks, allowing you to focus on building features rather than managing infrastructure.
72-
73-
## Resources
74-
75-
Check out a few resources that may come in handy when working with NestJS:
76-
77-
- Visit the [NestJS Documentation](https://docs.nestjs.com) to learn more about the framework.
78-
- For questions and support, please visit our [Discord channel](https://discord.gg/G7Qnnhy).
79-
- To dive deeper and get more hands-on experience, check out our official video [courses](https://courses.nestjs.com/).
80-
- Deploy your application to AWS with the help of [NestJS Mau](https://mau.nestjs.com) in just a few clicks.
81-
- Visualize your application graph and interact with the NestJS application in real-time using [NestJS Devtools](https://devtools.nestjs.com).
82-
- Need help with your project (part-time to full-time)? Check out our official [enterprise support](https://enterprise.nestjs.com).
83-
- To stay in the loop and get updates, follow us on [X](https://x.com/nestframework) and [LinkedIn](https://linkedin.com/company/nestjs).
84-
- Looking for a job, or have a job to offer? Check out our official [Jobs board](https://jobs.nestjs.com).
85-
86-
## Support
87-
88-
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
89-
90-
## Stay in touch
91-
92-
- Author - [Kamil Myśliwiec](https://twitter.com/kammysliwiec)
93-
- Website - [https://nestjs.com](https://nestjs.com/)
94-
- Twitter - [@nestframework](https://twitter.com/nestframework)
95-
96-
## License
97-
98-
Nest is [MIT licensed](https://github.com/nestjs/nest/blob/master/LICENSE).
54+
### 주요 구현 기능
55+
- 인증
56+
- JWT + Passport 기반 인증 처리
57+
- Access Token 기반 API 보호
58+
- 데이터베이스
59+
- TypeORM Entity 구성
60+
- 마이그레이션 파일 기반 스키마 관리
61+
- 테스트
62+
- Jest 기반 서비스 레이어 유닛 테스트
63+
- E2E 테스트를 통한 API 흐름 검증
64+
- Health Check
65+
- /health 엔드포인트 제공
66+
- 배포 성공/실패 판단 기준으로 활용
67+
68+
### 의도적 선택 및 제한 사항
69+
- 마이그레이션 중복 방지 미구현
70+
- 단일 서버 환경에서 운영하므로, CD 단계에서 1회 실행하는 방식으로 관리
71+
- 멀티 인스턴스 환경에서 필요한 중복 방지 로직은 범위에서 제외
72+
- Prometheus & Grafana 미적용
73+
- 단일 EC2 환경에서는 CloudWatch로 기본적인 서버 상태 확인이 가능하다고 판단
74+
75+
### 회고
76+
- 실무에서 경험은 있었지만 개념적으로 불명확했던 부분들을 공식 문서와 직접 실습을 통해 다시 정리하는 계기가 되었다.
77+
- 생성형 AI를 보조 수단으로 활용하면서, OOP, TypeScript, Shell Script와 같은 기본 개념에 대한 이해가 있어야 AI의 결과를 판단하고 설계에 반영할 수 있다는 점을 체감했다.

anything/cicd_codedeploy.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
## CI/CD With CodeDepoly
2+
### CI
3+
- 기존에 풀퀘로 진행한 CI처럼 githubactions의 러너에서 빌드까지 진행
4+
- 기존 SCP 압축 파일에 CodeDepoly 실행할 수 있는 appspec.yml, scripts/ 포함하여 압축파일 생성
5+
- 압축파일명은 $GITHUB_SHA(랜덤값 생성)으로 파일명 지정
6+
- S3, CodeDepoly 접근할 수 있는 사용자 계정의 Access 값들을 셋팅
7+
- S3에 압축파일 업로드
8+
- CodeDepoly에서 해당 압축파일에서 EC2로 전달
9+
10+
### CD
11+
- Scripts 폴더 내에 있는 쉘스크립트가 appspec에서 명시한 훅 순서대로 진행
12+
- overwrite: 허용
13+
- ApplicationStop: pm2 stop
14+
- BeforeInstall: 환경변수 생성(AWS Parameter Store)
15+
- AfterInstall: npm 패키지 설치 & 마이그레이션 실행
16+
- ApplicationStart: pm2 startOrReload
17+
- ValidateService: 헬스 체크
18+
19+
### ETC
20+
- EC2, RDS(mariadb) 셋팅 > node, pm2 설치(2025.12.25)
21+
- 단일 서버로 운영했기 때문에 CD에서 마이그레이션 실행
22+
- S3 & CodeDepoly 셋팅 & IAM 추가, EC2 내 code-depoly-agent 설치(2025.12.27)
23+
- CodeDepoly: CodeDepoly 접근할 수 있는 정책이 포함되어 있는 역할 추가
24+
- EC2: codeDepoly 접근할 수 있는 권한 추가
25+
- Githubactions 사용자: s3, codedepoly 접근할 수 있는 권한 추가 생성 후, access 키 생성
26+
- Code-depoly-agent 설치: https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html
27+
- log: 확인 /opt/codedeploy-agent/deployment-root/{deployment-group-ID}/{deployment-ID}/logs/scripts.log
28+
- 환경변수
29+
- 기존에는 서버 내의 환경변수가 없으면, 배포 중지하거나 백업 파일을 만든 후에 새 환경 변수 파일을 생성
30+
- AWS Parameter Store 활용하여 환경변수들을 등록 후, 반복문으로 한개 한개 가져와서 환경변수 파일 구성
31+
- 10,000개 미만은 공짜기이기 때문에 바로 등록해서 api 호출로 가져오는 걸로 변경
32+
- 파라미터에 접근할 수 있는 권한은 EC2에 추가
33+
34+
### Error
35+
- Error: Jest not found
36+
- npm ci --omit=dev 옵셥값을 줬는데, 이 옵션값 때문에 테스트 진행 에러
37+
- Error: appspec.yml: Cannot stat: No such file or directory
38+
- 파일명 오타
39+
- Error: Credentials could not be loaded, please check your action inputs: Could not load credentials from any providers
40+
- 시크릿 키 오타
41+
- Error: creational 값이 있으면, ec2와 충돌나 parameter store에 있는 값을 못 가져옴
42+
- Error: An error occurred (AccessDeniedException) when calling the GetParametersByPath operation: User: arn:aws:iam::xxxxxx:user/gitactions-user is not authorized to perform: ssm:GetParametersByPath on resource: arn:aws:ssm:ap-northeast-2:xxxxxx:parameter/challenge-api/prod because no identity-based policy allows the ssm:GetParametersByPath action
43+
- EC2에 ssmManager Access 접근이 되어져 있다면, 서버 내에서 한번 더 사용자에 대한 configure를 등록하면, 충돌 발생 > configure 명시적으로 제거
44+
```shell
45+
rm -rf ~/.aws
46+
# 확인
47+
ls -la ~/.aws
48+
```
49+
- Error: You must specify a region. You can also configure your region by running "aws configure".
50+
- 지역 명시
51+
- Error: An error occurred (AccessDeniedException) when calling the GetParametersByPath operation: User: arn:aws:sts::xxxxxx:assumed-role/code-deploy-ec2-role/i-069cab1b827924414 is not authorized to perform: ssm:GetParametersByPath on resource: arn:aws:ssm:ap-northeast-2:xxxxxx:parameter/challenge-api/prod because no identity-based policy allows the ssm:GetParametersByPath action
52+
- EC2에 권한 추가가 잘되지 않아, ssmManagerReadOnly Access로 변경
53+
- Error: The `npm ci` command can only install with an existing package-lock.json or npm error npm-shrinkwrap.json with lockfileVersion >= 1. Run an install with npm@5 or npm error later to generate a package-lock.json file, then try again.
54+
- npm 실행 위치 오류
55+
56+
### 강제 Error
57+
- 환경변수 파일 유무 확인: Parameter Store 전에 서버 내에 환경 변수 파일이 있는지 확인 후 배포 진행
58+
![환경변수실패](./images/env_fail.png)
59+
- 헬스 체크 확인: start.sh에 일부러 pm2 실행을 주석 처리하여 validservice에서 헬스체크하는지 확인
60+
![헬스체크실패](./images/healthcheck_fail.png)
61+

anything/cicd_scp.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## CI/CD With SCP
2+
### CI
3+
- 기존에 풀퀘로 진행한 CI처럼 githubactions의 러너에서 빌드까지 진행
4+
- production에서 필요한 파일들만 압축파일을 생성
5+
- 스토어에 제공하는 scp로 ec2에 압축파일 업로드
6+
7+
### CD
8+
- app 폴더를 생성, 그 폴더에 압축파일에 덮어쓰기로 압축해제(그 전에 app에 있던 파일들은 삭제)
9+
- 이미 러너에서 ci로 받았기 때문에 prodcution 모드로 npm 설치
10+
- 마이그레이션 실행 하기 전에 현 위치와 마이그레이션 파일들이 있는지 확인 후, 마이그레이션 실행
11+
- pm2로 스타트/리로드
12+
13+
### ETC
14+
- EC2, RDS(mariadb) 셋팅 > node, pm2 설치(2025.12.25)
15+
- github에 ssh 접속 정보 저장
16+
- .env 원본 파일은 미리 서버에 등록
17+
- 압축 파일명을 app_{타입스탬프} 형태로 하여 파일명 중복 방지
18+
19+
### Error
20+
- TypeORM 마이그레이션 부분에서 오류가 발생하여 10번 시도 끝에 배포 성공
21+
- ❗️마이그레이션 경로, 실행 명령어 점검 필요
22+
- Error: Cannot find module 'ts-node/register'
23+
- 타입스크립트 기반 ts-node로 실행 대신 js로 실행되도록 변경
24+
```text
25+
# ts 기반 마이그레이션 실행
26+
node -r ts-node/register ./node_modules/typeorm/cli.js -d typeorm.datasource.ts
27+
# js 기반 마이그레이션 실행
28+
node ./node_modules/typeorm/cli.js -d dist/typeorm.datasource.js migration:run
29+
```
30+
- Error: Cannot find module '/home/***/app/node_modules/typeorm/cli.js'
31+
- cli 파일을 못찾아서 계속 실패하여 npx로 사용
32+
```text
33+
npx typeorm migration:run -d ./dist/typeorm.datasource.js
34+
```
35+
- Error: http fetch GET https://registry.npmjs.org/typeorm attempt 1 failed with ETIMEDOUT
36+
- 보안그룹 개방 안해서 일시적으로 80/443 포트 열어둠
37+
- Error: 마이그레이션이 됐으나, 엔티티/마이그레이션 경로가 맞지 않아서 migrations 테이블만 생성
38+
- `NODE_ENV`에 따라 구분해서 실행하려고 했으나, api 서버 실행하기 전에 마이그레이션을 진행하기 때문에 모드 구분 없이 {ts,js} 파일 형식만 & path를 이용하여 경로 위치 변경
39+
```text
40+
entities: [join(__dirname, 'src/**/entity/*.entity.{ts,js}')],
41+
migrations: [join(__dirname, 'src/migrations/*.{ts,js}')],
42+
```

anything/images/env_fail.png

97.7 KB
Loading
97.7 KB
Loading

0 commit comments

Comments
 (0)