Skip to content

Commit 9a98eb6

Browse files
authored
Merge pull request #362 from Quickchive/develop
Develop to main
2 parents 788407c + 4c0e2a3 commit 9a98eb6

File tree

157 files changed

+20359
-10588
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+20359
-10588
lines changed

.github/workflows/ci-cd-for-test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Docker Image CI && Deploy to EC2 for Test Server
22

33
on:
44
push:
5-
branches: ['release/**']
5+
branches: ['release/**', develop]
66

77
jobs:
88
job1:
@@ -23,7 +23,7 @@ jobs:
2323
uses: docker/[email protected]
2424
with:
2525
context: .
26-
tags: hou27/test_quickchive_backend:latest
26+
tags: quickarchive/quickarchive_api:test
2727
push: true
2828
job2:
2929
needs: job1

.github/workflows/ci-cd.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
uses: docker/[email protected]
2626
with:
2727
context: .
28-
tags: hou27/quickchive_backend:latest
28+
tags: quickarchive/quickarchive_api:main
2929
# build on feature branches, push only on develop branch
3030
push: true
3131
job2:
@@ -37,8 +37,8 @@ jobs:
3737
- name: executing remote ssh commands using password
3838
uses: appleboy/ssh-action@master
3939
with:
40-
host: ${{ secrets.HOST }}
40+
host: ${{ secrets.PROD_HOST }}
4141
username: ubuntu
42-
key: ${{ secrets.KEY_PAIR }}
42+
key: ${{ secrets.PROD_KEY_PAIR }}
4343
script: |
44-
sh /home/ubuntu/actions-runner/deploy.sh
44+
sh /home/ec2-user/deploy.sh

.gitignore

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pnpm-debug.log*
1010
yarn-debug.log*
1111
yarn-error.log*
1212
lerna-debug.log*
13+
/user_logs
1314

1415
# OS
1516
.DS_Store
@@ -36,10 +37,10 @@ lerna-debug.log*
3637

3738
# dotenv environment variables file
3839
.env
39-
.env.dev
40-
.env.prod
41-
.env.test
40+
.env.*
4241
envFile.ts
4342

4443
# certificate files
45-
*.pem
44+
*.pem
45+
46+
.localstack

.vscode/launch.json

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
// IntelliSense를 사용하여 가능한 특성에 대해 알아보세요.
3+
// 기존 특성에 대한 설명을 보려면 가리킵니다.
4+
// 자세한 내용을 보려면 https://go.microsoft.com/fwlink/?linkid=830387을(를) 방문하세요.
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "node",
9+
"request": "launch",
10+
"name": "개발 디버그",
11+
"skipFiles": ["<node_internals>/**"],
12+
"runtimeExecutable": "npm",
13+
"runtimeArgs": ["run", "start:local"],
14+
"autoAttachChildProcesses": true,
15+
"restart": true,
16+
"sourceMaps": true,
17+
"cwd": "${workspaceRoot}",
18+
"console": "integratedTerminal",
19+
"protocol": "inspector"
20+
},
21+
{
22+
"type": "node",
23+
"request": "launch",
24+
"name": "E2E 테스트 디버그",
25+
"skipFiles": ["<node_internals>/**"],
26+
"runtimeExecutable": "npm",
27+
"runtimeArgs": ["run", "test:e2e"],
28+
"autoAttachChildProcesses": true,
29+
"restart": true,
30+
"sourceMaps": true,
31+
"cwd": "${workspaceRoot}",
32+
"console": "integratedTerminal",
33+
"protocol": "inspector"
34+
}
35+
]
36+
}

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"typescript.preferences.importModuleSpecifier": "relative"
3+
}

README.md

Lines changed: 31 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
[Quickchive](https://quickchive.swygbro.com/)
99
[Quickchive Frontend](https://github.com/Quickchive/Quickchive-frontend)
1010

11-
# v0.1.0
11+
# v1.0.0
1212

1313
> releated with quickchive version 1.0
1414
@@ -46,27 +46,21 @@
4646

4747
### User API
4848

49-
| URL | method | Usage | Authorization Needed |
50-
| --------------------------- | ------ | -------------------- | -------------------- |
51-
| /api/users/edit | POST | 프로필 수정 | O |
52-
| /api/users/reset-password | POST | 비밀번호 재생성 | X |
53-
| /api/users/me | GET | 프로필 조회 | O |
54-
| /api/users/load-contents | GET | 유저의 콘텐츠 조회 | O |
55-
| /api/users/load-favorites | GET | 유저의 즐겨찾기 조회 | O |
56-
| /api/users/load-collections | GET | 유저의 콜렉션 조회 | O |
57-
| /api/users/load-categories | GET | 유저의 카테고리 조회 | O |
49+
| URL | method | Usage | Authorization Needed |
50+
| ------------------ | ------ | -------------------- | -------------------- |
51+
| /api/user | PATCH | 유저 정보 수정 | O |
52+
| /api/user/password | POST | 비밀번호 재설정 | X |
53+
| /api/user | GET | 유저 정보 조회 | O |
54+
| /api/user | DELETE | 유저 삭제(회원 탈퇴) | O |
5855

5956
### Auth API
6057

61-
| URL | method | Usage | Authorization Needed |
62-
| ------------------------------------------------- | ------ | -------------------------------- | -------------------- |
63-
| /api/auth/register | POST | 회원가입 | X |
64-
| /api/auth/login | POST | 이메일 로그인 | X |
65-
| /api/auth/logout | POST | 로그아웃 | O |
66-
| /api/auth/reissue | POST | 토큰 재발행 | X |
67-
| /api/auth/send-verify-email/\<str:email\> | GET | 유저 인증을 위한 메일 전송 | X |
68-
| /api/auth/send-password-reset-email/\<str:email\> | GET | 비밀번호 재설정을 위한 메일 전송 | X |
69-
| /api/auth/verify-email | GET | 이메일 인증 | X |
58+
| URL | method | Usage | Authorization Needed |
59+
| ------------------------------------------------- | ------ | ---------------------------------- | -------------------- |
60+
| /api/auth/login | POST | 이메일 로그인 | X |
61+
| /api/auth/logout | POST | 로그아웃 | O |
62+
| /api/auth/token | POST | 토큰 재발행(access, refresh token) | X |
63+
| /api/auth/send-password-reset-email/\<str:email\> | POST | 비밀번호 재설정을 위한 메일 전송 | X |
7064

7165
### OAuth API
7266

@@ -79,32 +73,27 @@
7973

8074
### Content API
8175

82-
| URL | method | Usage | Authorization Needed |
83-
| ---------------------------------------- | ------ | --------------------- | -------------------- |
84-
| /api/contents/add | POST | 콘텐츠 추가 | O |
85-
| /api/contents/addMultiple | POST | 다수의 콘텐츠 추가 | O |
86-
| /api/contents/update | POST | 콘텐츠 정보 수정 | O |
87-
| /api/contents/favorite/\<int:contentId> | PATCH | 즐겨찾기 등록 및 해제 | O |
88-
| /api/contents/read/\<int:contentId> | PATCH | 읽었음 표시 | O |
89-
| /api/contents/delete/\<int:contentId> | DELETE | 콘텐츠 삭제 | O |
90-
| /api/contents/summarize/\<int:contentId> | GET | 콘텐츠 문서 요약 | O |
76+
| URL | method | Usage | Authorization Needed |
77+
| ---------------------------------------- | ------ | ----------------------- | -------------------- |
78+
| /api/contents | POST | 콘텐츠 추가 | O |
79+
| /api/contents/multiple | POST | 다수의 콘텐츠 일괄 추가 | O |
80+
| /api/contents | PATCH | 콘텐츠 정보 수정 | O |
81+
| /api/contents/\<int:contentsId>/favorite | PATCH | 즐겨찾기 등록 및 해제 | O |
82+
| /api/contents/\<int:contentsId> | DELETE | 콘텐츠 삭제 | O |
83+
| /api/contents | GET | 콘텐츠 조회 | O |
84+
| /api/contents/favorite | GET | 즐겨찾기 조회 | O |
85+
| /api/contents/\<int:contentId>/summarize | GET | 콘텐츠 문서 요약 | O |
86+
| /api/contents/reminder-count | GET | 리마인더 개수 조회 | O |
9187

9288
### Category API
9389

94-
| URL | method | Usage | Authorization Needed |
95-
| -------------------------------------- | ------ | ------------- | -------------------- |
96-
| /api/category/add | POST | 카테고리 추가 | O |
97-
| /api/category/update | POST | 카테고리 수정 | O |
98-
| /api/category/delete/\<int:categoryId> | DELETE | 카테고리 삭제 | O |
99-
100-
### Collection API
101-
102-
| URL | method | Usage | Authorization Needed |
103-
| --------------------------------------------- | ------ | --------------------- | -------------------- |
104-
| /api/collections/add | POST | 콜렉션 추가 | O |
105-
| /api/collections/update | POST | 콜렉션 수정 | O |
106-
| /api/collections/favorite/\<int:collectionId> | PATCH | 즐겨찾기 등록 및 해제 | O |
107-
| /api/collections/delete/\<int:contentId> | DELETE | 콜렉션 삭제 | O |
90+
| URL | method | Usage | Authorization Needed |
91+
| --------------------------------- | ------ | ------------------------- | -------------------- |
92+
| /api/categories | POST | 카테고리 추가 | O |
93+
| /api/categories | PATCH | 카테고리 수정 | O |
94+
| /api/categories/\<int:categoryId> | DELETE | 카테고리 삭제 | O |
95+
| /api/categories | GET | 카테고리 조회 | O |
96+
| /api/categories/frequent | GET | 자주 저장한 카테고리 조회 | O |
10897

10998
## License
11099

Wiki/DB_Migration.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# TypeORM을 이용한 DB Migration
2+
3+
## typerom-config.service.ts
4+
5+
```typescript
6+
import { Injectable } from '@nestjs/common';
7+
import { ConfigService } from '@nestjs/config';
8+
import { TypeOrmModuleOptions, TypeOrmOptionsFactory } from '@nestjs/typeorm';
9+
import { Collection } from '../collections/entities/collection.entity';
10+
import { NestedContent } from '../collections/entities/nested-content.entity';
11+
import { Category } from '../contents/entities/category.entity';
12+
import { Content } from '../contents/entities/content.entity';
13+
import { User } from '../users/entities/user.entity';
14+
15+
@Injectable()
16+
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
17+
constructor(private configService: ConfigService) {}
18+
19+
createTypeOrmOptions(): TypeOrmModuleOptions {
20+
return {
21+
type: 'postgres',
22+
...(this.configService.get('POSTGRES_DB')
23+
? {
24+
host: this.configService.get('POSTGRES_DB'),
25+
port: +this.configService.get('DB_PORT'),
26+
username: this.configService.get('POSTGRES_USER'),
27+
password: this.configService.get('POSTGRES_PASSWORD'),
28+
database: this.configService.get('POSTGRES_DB_NAME'),
29+
}
30+
: {
31+
host: this.configService.get('DB_HOST'),
32+
port: +this.configService.get('DB_PORT'),
33+
username: this.configService.get('DB_USERNAME'),
34+
password: this.configService.get('DB_PW'),
35+
database: this.configService.get('DB_NAME'),
36+
}),
37+
maxQueryExecutionTime: 10000, // If query execution time exceed this given max execution time (in milliseconds) then logger will log this query.
38+
extra: {
39+
statement_timeout: 10000, // timeout in milliseconds
40+
},
41+
synchronize: this.configService.get('NODE_ENV') !== 'prod',
42+
logging:
43+
this.configService.get('NODE_ENV') !== 'prod' &&
44+
this.configService.get('NODE_ENV') !== 'test',
45+
entities: [User, Content, Category, Collection, NestedContent],
46+
migrations: [__dirname + '/migrations/**/*{.ts,.js}'],
47+
} as TypeOrmModuleOptions;
48+
}
49+
}
50+
```
51+
52+
기본적인 typeorm 설정
53+
54+
## ormconfig(data source)
55+
56+
```typescript
57+
import { DataSource, DataSourceOptions } from 'typeorm';
58+
import * as dotenv from 'dotenv';
59+
60+
dotenv.config({ path: __dirname + '/../../.env.dev' });
61+
62+
export const AppDataSource = new DataSource({
63+
type: 'postgres',
64+
...(process.env.POSTGRES_DB
65+
? {
66+
host: process.env.POSTGRES_DB,
67+
port: +process.env.DB_PORT,
68+
username: process.env.POSTGRES_USER,
69+
password: process.env.POSTGRES_PASSWORD,
70+
database: process.env.POSTGRES_DB_NAME,
71+
}
72+
: {
73+
host: process.env.DB_HOST,
74+
port: +process.env.DB_PORT,
75+
username: process.env.DB_USERNAME,
76+
password: process.env.DB_PW,
77+
database: process.env.DB_NAME,
78+
}),
79+
maxQueryExecutionTime: 10000, // If query execution time exceed this given max execution time (in milliseconds) then logger will log this query.
80+
extra: {
81+
statement_timeout: 10000, // timeout in milliseconds
82+
},
83+
synchronize: false,
84+
logging: process.env.NODE_ENV !== 'prod' && process.env.NODE_ENV !== 'test',
85+
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
86+
migrations: [__dirname + '/migrations/**/*{.ts,.js}'],
87+
cli: {
88+
entitiesDir: 'src/**/**',
89+
migrationsDir: 'src/database/migrations',
90+
},
91+
} as DataSourceOptions);
92+
```
93+
94+
typeorm cli를 사용하기 위한 설정
95+
96+
## package.json
97+
98+
```json
99+
{
100+
...
101+
"scripts": {
102+
...
103+
"typeorm": "typeorm-ts-node-commonjs",
104+
"migration:generate": "npm run typeorm -- -d src/database/ormconfig.ts migration:generate",
105+
"migration:create": "npm run typeorm -- migration:create",
106+
"migration:run": "npm run typeorm -- -d src/database/ormconfig.ts migration:run"
107+
},
108+
...
109+
```
110+
111+
script를 통해 typeorm cli를 사용할 수 있도록 설정
112+
113+
<br/>
114+
115+
# 주의점
116+
117+
## generate
118+
119+
create랑 generate 모두 마이그레이션 파일을 생성하지만 둘 사이에는 큰 차이가 있다.
120+
create는 그냥 빈 파일만을 생성시켜 줄 뿐이지만
121+
generate는 db와 entity 사이의 차이점이 있다면 이를 파악하고 sql구문을 작성한다.
122+
그러나 컬럼의 길이 또는 타입 변경 시 해당 테이블의 컬럼을 DROP한 후 재생성하는 방식이기 때문에 기존 컬럼에 있던 데이터가 모두 삭제된다.
123+
124+
```bash
125+
EX)
126+
npm run migration:generate src/database/migrations/migration_test
127+
```

docker-compose.yml

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,42 @@ services:
55
image: redis:latest
66
restart: always
77
ports:
8-
- 6379:6379
8+
- 6380:6379
99
networks:
1010
- shared-network
11+
1112
postgres: # Name of container
1213
image: postgres:alpine
1314
restart: always
1415
env_file:
15-
- .env.prod
16+
- .env.local
1617
environment:
1718
POSTGRES_HOST_AUTH_METHOD: 'trust'
1819
TZ: 'Asia/Seoul' # Timezone for OS
1920
PGTZ: 'Asia/Seoul' # Timezone for postgres
2021
ports:
21-
- 5432:5432
22+
- 5433:5432
2223
networks:
2324
- shared-network
25+
26+
localstack:
27+
container_name: 'localstack-quickarchive'
28+
image: localstack/localstack:latest
29+
ports:
30+
- '4567:4566' # Default port forward
31+
environment:
32+
- SERVICES=s3
33+
- EDGE_PORT=4566
34+
- DEBUG=1 # Debug level 1 if you want to logs, 0 if you want to disable
35+
- START_WEB=0 # Flag to control whether the Web UI should be started in Docker
36+
- AWS_ACCESS_KEY_ID=local
37+
- AWS_SECRET_ACCESS_KEY=local
38+
- DEFAULT_REGION=ap-northeast-2
39+
volumes:
40+
- './.localstack:/var/lib/localstack'
41+
- '/var/run/docker.sock:/var/run/docker.sock'
42+
- './localstack_s3_init.sh:/etc/localstack/init/ready.d/localstack_s3_init.sh'
43+
2444
networks:
2545
shared-network:
2646
driver: bridge

localstack_s3_init.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
echo "Init localstack s3"
3+
awslocal s3 mb s3://quickarchive-common-image

0 commit comments

Comments
 (0)