pilot project for True point
Truepoint์ ๋๋ถ๋ถ์ ์๋น์ค๋ typescript๋ก ์์ฑ๋ฉ๋๋ค.
๋๋ถ๋ถ์ javascript(typescript ์ญ์) ํ๋ก์ ํธ์์ ์ฝ๋์ ๊ท์น์ ์ง์ ํ๊ณ ์ฌ๋ฐ๋ฅธ ๊ท์น์ ๋ง๊ฒ ์์ฑํ ์ ์๋๋ก Eslint๋ฅผ ์ฌ์ฉํฉ๋๋ค.
prettier๋ฅผ ํตํด ์ฝ๋ ์ ์ฅ ์ ์ฌ๋ฐ๋ฅธ ์ฝ๋ฉ ๋ฐฉ์์ผ๋ก์ ์๋ ์์ ๊ธฐ๋ฅ์ ๋ง๋ถ์ฌ ์ฌ์ฉํ์ฌ ๋์ฑ ์ฝ๊ณ ๋น ๋ฅด๊ฒ ์ฝ๋ฉํ์ค์ ์ ์ฉํ ์ ์์ต๋๋ค.
Truepoint๋ Vscode์์ ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ๋ฅผ ๊ถ์ฅํฉ๋๋ค. ์์ ๋งํ ๊ธฐ๋ฅ์ ์ฌ์ฉํ๊ธฐ ์ํด ์ฝ๋ ํ์ง ๊ด๋ฆฌ ํด์ ์ค์นํฉ๋๋ค.
Eslint Vscode Extension์ ์ค์นํด ์ฃผ์ธ์. ( Extensions => eslint ๊ฒ์ => install and enable )
์ดํ Cmd
+ ,
(windows: ctrl
+ ,
) ๋จ์ถ์ด๋ฅผ ์
๋ ฅํ์ฌ vscode setting ํ์ผ์ ์ด๊ณ , ์ฐ์ธก ์๋จ์ open settings(JSON) ๋ฒํผ์ ํด๋ฆญ ํด settings.json
ํ์ผ์ ์ด์ด ์๋์ ๋ด์ฉ์ ์ตํ๋จ์ ์ถ๊ฐํฉ๋๋ค.
// typescript semantic highlighting
"editor.semanticHighlighting.enabled": true,
// These are all my auto-save configs
"editor.formatOnSave": true,
// turn it off for JS and JSX, we will do this via eslint
"[javascript]": {
"editor.formatOnSave": false,
"editor.tabSize": 2
},
"[javascriptreact]": {
"editor.formatOnSave": false,
"editor.tabSize": 2
},
"[typescript]": {
"editor.formatOnSave": false,
"editor.tabSize": 2
},
"[typescriptreact]": {
"editor.formatOnSave": false,
"editor.tabSize": 2
},
// eslint config
"eslint.packageManager": "yarn",
"eslint.codeAction.showDocumentation": {
"enable": true
}
์ถ๊ฐ์ ์ผ๋ก vscode์์ ๊ฐ๋ฐ ์์ฐ์ฑ ํฅ์์ ์ํด ๋ค์์ ์ฝ๋๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค. vscode์ Explorer์์ ๊ฒ์ ์ ํฌํจ๋์ง ์์ ํ์ผ ๋๋ ํด๋๋ฅผ ์ค์ ํฉ๋๋ค.
// ๊ฒ์์ ๊ฒ์๋์ง ์์ ํ์ผ ๋ฐ ๋๋ ํ ๋ฆฌ ์ค์
"search.exclude": {
"**/.git": true,
"**/node_modules": true,
"**/bower_components": true,
"**/tmp": true,
"**/build": true,
"**/dist": true,
"**/yarn.lock": true,
"**/*.log": true,
},
truepoint์ REST API ์๋น์ค๋ nestjs ํ๋ ์์ํฌ๋ฅผ ์ฌ์ฉํฉ๋๋ค. nestjs๋ ์ผ๊ดํ๋ ๋ฐฉ์์ผ๋ก Nodejs Backend ์ฑ์ ๊ฐ๋ฐํ ์ ์๊ฒ ๋์์ค๋๋ค.
nestjs๋ Angular์ ์ฒ ํ๊ณผ ๊ฐ๋
์ ๋ง์ ๋ถ๋ถ ์ฐจ์ฉํ์๊ณ , ๊ทธ์ ๋ฐ๋ฅด๋ ์ฌ๋ฌ ๊ฐ๋
๊ณผ ๊ทธ์ ๋ฐ๋ฅด๋ ํ์ผ ๋ค์ด๋ฐ ๋ฃฐ์ด ์์ต๋๋ค.
vscode์ material-icon-theme ํ์ฅํ๋ก๊ทธ๋จ์ ์ฌ์ฉํ๋ฉด ํ์๊ธฐ์์ ๋์ฑ ์ฝ๊ณ ๋ช
ํํ๊ฒ ํ์ผ๊ณผ ํด๋๋ฅผ ๊ตฌ๋ถํ ์ ์์ต๋๋ค.
vscode์ Material Icon Theme๋ฅผ ์ค์นํฉ๋๋ค. ( Extensions => material-icon-theme ๊ฒ์ => intsall and enable )
๊ธฐ๋ณธ์ ์ผ๋ก material-icon-theme๋ nestjs ๋ฐฉ์์ ํ์ผ๋ค์ Angular ์์ด์ฝ์ผ๋ก ํ์ํฉ๋๋ค. nestjs ์์ด์ฝ์ผ๋ก ๋ณ๊ฒฝํ๊ธฐ ์ํด ๋ค์์ ๊ณผ์ ์ ์งํํฉ๋๋ค.
Cmd
+ ,
(windows: ctrl
+ ,
)=> ์ฐ์ธก ์๋จ Open Settings(JSON) ๋ฒํผ์ผ๋ก ์ค์ ํ์ผ์ ์ด์ด ๋ค์ ๋ด์ฉ์ ์ถ๊ฐํฉ๋๋ค.
์ด๋ฅผ ํตํด vscode Explorer์์ Nest์ ๊ด๋ จ๋ ํ์ผ, ํด๋๋ค์ด ๋ ๋ช
ํํ ์์ด์ฝ์ผ๋ก ๋ํ๋ฉ๋๋ค.
// material-icon-theme config
"material-icon-theme.files.associations": {
"*.pipe.ts": "nest-pipe",
"*.guard.ts": "nest-guard",
"*.controller.ts": "nest-controller",
"*.module.ts": "nest-module",
"*.service.ts": "nest-service",
"*.middleware.ts": "nest-middleware",
"*.filter.ts": "nest-filter",
"*.interface.ts": "typescript-def",
"*.dto.ts": "nest-resolver",
"*.strategy.ts": "key",
"*.entity.ts": "sequelize",
"*.config.ts": "settings",
"*.style.ts": "css",
"*.roles.ts": "nest-decorator",
"*.decorator.ts": "nest-decorator",
},
"material-icon-theme.folders.associations": {
"interfaces": "typescript",
"atoms": "react-components",
"organisms": "core",
"dto": "delta",
"strategies": "keys",
"entities": "database"
}
truepoint์ ๋ชจ๋ ์๋น์ค๋ ํจํค์ง ๋งค๋์ ๋ก yarn์ ์ฌ์ฉํฉ๋๋ค. ๋จผ์ yarn์ ์ค์นํ ์ดํ, yarn์ ํตํด ๊ฐ ์๋น์ค ํด๋์ ์์กด๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์นํฉ๋๋ค. yarn ๊ณต์ ํํ์ด์ง - ์ค์น
๋ค์์ ๋ช ๋ น์ด๋ฅผ ํตํด ์์กด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ค์น ํฉ๋๋ค.
cd client
yarn
cd server
yarn
๋ค์์ ๋ช ๋ น์ด๋ฅผ ํตํด ๊ฐ ์๋ฒ๋ฅผ ์คํํฉ๋๋ค
- ํ๋ก ํธ ์๋
# ์๋์ฐ์ฆ OS
yarn start
# ๋งฅOS
yarn start:mac
- ๋ฐฑ์๋
# OS ๊ตฌ๋ถ ์์ด ์คํ ์คํฌ๋ฆฝํธ ๋์ผํฉ๋๋ค.
# devํ๊ฒฝ ( hot reloading )
yarn start:dev
monorepo๋ ๋ค์ํ ๋ชจ๋์ ์ฌ๋ฌ ๋ฆฌํ์งํ ๋ฆฌ๋ก ๊ด๋ฆฌํ์ง ์๊ณ , ํ๋์ ๋ฆฌํ์งํ ๋ฆฌ์์ ๊ด๋ฆฌํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. monorepo๋ก์ ์ฌ๋ฌ ๋ชจ๋์ ํจ๊ป ๊ด๋ฆฌํ๊ฒ ๋๋ฉด ์ ์ญ์ ์ผ๋ก eslint๋ husky, tsconfig ๋ฑ์ ๋ํด ์ค์ ํ์ฌ ํต์ผ์ฑ์๋ ํ๋ก์ ํธ ๊ด๋ฆฌ์ ์ฉ์ดํ๋ฉฐ, ๊ฐ ๋ชจ๋ ๊ฐ ์์กด์ด ํ์ํ ๊ฒฝ์ฐ์ ์ฉ์ดํฉ๋๋ค.
tp-mvp ํ๋ก์ ํธ์์๋ monorepo๋ก ํ๋ก์ ํธ๋ฅผ ๊ด๋ฆฌํ๊ณ ์ ํฉ๋๋ค. ์ด๋ก์ธํด ๋ณ๊ฒฝ๋๋ ํด๋ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค
- ํ์ฌ
tp-mvp
client
web
package.json
node_modules
yarn.lock
.eslintrc
admin
package.json
node_modules
yarn.lock
.eslintrc
server
package.json
node_modules
yarn.lock
.eslintrc
- ์ดํ
tp-mvp
client
web
package.json
admin
package.json
server
package.json
shared
package.json
node_modules
yarn.lock
.eslintrc
๊ธฐ์กด UI ๋ฐ ์น ํ์ด์ง ๋ฆฌ์กํธ ์๋ฒ๋ client/web, Nest API ์๋ฒ๋ server ํด๋์ ๊ด๋ฆฌ๋์ด ์์ผ๋ฉฐ, HTTP/S ์ฐ๊ฒฐ๋ก ์๋ก ํต์ ํ๋ฉฐ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ํํ์ ๋๋ค. useAxios hook์ ํตํด ๋ฐฑ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๊ณ , ์ ํฌ๋ ๋ฐฑ์๋๋ก ๋ถํฐ ์๋ต๋ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ๋ฆฌ์กํธ ๋ด๋ถ์์ ํด๋น ๋ฐ์ดํฐ๋ฅผ ๋ ๋๋ง ํ๋ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ค๋ฃจ๊ณ ์์ต๋๋ค.
์์ ๊ณผ์ ์์ ํ๋ก ํธ์๋๋ ๋ฐฑ์๋๋ก๋ถํฐ ์๋ต๋๋ ๋ฐ์ดํฐ์ ํํ๊ฐ ์ด๋ป๊ฒ ๋๋ ์ง ์์์ผ ํฉ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก axios์์ ๋ฐฑ์๋๋ก๋ถํฐ ๋ฐํ๋๋ ๋ฐ์ดํฐ ๊ฐ์ฒด์ธres.data
์ ํ์
์ any
๋ก ์ค์ ๋์ด ์์ต๋๋ค. res.data
๋ฅผ any
๊ฐ ์๋ ์๋ง์ ํ์
๋๋ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๊ฒ ํ๊ธฐ ์ํด์๋ axios ์์ฒญ์ generic์ ํตํด res.data
์ ํ์
์ ๋ช
์ํด์ฃผ์ด์ผ ํฉ๋๋ค.
๋ํ ๋ฐฑ์๋๋ ํ๋ก ํธ์๋๋ก๋ถํฐ API ์์ฒญ์ ์ ์ก๋ ์ ํํ ๋ฐ์ดํฐ์ ํํ(data transfer object, DTO)๋ฅผ ์ ์ํด ๋์ด์ผ ํ๋ฉฐ, ๊ทธ ์ ์๋ ๋ฐ์ดํฐ ํํ์ ์ฌ๋ฐ๋ฅด๊ฒ ๋ง๋ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ์๋๊ฐ๋ฅผ ํ์ธํด์ผ ํฉ๋๋ค. ๋๋ถ์ด ํ๋ก ํธ์๋๋ก ์๋ตํ ๋ฐ์ดํฐ์ ํํ๋ฅผ ์ ์ํด ๋์ด์ผ ํ๋ฉฐ, ํ๋ก ํธ์๋์๋ ํด๋น ๋ฐํ๋ ํ์ ์ ๋ณด๋ฅผ ๊ณต์ ํ๋ ๊ฒ์ด ๋ฐ๋์งํฉ๋๋ค.
๊ธฐ์กด์ tp ํ๋ก์ ํธ์์๋ ๋ฐฑ์๋์ ๊ฒฝ์ฐ DTO๋ฅผ ์ ์ํ๊ณ , ์๋ตํ ๋ฐ์ดํฐ ํํ์ญ์ ์ ์ํด์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ํ์ง๋ง ํ๋ก ํธ์๋์์๋ ๋๊ฐ์ ๊ฒฝ์ฐ ๋ฐฑ์๋๋ก๋ถํฐ ์๋ต๋ฐ์ ๋ฐ์ดํฐ์ ํํ๋ฅผ ๋ชจ๋ฅธ์ฑ(any
๋ก ๋ ์ฑ) ์์
์ ์งํํด์์ต๋๋ค. ์ด ์์
์ด ๊ฐ์ ๋์ง ์์์ผ๋ฉฐ ๊ท์ฐฎ๊ธฐ๋ ํ์ฃ .
์ด์ ๋ ๋ฐฑ์๋์ ํ๋ก ํธ์๋๊ฐ ๋์์ ํ์ํ ์ ๋ณด๋ฅผ shared
๋ผ๋ ์๋ก์ด ๋ชจ๋์์ ์ ์ํ๊ณ ๋ฐฑ์๋์ ํ๋ก ํธ์์ shared๋ฅผ ์ฐธ์กฐํ์ฌ ์ฌ์ฉํ๊ณ ์ ํฉ๋๋ค.
shared
๋ชจ๋์ ๋ค์ ๋ ๊ฐ์ง ์ข
๋ฅ์ ํ์ผ์ ์ ์ํด ๋๋ ๊ณณ์ผ๋ก ์ฌ์ฉํฉ๋๋ค.
- ๋ฐ์ดํฐ ์ ์ก ๊ฐ์ฒด์ธ DTO -
class-validator
์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค. - ํ๋ก ํธ์๋๊ฐ ๋ฐฑ์๋๋ก๋ถํฐ ๋ฐํ๋ฐ๋ ๋ฐ์ดํฐ ( ๋ฐฑ์๋์ ํน์ ๋ผ์ฐํฐ๊ฐ ๋ฐํํ๋ ๋ฐ์ดํฐ )์ ํ์ - typescript interface 2-1. ์๋ตํ๋ ๋ฐ์ดํฐ๊ฐ ์ํฐํฐ์ ๊ด๊ณ๊ฐ ๊น์ ๊ฒฝ์ฐ, ์ด interface ๋ ๊ฐ ๋ฆฌ์์ค Entity ์์ implement ํ๋ ๋ฑ ํด๋น entity์ ๋ชจ์ฒด๋ก์ ์ฌ์ฉ ํ ์ ์์ต๋๋ค.)
- ๋ชจ๋ useAxios ์์ฒญ์์
useAxios<SomeResponseType>
์ ๊ฐ์ด generic์ผ๋ก ๋ฐํ๋ฐ๋ ๋ฐ์ดํฐ ํํ๋ฅผ ๋ช ์ํฉ๋๋ค. - ๋ชจ๋ useAxios ์์ฒญ์์ ํจ๊ป ๋ณด๋ด๋ ๋ฐ์ดํฐ (GET method ์ ๊ฒฝ์ฐ
params
, POST,PATCH,DELETE์ ๊ฒฝ์ฐdata
๊ฐ์ฒด) ํํ๋ฅผ ๋ช ์ํฉ๋๋ค. - ์์์ ๋ช
์ํ๋ ๋ชจ๋ ํ์
(DTO, interface, type)์
shared
๋ชจ๋ ์์ ๊ฐ์ ธ์ต๋๋ค.
- ์์1) shared์ Notice entity ์ ๋ชจ์ฒด๊ฐ ๋๋ interface
export interface Notice {
id: number;
category: string;
}
- ์์1-1) client์ ๋ฐ์ดํฐ ์์ฒญ์ด ํ์ํ ์ปดํฌ๋ํธ
import { Notice } from '@truepoint/shared/dist/interface/Notice.interface';
import { NoticeGetDto } from '@truepoint/shared/dist/dto/NoticeGet.dto';
export function SomeComponent() {
const dto: NoticeGetDto = { userId: 'userId1' };
const [{data, loading}] = useAxios<Notice>(
{ url: '/notice', method: 'get', params: dto }
)
return (<div>์นดํ
๊ณ ๋ฆฌ: {loading ? 'loading...' : data.category}</div>)
}
- ๋ชจ๋ POST, PATCH, PUT, DELETE ์์ฒญ ํธ๋ค๋ฌ์๋ DTO ๋ฅผ ์ ์ํ๊ณ , ValidationPipe๋ก ์์ฒญ ๋ฐ์ดํฐ์ ๋ํด ๊ฒ์ฌํฉ๋๋ค.
(GET ์์ฒญ ํธ๋ค๋ฌ์๋ DTO๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ํ์ง ์์๋ ๋ฉ๋๋ค.) - ๋ชจ๋ ๋ผ์ฐํฐ์ ์๋ต ๋ฐ์ดํฐ์ ๋ํ ํํ๋ฅผ ๋ช ์ํฉ๋๋ค. ์ฆ, controller์ ๊ฐ ๋ฉ์๋(์์ฒญ ํธ๋ค๋ฌ)์ ๋ฐํ ํ์ ์ ๋ช ์ํฉ๋๋ค.
- ๋ชจ๋ Entity ์ ์ ์, ํด๋น Entity์ ๋ชจ์ฒด๊ฐ ๋๋ interface๋ฅผ implements ํ์ฌ ์ ์ํฉ๋๋ค.
- ์์์ ๋ช
์ํ ๋ชจ๋ ํ์
(DTO, ์๋ต ๋ฐ์ดํฐ)์
shared
๋ชจ๋์์ ๊ฐ์ ธ์ต๋๋ค.
- ์์2) shared์ Notice entity ์ ๋ชจ์ฒด๊ฐ ๋๋ interface
export interface Notice {
id: number;
category: string;
}
- ์์2-1) server/resources/notice/entities/notice.entity.ts
import { Notice } from '@truepoint/shared/dist/interfaces/Notice.interface';
import {
Column, Entity, PrimaryGeneratedColumn,
} from 'typeorm';
@Entity('Notice')
export class NoticeEntity implements Notice { // shared์ Notice ์ธํฐํ์ด์ค๋ฅผ ๋ชจ์ฒด๋ก ์ฌ์ฉ.
@PrimaryGeneratedColumn()
id: number;
@Column({ comment: '๊ณต์ง์ฌํญ ๊ตฌ๋ถ' })
category: string;
}
- ์์2-2) server/resources/notice/notice.controller.ts
import { Notice } from '@truepoint/shared/dist/interfaces/Notice.interface';
import { NoticeGetDto } from '@truepoint/shared/dist/dto/NoticeGet.dto';
import { Controller, Get } from '@nestjs/common';
@Controller('notice')
export class NoticeController {
constructor(private readonly noticeService: NoticeService) {}
@Post()
async create(
@Body() dto: NoticeGetDto,
): Promise<Notice[]> {
return this.noticeService.create(dto);
}
- dto
import { SomethingDto } from '@truepoint/shared/dist/dto/Something.dto';
- ๋ฐํ ๋ฐ์ดํฐ ํ์
๋๋ entity ๋ชจ์ฒด ํ์
import { SomeResponseType } from '@truepoint/shared/dist/interfaces/Something.dto';
- Backend ์ Entity์๋ ์๋ฌด ์๊ด์๋ ํํ์ ๋ฐ์ดํฐ๋ฅผ ์๋ตํ ๋ shared/res ํด๋์ ํด๋น์๋ต์ interface๋ฅผ ์ ์ํ ํ client์ useAxios ์์ฒญ, ๋ฐฑ์๋server์ ๋ผ์ฐํธ ํธ๋ค๋ฌ ์์ ๊ฐ์ ํ์ ์ ๊ณต์
์ค์น
- ์ด์ ๊ฐ ํด๋์ server, client/web, client/admin, shared ์์ ๊ฐ๊ฐ yarn install ์ ํตํด dependencies๋ฅผ ์ค์นํ์ง ์์๋ ๋ฉ๋๋ค.
๊ฐ ํด๋ ๋๋ ์ต์์ ํด๋์์
yarn install
(yarn)์ ํ ๋ฒ๋ง ์งํํ๋ฉด ์์์ server, client/web, client/admin ๋ฑ์ dependencies๊ฐ ๋ชจ๋ ์ค์น๋ฉ๋๋ค.
์คํ
- ์คํ์ ๊ธฐ์กด๊ณผ ๊ฐ์ด server ->
yarn start:dev
, client/web ->yarn start
, client/admin ->yarn start
๋ก์งํํฉ๋๋ค. - shared ๋ ๋
๋ฆฝ์ ์ผ๋ก ์คํํ ์ผ์ ์์ต๋๋ค. ๋์ , server, client/web, client/admin์์ shared ์ ์ ์๋ DTO ๋๋ interface ๋ฑ์ ์ฐธ์กฐ ํ๋ ๊ฒฝ์ฐ, shared/dist ์ ์ปดํ์ผ๋ js ํ์ผ์ ํ์๋ก ํ๊ธฐ ๋๋ฌธ์, ๋ณ๊ฒฝ์ฌํญ์ด ์๋ ๊ฒฝ์ฐ
yarn build
๋ฅผ ํตํด ts -> js ์ปดํ์ผ์ ์งํํด์ผ ํฉ๋๋ค. ํธํ๊ฒ ๊ฐ๋ฐ ํ๊ธฐ ์ํด์๋ ๋ณ๊ฒฝ์ฌํญ์ด ์์ ๋๋ง๋ค ๋น๋๊ฐ ์งํ๋๋๋ก ํ์ฌ์ผ ํฉ๋๋ค. yarn start:dev ์คํฌ๋ฆฝํธ๋ก ๋ณ๊ฒฝ ์ฌํญ์ด ์์ ๋๋ง๋ค ์ปดํ์ผ ํ๋ ํ๊ฒฝ์ ๊ตฌ์ถํด ๋์์ต๋๋ค. - ๊ฐ๋จํ ๋งํด shared ์ญ์
yarn start:dev
๋ก ์คํํด ๋ ์ฑ ์์ ์ ์งํํ๋ ๊ฒ์ด ํธํฉ๋๋ค.
- ์ปค๋ฐ ๋จ๊ณ lint ์ ํ
husky
์lint-staged
๋ฅผ ํตํด git ์ปค๋ฐ์, ํ์ฌ staged ์ํ์ธ ํ์ผ๋ค์ ๋ํด eslint ๊ฒ์ฌํ๊ณ , ํด๋น ๊ฒ์ฌ์์ eslint๋ฅผ ํต๊ณผํ์ง ๋ชปํ๋ฉด (error ๊ฐ ํ๋๋ผ๋ ์๋ค๋ฉด) ์ปค๋ฐ์ด ์งํ๋์ง ์๋๋ก ์ ํํฉ๋๋ค. - PR ๋จ๊ณ lint ์ ํ
github actions
๋ฅผ ํตํด PR์, ๋ณ๊ฒฝํ ํ์ผ ๋ง์ ํฌํจํ๋ ๊ฒ์ด ์๋, ๊ฐ ๋ชจ๋์ ๋ชจ๋ ํ์ผ์ ๋ํด eslint ๊ฒ์ฌ ์งํํ์ฌ ๋ฏธ ํต๊ณผ ์ merge๊ฐ ๋ถ๊ฐํ๋๋ก ์ ํํฉ๋๋ค. ์์1.) server์, client/web์์ ๋ฌด์ธ๊ฐ๋ฅผ ๋ณ๊ฒฝ์ฌํญ์ด ์๋ PR์ด๋ฉด, server ํด๋์ client/web ํด๋์ ๋ชจ๋ ํ์ผ์ eslint ๊ฒ์ฌํฉ๋๋ค. ์์2.) server ์์๋ง ๋ฌด์ธ๊ฐ๋ฅผ ๋ณ๊ฒฝํ ๊ฒฝ์ฐ, server ํด๋์ ๋ชจ๋ ํ์ผ์ ๋ํด์ eslint ๊ฒ์ฌ๋ฅผ ์งํํฉ๋๋ค. - PR ๋จ๊ณ ํ
์คํธ ์ ํ ( ํฅํ ์
๋ฐ์ดํธ ์ฌํญ )
github actions
๋ฅผ ํตํด PR์, jest ๋จ์ ํ ์คํธ ์งํํ์ฌ coverage๊ฐ ํน์ ์์ค ์ดํ์ธ ๊ฒฝ์ฐ merge๊ฐ ๋ถ๊ฐํ๋๋ก ์ ํํฉ๋๋ค.