- ๋ฐฐํฌ ๋ฐ ๋๋ฉ์ธ ์ ๋ณด
- ํ๋ก์ ํธ ํ์ ๊ตฌ์กฐ
- ์๋ฒ ์ํคํ ์ณ
- ํ๋ก์ ํธ ์๊ฐ
- ์ดํ๋ฆฌ์ผ์ด์ ๋ก์ปฌ ํ๊ฒฝ ์คํ
- API ๋ช ์ธ์
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ๊ตฌ์กฐ
- ๋ฐฐํฌ
- CI / CD ํ์ดํ๋ผ์ธ
- ๋ฐฑ์๋ ๋ฐฐํฌ์ํ : ๋ฐฑ์๋ ๋งํฌ
- ํ๋ก ํธ ๋ฐฐํฌ์ํ : ํ๋ก ํธ์๋ ๋งํฌ
- ๋๋ฉ์ธ: ์ดํ๋ฆฌ์ผ์ด์ ์ HTTPS ๊ตฌ์ฑ๋ ์ฌ์ฉ์ ์ ์ ๋๋ฉ์ธ์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
-
ํ๋ก์ ํธ๋ ๋ฐฑ์๋์ ํ๋ก ํธ์๋๋ก ๋๋์ด์ ธ ๊ฐ๋ฐ๋๊ณ ์์ต๋๋ค.
-
์ด๋ ๋ฐฑ์๋์ ํ๋ก ํธ์๋๊ฐ ๋ ๋ฆฝ์ ์ผ๋ก ๊ฐ๋ฐ๋๋ฉฐ, ๊ฐ๊ฐ์ ์ญํ ๊ณผ ์ฑ ์์ ๊ฐ์ง๊ณ ํ์ ํ๊ณ ์์์ ์๋ฏธํฉ๋๋ค.
1. ๋ฐฑ์๋ (Backend)
- ๋ฐฑ์๋ ๊ฐ๋ฐ์ ๊น๋ฏผ์ง์ ์ํด ๋ด๋น๋์์ต๋๋ค.
- ๋ฐฑ์๋๋ NestJS์ TypeORM MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์ถ๋์์ต๋๋ค.
- API ์๋ํฌ์ธํธ ๋ฐ ๋ก์ง์ ๋ฐฑ์๋ GitHub ์ ์ฅ์ ๋งํฌ์์ ํ์ธํ ์ ์์ต๋๋ค.
- ๋ฐฑ์๋๋ ์๋ฒ์ ํต์ฌ ๊ธฐ๋ฅ ๋ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๋ฅผ ๋ด๋นํ๋ฉฐ, ํ๋ก ํธ์๋์์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
- API ๋ฌธ์๋ API ๋ฌธ์ ๋งํฌ์์ ํ์ธ ๊ฐ๋ฅํ๋ฉฐ, ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๊ฐ ์ด๋ฅผ ํ์ฉํ์ฌ ํ๋ก ํธ์๋ ๊ตฌํ์ ์งํํ์์ต๋๋ค.
2. ํ๋ก ํธ์๋ (Frontend)
- ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ์ด์คํ์ ์ํด ๋ด๋น๋์์ต๋๋ค.
- ํ๋ก ํธ์๋๋ Nest.js๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ๋ฐ๋๊ณ ์์ต๋๋ค.
- ํ๋ก ํธ์๋ ๊ฐ๋ฐ์๋ ๋ฐฑ์๋ API์ ์ํธ ์์ฉํ๊ณ ์ฌ์ฉ์ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ๋ฐํ๋ฉฐ, ๋ฐฑ์๋์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ๋ฅผ ์๊ฐ์ ์ผ๋ก ํํํฉ๋๋ค.
- ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ๋ํ ์์ธํ ์ ๋ณด๋ ํ๋ก ํธ์๋ GitHub ์ ์ฅ์ ๋งํฌ์์ ํ์ธํ ์ ์์ต๋๋ค.
3. ํ๋ก์ ํธ ๊ด๋ฆฌ
- ํ๋ก์ ํธ ๊ด๋ฆฌ๋ฅผ ์ํด GitHub Projects๋ฅผ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
- ์ด๋ฅผ ํตํด ์์ ํญ๋ชฉ ๋ฐ- ํ๋ก์ ํธ ์งํ ์ํฉ์ ์๊ฐ์ ์ผ๋ก ์ถ์ ํ๊ณ ์์ต๋๋ค.
- ํฐ์ผ(์ด์)๋ฅผ ์ฌ์ฉํ์ฌ ์๋ก์ด ๊ธฐ๋ฅ ๊ฐ๋ฐ, ๋ฒ๊ทธ ์์ , ์์ ๋ฑ์ ์์ ํญ๋ชฉ์ ์์ฑํ๊ณ ๊ด๋ฆฌํฉ๋๋ค.
- ์์ ํญ๋ชฉ์ GitHub Projects์ ๋ค์ํ ์ด(์นธ๋ฐ ๋ณด๋)์ ๋ฐฐ์นํ์ฌ ์์ ์ด ์งํ๋๋ ์ํ๋ฅผ ์ค์๊ฐ์ผ๋ก ํ์ธํฉ๋๋ค.
4. PR ๋ฐ ํ์
- ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ ๋๋ ๋ฒ๊ทธ ์์ ๊ณผ ๊ด๋ จ๋ ์์ ์ ๊ฐ๋ณ ๋ธ๋์น์์ ์ํ๋ฉ๋๋ค.
- PR์ ํตํด ๊ฐ๋ณ ๋ธ๋์น์์ ๋ฉ์ธ ๋ธ๋์น๋ก ๋ณ๊ฒฝ ์ฌํญ์ ๋ณํฉํฉ๋๋ค.
- ์ฝ๋ ๋ฆฌ๋ทฐ ๋ฐ ํ ๋ก ์ PR์์ ์ด๋ฃจ์ด์ง๋ฉฐ, ๋ณ๊ฒฝ ์ฌํญ์ ๋ํ ์๊ฒฌ ๋ฐ ํผ๋๋ฐฑ์ด ๊ณต์ ๋ฉ๋๋ค.
- ๋ณ๊ฒฝ ์ฌํญ์ด ์น์ธ๋๋ฉด ํด๋น PR์ด ๋ฉ์ธ ๋ธ๋์น๋ก ๋ณํฉ๋๊ณ , ํด๋น ์์ ํญ๋ชฉ์ ๋ํ ํฐ์ผ์ด ๋ซํ๋๋ค.
-
์ด๋ฌํ ํ์ ํ๋ก์ธ์ค์ ์์ฌ ์ํต ๋ฐฉ๋ฒ์ ๋ช ์ํ๋ฉด์ ํ๋ก์ ํธ์ ํ์ ํ๊ฒฝ์ ์ดํดํ๊ณ ๊ฐ๋ฐ์ ๊ฐ์ ์ํํ ํ์ ์ ์ด์งํ ์ ์์์ต๋๋ค.
-
WalkDi์ ๋ฐฑ์๋๋ NestJS๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌ์ถ๋์์ต๋๋ค.
-
Planet Scale์์ ํธ์คํ ๋๋ MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํ์ฉํฉ๋๋ค.
-
WalkDi์ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ Planet Scale์์ ํธ์คํ ๋๋ฉฐ, ๋ค์ํ Entity์ ๋ฐ๋ผ ์คํค๋ง๊ฐ ๊ตฌ์ฑ๋ฉ๋๋ค. ์คํค๋ง๋ ํ ์ด๋ธ, ์ปฌ๋ผ ๋ฐ ๊ด๊ณ๋ฅผ ์ ์ํ๊ณ , ๋ฐ์ดํฐ์ ๊ตฌ์กฐ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค.
-
์๋๋ ์ฃผ์ ์ปดํฌ๋ํธ์ ๋ชจ๋ ๊ตฌ์ฑ์ ๋๋ค.
1. User Module
- User Module : ์ฌ์ฉ์ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํ๋ ๋ชจ๋์ ๋๋ค.
- User Entity : ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๋ํ๋ด๋ Entity๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ฌ์ฉ์ ํ ์ด๋ธ๊ณผ ์ฐ๊ฒฐ๋ฉ๋๋ค.
- User Controller : ์ฌ์ฉ์์ ๊ด๋ จ๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ปจํธ๋กค๋ฌ์ ๋๋ค.
- User Service : ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์กฐํ, ์์ฑ, ์์ ๋ฐ ์ญ์ ํ๋ ๋ก์ง์ ์ฒ๋ฆฌํ๋ ์๋น์ค์ ๋๋ค.
- User DTO : ์ฌ์ฉ์ ๋ฐ์ดํฐ ์ ์ก ๊ฐ์ฒด๋ก, ํด๋ผ์ด์ธํธ์ ์๋ฒ ๊ฐ ๋ฐ์ดํฐ ๊ตํ์ ์ฌ์ฉ๋ฉ๋๋ค.
2. Auth Module
- Auth Module : ์ธ์ฆ๊ณผ ๊ด๋ จ๋ ๋ชจ๋์ ๋๋ค.
- Auth Decorators : ์ธ์ฆ ๊ด๋ จ ๋ฐ์ฝ๋ ์ดํฐ๋ก, ์์ธ์ค ํ ํฐ, ๋ฆฌํ๋ ์ ํ ํฐ, ์ญํ (Role)๋ฑ์ ๊ด๋ฆฌํฉ๋๋ค.
- Auth Guards : ์ธ์ฆ๋ ์ฌ์ฉ์์ ์๋ํฌ์ธํธ ์ก์ธ์ค๋ฅผ ์ ์ดํ๋ ๊ฐ๋๋ก, ์ญํ (Role) ๋ฐ๊ถํ์ ๋ฐ๋ฅธ ์ก์ธ์ค ์ ํ์ด ๊ฐ๋ฅํฉ๋๋ค.
- Auth Strategies : ์ธ์ฆ ์ ๋ต์ผ๋ก, GitHub ๋ก๊ทธ์ธ๊ณผ ๊ฐ์ ๋ค์ํ ๋ก๊ทธ์ธ ์ ๋ต์ ๊ตฌํํฉ๋๋ค.
- Auth Controller : ์ธ์ฆ ๊ด๋ จ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ปจํธ๋กค๋ฌ์ ๋๋ค.
- Auth Service : ์ฌ์ฉ์ ๋ก๊ทธ์ธ, ํ์๊ฐ์
๋ฐ ์ธ์ฆ์ ๊ดํ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.
3. Article Module
- Article Module : ๊ธฐ์ฌ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํ๋ ๋ชจ๋์ ๋๋ค.
- Article Entity : ๊ธฐ์ฌ ์ ๋ณด๋ฅผ ๋ํ๋ด๋ Entity๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ธฐ์ฌ ํ ์ด๋ธ๊ณผ ์ฐ๊ฒฐ๋ฉ๋๋ค.
- Article Controller : ๊ธฐ์ฌ์ ๊ด๋ จ๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ปจํธ๋กค๋ฌ์ ๋๋ค.
- Article Service : ๊ธฐ์ฌ ์์ฑ, ์กฐํ, ์์ ๋ฐ ์ญ์ ์ ๊ด๋ จ๋ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.
4. Category Module
- Category Module : ์นดํ ๊ณ ๋ฆฌ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํ๋ ๋ชจ๋์ ๋๋ค.
- Category Entity : ์นดํ ๊ณ ๋ฆฌ ์ ๋ณด๋ฅผ ๋ํ๋ด๋ Entity๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์นดํ ๊ณ ๋ฆฌ ํ ์ด๋ธ๊ณผ ์ฐ๊ฒฐ๋ฉ๋๋ค.
- Category Controller : ์นดํ ๊ณ ๋ฆฌ์ ๊ด๋ จ๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ปจํธ๋กค๋ฌ์ ๋๋ค.
- Category Service : ์นดํ ๊ณ ๋ฆฌ ์์ฑ, ์กฐํ, ์์ ๋ฐ ์ญ์ ์ ๊ด๋ จ๋ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.
5. Comment Module
- Comment Module : ๋๊ธ ๊ด๋ฆฌ๋ฅผ ๋ด๋นํ๋ ๋ชจ๋์ ๋๋ค.
- Comment Entity : ๋๊ธ ์ ๋ณด๋ฅผ ๋ํ๋ด๋ Entity๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋๊ธ ํ ์ด๋ธ๊ณผ ์ฐ๊ฒฐ๋ฉ๋๋ค.
- Comment Controller : ๋๊ธ๊ณผ ๊ด๋ จ๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ปจํธ๋กค๋ฌ์ ๋๋ค.
- Comment Service : ๋๊ธ ์์ฑ, ์กฐํ, ์์ ๋ฐ ์ญ์ ์ ๊ด๋ จ๋ ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.
6. Mail Module
- Mail Module : ๋ก๊ทธ์ธ ๋ฐ ํ์๊ฐ์ ๊ณผ ๊ฐ์ ์ฌ์ฉ์ ์ธ์ฆ ํ๋ก์ธ์ค๋ฅผ ์ํ ๋ฉ์ผ ์๋น์ค๋ฅผ ๊ด๋ฆฌํ๋ ๋ชจ๋์ ๋๋ค.
- Mail Service : ์ด ๋ชจ๋์ ๋ฉ์ผ ์ ์ก ๋ฐ ๊ด๋ฆฌ์ ๊ด๋ จ๋ ๋ชจ๋ ๋ก์ง์ ์ฒ๋ฆฌํฉ๋๋ค.
- Mail Controller : ๋ฉ์ผ๊ณผ ๊ด๋ จ๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ปจํธ๋กค๋ฌ์ ๋๋ค.
7. Search Module
- Search Module : ๊ฒ์ ๊ธฐ๋ฅ์ ๊ด๋ฆฌํ๋ ๋ชจ๋๋ก, ์ฌ์ฉ์๊ฐ ๊ธฐ์ฌ, ์ฌ์ฉ์, ๋๊ธ ๋ฑ์ ๊ฒ์ํ ์ ์๋๋ก ํด์ค๋๋ค.
- Search Controller : ๊ฒ์ ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ์ ์ ํ ์๋น์ค๋ก ๋ผ์ฐํ ํ๋ ์ปจํธ๋กค๋ฌ์ ๋๋ค.
- Search Service : ์ค์ ๊ฒ์ ๋ก์ง์ ์ฒ๋ฆฌํ๋ ์๋น์ค๋ก, ๊ฒ์์ด์ ๋ฐ๋ผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ ์ ํ ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ํ๊ณ ๋ฐํํฉ๋๋ค.
8. Tag Module
- Tag Module : ๊ธฐ์ฌ๋ ์ฌ์ฉ์ ํ๋กํ๊ณผ ๊ฐ์ ์ฝํ ์ธ ์ ํ๊ทธ๋ฅผ ๋ถ์ฌํ๊ณ ๊ด๋ฆฌํ๋ ๋ชจ๋์ ๋๋ค.
- Tag Entity : ํ๊ทธ ์ ๋ณด๋ฅผ ๋ํ๋ด๋ Entity๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ๊ทธ ํ ์ด๋ธ๊ณผ ์ฐ๊ฒฐ๋ฉ๋๋ค.
- Tag Controller : ํ๊ทธ์ ๊ด๋ จ๋ ์์ฒญ์ ์ฒ๋ฆฌํ๋ ์ปจํธ๋กค๋ฌ์ ๋๋ค.
- Tag Service : ํ๊ทธ ์์ฑ, ์์ , ์ญ์ , ์กฐํ์ ๊ด๋ จ๋ ๋ก์ง์ ์ฒ๋ฆฌํ๋ ์๋น์ค์ ๋๋ค.
WalkDi๋์ !
์ฌ์ฉ์๋ค์๊ฒ ๋ ๋์ ๊ฑด๊ฐ๊ณผ ์ถ์ ์ง์ ์ ๊ณตํ๋ ํ์ ์ ์ธ ํ๋ซํผ์ ๋๋ค. WalkDi๋ ๋ค์๊ณผ ๊ฐ์ ์ฃผ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ ์ฌ์ฉ์๋ค์ ๊ฑด๊ฐ๊ณผ ํ๋์ ์ฆ์ง์ํค๊ณ ์ํต์ ์ด์งํฉ๋๋ค.
-
๋ก๊ทธ์ธ ๋ฐ ํ์๊ฐ์ : ์ฌ์ฉ์๋ค์ ์์ ํ๊ฒ ๋ก๊ทธ์ธํ๊ณ ํ์๊ฐ์ ํ์ฌ WalkDi์ ๊ธฐ๋ฅ์ ํ์ฉํ ์ ์์ต๋๋ค.
-
๋์ Article ์์ฑ : ์ฌ์ฉ์๋ค์ ์์ ๋ง์ ๊ณต๊ฐ์์ ๋ค์ํ ์ฃผ์ ๋ก ๊ธ์ ์์ฑํ๊ณ ๊ณต์ ํ ์ ์์ต๋๋ค. ์์ ๋ก์ด ๊ธ ์์ฑ ํ๊ฒฝ์ ์ ๊ณตํ์ฌ ๋ค์ํ ์ด์ผ๊ธฐ๋ฅผ ๋๋ ์ ์์ต๋๋ค.
-
ํด์ํ๊ทธ ๊ธฐ๋ฅ : ๊ฒ์๋ฌผ์ ํด์ํ๊ทธ๋ฅผ ์ถ๊ฐํ์ฌ ๊ฒ์๋ฌผ์ ์นดํ ๊ณ ๋ฆฌํํ๊ณ ๊ฒ์ ๊ฐ๋ฅํ๊ฒ ๋ง๋ญ๋๋ค. ์ด๋ฅผ ํตํด ์ฌ์ฉ์๋ค์ ๊ด์ฌ ์๋ ์ฃผ์ ๋ฅผ ์ฝ๊ฒ ์ฐพ์๋ณผ ์ ์์ต๋๋ค.
-
Article ๊ฒ์ ๊ธฐ๋ฅ : ํค์๋๋ฅผ ์ด์ฉํด์ ๋ค์ํ ์ฃผ์ ์ ์ ๋ณด๋ฅผ ์ ๊ณตํ๋ ๊ฒ์๋ฌผ์ ์์ฝ๊ฒ ์ฐพ์๋ณด๋ ๊ฒ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
-
docker ํ๊ฒฝ์ ๋ค์ด๋ฐ์ docker๋ก mysql์ ์ฌ์ฉํ๊ฑฐ๋ local mysql์ ์ฌ์ฉํฉ๋๋ค.
-
git clone
git clone https://github.com/everydaycono/walking-distance
-
.env.dev ํ์ผ ์์ฑ
touch .env.dev
-
.env.dev ํ์ผ ๊ตฌ์ฑ ์์
NODE_ENV=dev PORT = 8000 # JWT ENV ########### JWT_SECRET=JWT_SECRET JWT_REFRESH_SECRET=JWT_REFRESH_SECRET # APP CONFIG ########### SERVER_API_URL=http://localhost:8000/api # APP CONFIG ## MAIL ENV START ########### SMTP_MAIL_SERVICE_HOST=SMTP_MAIL_SERVICE_HOST SMTP_MAIL_SERVICE_USER=SMTP_MAIL_SERVICE_USER SMTP_MAIL_SERVICE_PASS=SMTP_MAIL_SERVICE_PASS SMTP_MAIL_SERVICE_FROM='"No Reply" <noreply@example.com>' # SOCIAL LOGIN ############## GITHUB_SOCIAL_LOGIN_CLIENT_ID= GITHUB_SOCIAL_LOGIN_SECRET= GITHUB_SOCIAL_LOGIN_CALLBACK_URL= # ENV FILE ####### AWS_BUCKET_NAME=AWS_BUCKET_NAME ACCESS_ID=ACCESS_ID AWS_SECRET_KEY=AWS_SECRET_KEY # DB CONFIG DB_HOST=localhost DB_PORT=3306 DB_USERNAME=username DB_PASSWORD=wdpassword DB_NAME=walkdi
-
docker compose ํ์ผ up ์์ผ์ mysql ์๋ฒ ์์ฑํด์ ์ฐ๊ฒฐ
docker compose up -f docker-compose.dev.yml -d
-
์๋ฒ ์์ ์ํค๊ธฐ
yarn & yarn start:dev or npm i & npm run start:dev
- 1. create user
-
End point:
POST /api/auth/register
-
Request
{ "email": "test@gmail.com", "password": "password", "firstName": "firstName", "lastName": "lastName" }
-
Success Response
- 201 Created => ์ ์ ์ฑ๊ณต์ ์ผ๋ก ์์ฑ, ์ ์ ์์ฑํ๋ค๋ ๋ฌธ๊ตฌ ๋ฐํ
-
Error Response
- 400 Bad Request => ์์ฒญ์ด ์๋ชป or ํ์ ์ ๋ณด ๋๋ฝ or ์ ํจ์ฑ ๊ฒ์ฌ ํ๋ฝ
- 409 Conflict Error => ์ด๋ฏธ ์กด์ฌํ๋ ์ ์ ์๋ฌ
-
- 2. login user
- End point:
POST /api/auth/login
- Request
{ "email": "test@gmail.com", "password": "password" }
- Success Response
- 200 OK
- Error Response
- 400 Bad Request => ์์ฒญ์ด ์๋ชป or ํ์ ์ ๋ณด ๋๋ฝ or ์ ํจ์ฑ ๊ฒ์ฌ ํ๋ฝ
- 401 Unauthorized Error => username์ด๋ password๊ฐ ์ผ์นํ์ง ์์๋
- 403 Forbidden Error => account๊ฐ locked์ผ๋ ์๋ฌ
- End point:
- 3. social login user
- End point:
POST /api/auth/social-login
- Success Response
- 200 OK => github login ์ ์ ์ ๋ณด ๋ฐํ
- Error Response
- 500 Intenal server errror
- End point:
- 1. get my all articles
- End point:
GET /api/user/my/articles
- Authorization - JWT accessToken ํ์
- Success Response
- 200 OK => my articles ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์ฑ๊ณต
- Error Response
- 401 Unauthorized => ์ธ์ฆ ๊ถํ ์คํจ
- End point:
- 2. get other person articles
- End point:
GET /api/user/{userId}/articles
- Authorization - JWT accessToken ํ์
- required parameter - userId ํ์
- Success Response
- 200 OK => other person's articles ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์ฑ๊ณต
- Error Response
- 401 Unauthorized => ์ธ์ฆ ๊ถํ ์คํจ
- End point:
- 1. create article
- End point:
POST /api/article
- Authorization - JWT accessToken ํ์
- Success Response
- 201 CREATED => article ์์ฑ ์ฑ๊ณต
- Error Response
- 401 Unauthorized => ๊ถํ ์ธ์ฆ ์คํจ
- 400 Bad Request => ํ์ ์ ๋ ฅ ๋ชฉ๋ก ์คํจ
- End point:
- 2. get other person articles
- End point:
GET /api/article
- required parameter - userId ํ์
- Success Response
- 200 OK => other person's articles ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์ฑ๊ณต
- Error Response
- 400 Bad Request => status์ ๋ฐ๋ฅธ ๊ฒฐ๊ณผ๊ฐ์ด ์์๋ ์๋ฌ
- End point:
- 2. get single article
- End point:
GET /api/article/{id}
- required parameter - articleID ํ์
- Success Response
- 200 OK => single articles ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์ฑ๊ณต
- Error Response
- 400 Bad Request => article id์ ๋ฐ๋ฅธ ๊ฒ์๋ฌผ์ ๋ชป ์ฐพ์์๋
- End point:
- 2. edit single article
- End point:
PATCH /api/article/{id}
- Authorization - JWT accessToken ํ์
- required parameter - articleID ํ์
- Success Response
- 200 OK => single articles ๋ฐ์ดํฐ ๊ฐ์ ธ์ค๊ธฐ ์ฑ๊ณต
- Error Response
- 404 Not Fount => article id์ ๋ฐ๋ฅธ ๊ฒ์๋ฌผ์ ๋ชป ์ฐพ์์๋
- 401 Unauthorized => ๊ถํ ์ธ์ฆ ์คํจ
- End point:
- 2. delete single article
- End point:
DELETE /api/article/{id}
- Authorization - JWT accessToken ํ์
- required parameter - articleID ํ์
- Success Response
- 200 OK => article ์ญ์ ์ฑ๊ณต
- Error Response
- 404 Not Fount => article id์ ๋ฐ๋ฅธ ๊ฒ์๋ฌผ์ ๋ชป ์ฐพ์์๋
- 401 Unauthorized => ๊ถํ ์ธ์ฆ ์คํจ
- End point:
- 1. get all category
- End point:
GET /api/category
- Success Response
- 200 OK => ๋ชจ๋ category ๋ถ๋ฌ์ค๊ธฐ ์ฑ๊ณต
- End point:
- 2. get single category
- End point:
GET /api/category/{label}
- required parameter : label
- Success Response
- 200 OK => label๋ณ๋ก category ๋ถ๋ฌ์ค๊ธฐ ์ฑ๊ณต
- Error Response
- 404 Not Fount => article label์ 8000 ๋ชป ๋ถ๋ฌ์์๋
- End point:
- 1. find all tags
- End point:
GET /api/tag
- option parameter : ?label={label} ์ต์ ์ผ๋ก ์ ๋ณด ์ ๊ณต
- Success Response
- 200 OK => ๋ชจ๋ tags ๋ถ๋ฌ์ค๊ธฐ ์ฑ๊ณต
- End point:
- 2. find single tag
- End point:
GET /api/tag/{id}
- required parameter : tagId
- Success Response
- 200 OK => single tag ๋ถ๋ฌ์ค๊ธฐ ์ฑ๊ณต
- Error Response
- 400 Not Fount => article tag๋ฅผ ๋ชป ๋ถ๋ฌ์์๋
- End point:
- 1. create comment
- End point:
POST /api/comment/{articleId}
- Authorization - JWT accessToken ํ์
- required parameter - articleId ํ์
- Success Response
- 201 CREATED => comment ์์ฑ ์ฑ๊ณต
- Error Response
- 401 Unauthorized => ๊ถํ ์ธ์ฆ ์คํจ
- 400 Bad Request => ํ์ ์ ๋ ฅ ๋ชฉ๋ก ์คํจ
- End point:
- 2. Find all comments by article
- End point:
GET /api/comment/article/{articleId}
- required parameter - articleId ํ์
- Success Response
- 200 OK => ํด๋น article์ ๋ํ all comments ๋ถ๋ฌ์ค๊ธฐ ์ฑ๊ณต
- End point:
- 3. Find comment by id
- End point:
GET /api/comment/{commentId}
- required parameter - commentId ํ์
- Success Response
- 200 OK => single commnet ๋ถ๋ฌ์ค๊ธฐ ์ฑ๊ณต
- End point:
- 4. edit single comment
- End point:
PATCH /api/comment/{commentId}
- Authorization - JWT accessToken ํ์
- required parameter - commentId ํ์
- Success Response
- 200 OK => single comment ์ ๋ฐ์ดํธ ์ฑ๊ณต
- Error Response
- 403 Forbidden => ์ ์ ๊ฐ ๋๊ธ์ ์์ฑ์๊ฐ ์๋๋ ์๋ฌ
- 401 Unauthorized => ๊ถํ ์ธ์ฆ ์คํจ
- 400 Bad Request => comment update ์๋ฌ
- End point:
- 5. delete single comment
- End point:
DELETE /api/comment/{commentId}
- Authorization - JWT accessToken ํ์
- required parameter - articleID ํ์
- Success Response
- 200 OK => comment ์ญ์ ์ฑ๊ณต
- Error Response
- 404 Not Found => comment ์ฐพ์ ์ ์์ ๋
- 403 Forbidden => ์ ์ ๊ฐ ๋๊ธ์ ์์ฑ์๊ฐ ์๋๋ ์๋ฌ
- 401 Unauthorized => ๊ถํ ์ธ์ฆ ์คํจ
- End point:
- 1. search article by title or content
- End point:
GET /api/search/article
- required parameter - ?keyword=title&keyword=content
- Success Response
- 200 OK => title์ด๋ content keyword๊ฐ ๋ค์ด์๋ article ๊ฒ์ ์ฑ๊ณต
- End point:
- 2. search article by category
- End point:
GET /api/search/article/category
- required parameter - ?label=hobby
- Success Response
- 200 OK => label์ ๋ฐ๋ฅธ category ๊ฒ์ ์ฑ๊ณต
- Error Response
- 404 Not Found => ํด๋น label์ category๋ฅผ ์ฐพ์ ์ ์์๋
- End point:
- 2. search article by tag
- End point:
GET /api/search/article/tag
- required parameter - ?label=hobby
- Success Response
- 200 OK => label์ ๋ฐ๋ฅธ tag ๊ฒ์ ์ฑ๊ณต
- Error Response
- 400 Bad Reuqest => ํด๋น label์ tag ์ฐพ์ ์ ์์๋
- End point:
1. Article Entity
- id: ๊ณ ์ ํ ์์ด๋ (UUID)๋ก ๊ธฐ๋ณธ ํค
- title: ๊ธ์ ์ ๋ชฉ์ ๋ํ๋ด๋ ๋ฌธ์์ด
- content: ๊ธ์ ๋ด์ฉ์ ๋ํ๋ด๋ ์ค๋ํ ํ ์คํธ
- thumbnail: ๊ธ์ ์ฒจ๋ถ๋ ์ธ๋ค์ผ ์ด๋ฏธ์ง ๊ฒฝ๋ก๋ฅผ ๋ํ๋ด๋ ๋ฌธ์์ด
- status:
- ๊ธ์ ์ํ๋ฅผ ๋ํ๋ด๋ ๋ฌธ์์ด (draft, publish, onlyme ์ค ํ๋)
- ๊ธฐ๋ณธ๊ฐ์ draft
- views: ๊ธ์ ์กฐํ์๋ฅผ ๋ํ๋ด๋ ์ ์, ๊ธฐ๋ณธ๊ฐ์ 0
- likes: ๊ธ์ ์ข์์ ์๋ฅผ ๋ํ๋ด๋ ์ ์, ๊ธฐ๋ณธ๊ฐ์ 0
- category:
- ๊ธ์ด ์ํ ์นดํ ๊ณ ๋ฆฌ๋ฅผ ๋ํ๋ด๋ ์ธ๋ ํค
- Category ์ํฐํฐ์์ ๊ด๊ณ ์ค์
- tags: ๊ธ์ ๋ถ์ฌ๋ ํ๊ทธ ๋ชฉ๋ก. Tag ์ํฐํฐ์ ๋ค๋๋ค ๊ด๊ณ ์ค์
- isRecommended: ๊ธ์ ์ถ์ฒํ๋์ง ์ฌ๋ถ๋ฅผ ๋ํ๋ด๋ ๋ถ์ธ ๊ฐ, ๊ธฐ๋ณธ๊ฐ์ false
- createAt: ๊ธ์ ์์ฑ ์๊ฐ์ ๋ํ๋ด๋ ๋ ์ง ๋ฐ ์๊ฐ ์ ๋ณด
- updateAt: ๊ธ์ ์ต๊ทผ ์์ ์๊ฐ์ ๋ํ๋ด๋ ๋ ์ง ๋ฐ ์๊ฐ ์ ๋ณด
- comments: ๊ธ์ ๋ฌ๋ฆฐ ๋๊ธ ๋ชฉ๋ก. Comment ์ํฐํฐ์ ์ผ๋๋ค ๊ด๊ณ ์ค์
- user:
- ๊ธ์ ์์ฑํ ์ฌ์ฉ์ ์ ๋ณด
- User ์ํฐํฐ์์ ๊ด๊ณ ์ค์
2. Category Entity
- id: ๊ณ ์ ํ ์์ด๋ (UUID)๋ก ๊ธฐ๋ณธ ํค
- label: ์นดํ ๊ณ ๋ฆฌ์ ๋ ์ด๋ธ์ ๋ํ๋ด๋ ๋ฌธ์์ด
- articles: ํด๋น ์นดํ ๊ณ ๋ฆฌ์ ์ํ ๊ธ ๋ชฉ๋ก, Article ์ํฐํฐ์์ ์ผ๋๋ค ๊ด๊ณ ์ค์
- createAt: ์นดํ ๊ณ ๋ฆฌ์ ์์ฑ ์๊ฐ์ ๋ํ๋ด๋ ๋ ์ง ๋ฐ ์๊ฐ ์ ๋ณด
- updateAt: ์นดํ ๊ณ ๋ฆฌ์ ์ต๊ทผ ์์ ์๊ฐ์ ๋ํ๋ด๋ ๋ ์ง ๋ฐ ์๊ฐ ์ ๋ณด
3. Comment Entity
- id: ๊ณ ์ ํ ์์ด๋ (autoincrement)๋ก ๊ธฐ๋ณธ ํค
- content: ๋๊ธ ๋ด์ฉ์ ๋ํ๋ด๋ ๋ฌธ์์ด
- createAt: ๋๊ธ์ ์์ฑ ์๊ฐ์ ๋ํ๋ด๋ ๋ ์ง ๋ฐ ์๊ฐ ์ ๋ณด
- updateAt: ๋๊ธ์ ์ต๊ทผ ์์ ์๊ฐ์ ๋ํ๋ด๋ ๋ ์ง ๋ฐ ์๊ฐ ์ ๋ณด
- pass: ๋๊ธ์ ์ํ๋ฅผ ๋ํ๋ด๋ ๋ถ์ธ ๊ฐ (true ๋๋ false), ๊ธฐ๋ณธ๊ฐ์ true
- user: ๋๊ธ์ ์์ฑํ ์ฌ์ฉ์ ์ ๋ณด, User ์ํฐํฐ์์ ๊ด๊ณ ์ค์
- article: ๋๊ธ์ด ์ํ ๊ธ ์ ๋ณด, Article ์ํฐํฐ์์ ๊ด๊ณ ์ค์
- parent: ๋๊ธ์ ๋ถ๋ชจ ๋๊ธ ์ ๋ณด (์๊ธฐ ์ฐธ์กฐ ๊ด๊ณ), Comment ์ํฐํฐ์์ ๊ด๊ณ ์ค์
- children: ๋๊ธ์ ์์ ๋๊ธ ๋ชฉ๋ก (์๊ธฐ ์ฐธ์กฐ ๊ด๊ณ), Comment ์ํฐํฐ์์ ๊ด๊ณ ์ค์
4. Tag Entity
- id: ๊ณ ์ ํ ์์ด๋ (UUID)๋ก ๊ธฐ๋ณธ ํค
- label: ํ๊ทธ์ ๋ ์ด๋ธ์ ๋ํ๋ด๋ ๋ฌธ์์ด
- articles: ํด๋น ํ๊ทธ์ ์ฐ๊ฒฐ๋ ๊ธ ๋ชฉ๋ก, Article ์ํฐํฐ์์ ๋ค๋๋ค ๊ด๊ณ ์ค์
- createAt: ํ๊ทธ์ ์์ฑ ์๊ฐ์ ๋ํ๋ด๋ ๋ ์ง ๋ฐ ์๊ฐ ์ ๋ณด
- updateAt: ํ๊ทธ์ ์ต๊ทผ ์์ ์๊ฐ์ ๋ํ๋ด๋ ๋ ์ง ๋ฐ ์๊ฐ ์ ๋ณด
5. User Entity
- id: ๊ณ ์ ํ ์์ด๋ (UUID)๋ก ๊ธฐ๋ณธ ํค
- firstName: ์ฌ์ฉ์์ ์ด๋ฆ์ ๋ํ๋ด๋ ๋ฌธ์์ด
- ํ๋ก์ ํธ๋ฅผ PlanetScale MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค์ Digital Ocean Ubuntu ์๋ฒ์ ๋ฐฐํฌํ์ต๋๋ค.
-
PlanetScale MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค์
- PlanetScale์ ๊ณ์ ์ ์์ฑํ๊ณ , MySQL ๋ฐ์ดํฐ๋ฒ ์ด์ค ํด๋ฌ์คํฐ๋ฅผ ์ค์ ํฉ๋๋ค.
- ํด๋ฌ์คํฐ ์ฐ๊ฒฐ ์ ๋ณด๋ฅผ ํ๋ํ๊ณ , ํ๊ฒฝ ๋ณ์ ๋๋ ์ค์ ํ์ผ์ ์ ์ฅํฉ๋๋ค.
-
Digital Ocean ์๋ฒ ์ค์
- Digital Ocean์ ๊ณ์ ์ ์์ฑํ๊ณ , Ubuntu ์๋ฒ๋ฅผ ์์ฑํฉ๋๋ค.
- ์๋ฒ์ SSH๋ก ์ ์ํ๊ณ ํ์ํ ์ํํธ์จ์ด๋ฅผ ์ค์นํฉ๋๋ค.
-
ํ๋ก์ ํธ ์ฝ๋ ๋ฐฐํฌ
- ํ๋ก์ ํธ ์ฝ๋๋ฅผ ์๋ฒ๋ก ๋ณต์ ํฉ๋๋ค.
- ํ๊ฒฝ ๋ณ์ ์ค์ : ํ๋ก์ ํธ์์ ์ฌ์ฉํ๋ ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํฉ๋๋ค.
- .env ํ์ผ์ ๋ง๋ค์ด ์ ์ฅํฉ๋๋ค.
-
Docker์ Docker Compose ์ค์น
- ์๋ฒ์ Docker์ Docker Compose๋ฅผ ์ค์นํฉ๋๋ค.
-
Nginx ์ค์
- Nginx๋ฅผ ์ค์นํ๊ณ ์ค์ ํ์ผ์ ์์ ํ์ฌ ๋ฐฑ์๋ ์๋ฒ๋ก์ ์์ฒญ์ ํ๋ก์ํฉ๋๋ค.
-
๋๋ฉ์ธ ๋ฐ SSL ์ค์ (์ต์ )
- ๋๋ฉ์ธ์ ๊ตฌ๋งคํ๊ณ DNS ์ค์ ์ ์ ๋ฐ์ดํธํ์ฌ ์๋ฒ์ ์ฐ๊ฒฐํฉ๋๋ค.
- Let's Encrypt ์ธ์ฆ์๋ฅผ ์ฌ์ฉํ์ฌ SSL์ ํ์ฑํ ํ์ต๋๋ค.
-
Docker Compose๋ก ์๋น์ค ์คํ
- ํ๋ก์ ํธ ๋ฃจํธ ๋๋ ํ ๋ฆฌ์์ docker-compose.yml ํ์ผ์ ์ฌ์ฉํ์ฌ ์๋น์ค๋ฅผ ์์ํฉ๋๋ค.
docker-compose up -d
- ํ๋ก์ ํธ๋ CI/CD ํ์ดํ๋ผ์ธ์ ํตํด ์ง์์ ์ธ ํตํฉ๊ณผ ๋ฐฐํฌ๋ฅผ ์ํํฉ๋๋ค. ์ด ํ์ดํ๋ผ์ธ์ ์์ค ์ฝ๋ ๋ณ๊ฒฝ ์ฌํญ์ ์๋์ผ๋ก ํ ์คํธํ๊ณ ๋ฐฐํฌํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
- CI (Continuous Integration)
- ๋ชจ๋ ์ฝ๋ ๋ณ๊ฒฝ ์ฌํญ์ CI ์๋ฒ์์ ์๋์ผ๋ก ๋น๋ ๋ฐ ํ ์คํธ๋ฉ๋๋ค.
- CI ํ์ดํ๋ผ์ธ์ ์ฝ๋ ํ์ง, ํ ์คํธ ์ปค๋ฒ๋ฆฌ์ง ๋ฑ์ ๊ฒ์ฌํ๊ณ ์ด์์ด ๊ฐ์ง๋๋ฉด ๋น๋๋ฅผ ์ค๋จํ๊ณ ํต์งํฉ๋๋ค.
- GitHub Actions๋ฅผ ์ฌ์ฉํ์ฌ CI๋ฅผ ์ค์ ํ์์ผ๋ฉฐ, .github/workflows ๋๋ ํ ๋ฆฌ์์ ๊ด๋ จ ์ํฌํ๋ก์ฐ ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค.
- CD (Continuous Deployment)
- ์ฝ๋๊ฐ CI๋ฅผ ํต๊ณผํ๊ณ ๋ฉ์ธ ๋ธ๋์น์ ๋ณํฉ๋๋ฉด CD ํ์ดํ๋ผ์ธ์ด ์๋์ผ๋ก ๋ฐฐํฌ ์์ ์ ์์ํฉ๋๋ค.
- ํ๋ก ํธ์๋์ ๋ฐฑ์๋ ๋ชจ๋ ์๋ ๋ฐฐํฌ๊ฐ ๊ตฌ์ฑ๋์ด ์์ผ๋ฉฐ, ์ค์ ์๋ฒ์ ์๋์ผ๋ก ๋ฐฐํฌ๋ฉ๋๋ค.
- Docker ์ปจํ ์ด๋๋ฅผ ์ฌ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ ํจํค์งํ๊ณ , Nginx ๋๋ ๋ค๋ฅธ ์น ์๋ฒ๋ฅผ ์ฌ์ฉํ์ฌ ๋ฐฐํฌ ์๋ฒ์์ ํธ์คํ ํฉ๋๋ค.