ํ์์ผ๋ก ์ํตํ๋ ๋ธ๋ก๊ทธ ํ๋ซํผ
์์ ์ ์๊ฐ์ ๊ธ๋ก ์ ์ด๋ณด์์.
๊ณต๊ฐ ๊ฐ๋ ๊ธ์ ์ฝ๊ณ ๋ธ๋ก๊ฑฐ ์ฃผ์ธ๊ณผ ์ํตํ๊ณ ์ถ๋์?
๋์ ์๊ฐ์ ๊ณต์ ํด ๋๋ญ์์ ๋ชจ์ผ๊ณ ๋๊ธ๋ฟ๋ง ์๋๋ผ ํ์์ฑํ ์ผ๋ก ์ํตํ ์ ์์ต๋๋ค.
์์ ๋ง์ ์ด์ผ๊ธฐ๋ก ์ํตํ ์ ์๋ ๋ธ๋ก๊ทธ PAPER
- 2022.06.24 - 2022.08.06
-
๋ฐฑ์๋ ์น ์ดํ๋ฆฌ์ผ์ด์ ์๋ฒ๋ Node.js์ Express๋ก ๊ตฌ์ถ
-
Nginx์ SSL์ธ์ฆ์ ๋์ ํด WebRTC ์ค์๊ฐ ํ์ ํตํ ๊ตฌํ ๋ฐ ๋ฆฌ๋ฒ์ค ํ๋ก์ ์ค์ ์ ํตํด ๋ฐฑ์๋ ์๋ฒ์ ์ง์ ์ ์ธ ์ ๊ทผ์ ์ฐจ๋จํ์ฌ ๋ณด์ ๊ฐํ
-
๊นํ๋ธ ์ก์ CI-CD๋ฅผ ํตํด Docker Image๋ฅผ ๋น๋ํ์ฌ ๋์ผํ ๊ฐ๋ฐ ํ๊ฒฝ์ผ๋ก ์๋ํ ๋ฐฐํฌ
-
๊ธฐ๋ณธ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ์ ๋ณด์ฅํ๊ธฐ ์ํด RDS์ Mysql์ ORM์ธ Sequelize ์ฌ์ฉ
-
์ธ๋ฉ๋ชจ๋ฆฌ ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ ์ฅ์์ธ Redis์๋ I/O์ด ๋น๋ฒํ๊ฑฐ๋ ์ผํ์ฑ์ธ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ์ฌ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์๋๋ฅผ ํฌ๊ฒ ๊ฐ์
-
์ด๋ฏธ์ง ๋ฐ์ดํฐ๋ Multer ๋ฏธ๋ค์จ์ด๋ฅผ ํตํด Multipart/form-data๋ก ๋ฐ์์ค๊ณ S3 ๋ฒํท์ ์ ์ฅ, ์ญ์ ํ ์ ์๋๋ก ๊ตฌํ
-
์ฌ์ฉ์์ ๊ฐํธํ ๋ก๊ทธ์ธ์ ์ํด passport๋ฅผ ์ด์ฉํด ์นด์นด์ค ๋ก๊ทธ์ธ ๊ตฌํ
- ๋ก๊ทธ์ธ/ํ์๊ฐ์
- ์นด์นด์ค ์์ ๋ก๊ทธ์ธ
- ๋น๋ฐ๋ฒํธ ๋ณ๊ฒฝ
- ๋ธ๋ก๊ทธ
- ๊ฒ์๊ธ(+์ด๋ฏธ์ง), ๋๊ธ์ ์กฐํ, ์์ฑ, ์์ , ์ญ์
- 1์ฃผ์ผ๊ฐ ์ข์์๋ฅผ ๋ง์ด ๋ฐ์ ์ธ๊ธฐ ๊ฒ์๊ธ๊ณผ ์ ์ ์ถ์ฒ
- ์ข์์, ๊ตฌ๋
- ํค์๋๋ก ๊ฒ์๊ธ ๊ฒ์
- ์นดํ ๊ณ ๋ฆฌ, ํ๊ทธ๋ณ๋ก ๊ฒ์๊ธ ์กฐํ
- ์์ฝํ๊ธฐ
- ์์ฝ ์ ์ฒญ ๋ฐ ์ทจ์
- ํ์ ํตํ ๋ฐ ์ฑํ
- ๋ฐฉ ์ ์ฅ์ ํตํ ๋ธ๋ก๊ฑฐ์ 1๋1 ๋ํ
์ด๋ฆ | ์ค๋ช | ๋ฒ์ |
---|---|---|
sequelize | ๊ฐ์ฒด์งํฅ์ ์ธ ์ฝ๋๋ก ์ธํด ์ง๊ด์ ์ด๊ณ ๋ก์ง์ ๋ ์ง์คํ ์ ์๊ณ ํ ์ด๋ธ ๊ฐ ๊ด๊ณ์ค์ ์ SQL์ ๋นํด ์ฝ๊ฒ ํ ์ ์๋ค๋ ์ฅ์ ๋๋ฌธ์ ๋ํ์ ์ธ ORM์ธ Sequelize๋ฅผ ์ ํ | 6.21.1 |
redis | ํด๋ผ์ด์ธํธ์์ ๋์ผํ ์์ฒญ์ด ๊ณ์ ์ฌ๋ ์๋ฒ์์ ์ง์ ๋ฐ์ดํฐ๋ฅผ ์ฐพ์ผ๋ฉด ์๋นํ ๋นํจ์จ์ ์ด๊ณ ๋ฐ์ดํฐ์ ํฌ๊ธฐ์ ๋ฐ๋ผ ์๋ต์๋๊ฐ ๋๋ ค์ง. ์ด๋ ์์ฒญ๊ฒฐ๊ณผ๋ฅผ ๋ฏธ๋ฆฌ ์ ์ฅํด ๋์๋ค๊ฐ, ๋์ผํ ๋ฐ์ดํฐ ์์ฒญ์ด ์ค๋ฉด ๋ฐ๋ก ์ ๋ฌํ ์ ์๋๋ก redis๋ฅผ ์ฌ์ฉ | 4.2.0 |
bcrypt | ํด์ ํจ์๋ค์ ๋ฌด๊ฒฐ์ฑ ๊ฒ์ฌ๋ฅผ ์ํด ๋น ๋ฅธ ์๋๊ฐ ํ์ํ์ง๋ง, ํด์ปค๊ฐ DB๋ฅผ ํ์ทจ ํ์๋ ๋น ๋ฅธ ์๋๋ก ๋น๋ฐ๋ฒํธ๋ฅผ ์์๋ผ ์ ์์. ํจ์ค์๋ ์ ์ฅ์์์ ํด์ ํจ์์ ๋ฌธ์ ์ ์ ๋ณด์ํด์ ๋์จ๊ฒ์ด pbkfd2. 8๊ธ์ ๋ถํฐ๋ ๋์ผ ์์คํ ์์ bcrypt๊ฐ pbkfd2๋ณด๋ค 4๋ฐฐ ์ด์์ ์๊ฐ์ ์๋ชจํด์ผ ๋น๋ฐ๋ฒํธ๋ฅผ ์์๋ผ ์ ์๊ธฐ ๋๋ฌธ์ ๋ณด์์ฑ์ ์ํด ์ฌ์ฉ | 5.0.1 |
passport-kakao | passport๋ express ํ๋ ์์ํฌ ์์์ ์ฌ์ฉ๋๋ ์ธ์ฆ ๋ฏธ๋ค์จ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ. strategies๋ก ์๋ ค์ ธ ์๋ ์ธ์ฆ ๋ฉ์ปค๋์ฆ์ ๊ฐ ๋ชจ๋๋ก ํจํค์งํํด์ ์ ๊ณต. ์ฆ, ์ฑ์ passport์์ ์ง์ํ๋ ์ ๋ต์ ์ ํํด ์์กด์ฑ ์์ด ๋ ๋ฆฝ์ ์ผ๋ก ์ด์ฉ ๊ฐ๋ฅํจ | 1.0.1 |
nodemailer | ์ด๋ฉ์ผ ์ธ์ฆ์ ์ํด์ ์ด๋ฉ์ผ ์ ์ก์ ํ์ํ ๋คํธ์ํฌ ํ๋กํ ์ฝ์ธ SMTP(์ฐํธ ์ ์ก ํ๋กํ ์ฝ)์ ์ฌ์ฉํด์ผ ํจ. Node.js SMTP๊ธฐ๋ฐ์ผ๋ก ๊ฐ๋ฐ๋ ์ ์ฉ ๋ชจ๋์ธ nodemailer๋ ์ฌ์ฉ๋ฒ์ด ๋งค์ฐ ๊ฐ๋จํ์ฌ ์ฌ์ฉํ๊ฒ ๋จ | 6.7.5 |
multer | Multipart/form-data๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฏธ๋ค์จ์ด๋ก ์๋ก ๋ค๋ฅธ Content-type์ธ ์ด๋ฏธ์ง ํ์ผ๊ณผ ํ ์คํธ๋ฅผ ๊ฐ์ด ์ ์กํ๊ธฐ ์ํด ์ฌ์ฉ. aws-sdk, sharp์ ๊น์ด ์ฌ์ฉํ๊ธฐ ์ฝ๊ฒ ๊ตฌํ๋์ด ์์ | 1.4.5-lts.1 |
dayjs | javascript์ ๋ ์ง ๊ด๋ จ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์์ ๊ฐ์ฅ ๊ฐ๋ฒผ์. Date ๊ฐ์ฒด๋ ์์ฑํด์ผ ํ๋ ์ฝ๋๋ ๋ง๊ณ ์ถ๋ ฅ ํฌ๋งท์ ๋ณ๊ฒฝํ๋ ค๋ฉด ์ง์ ํจ์๋ฅผ ๋ง๋ค์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง | 1.11.3 |
joi | ๋ก๊ทธ์ธ, ํ์๊ฐ์ , ๊ฒ์๊ธ ๋ฑ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ์ํด joi๋ฅผ ์ฌ์ฉ, ์คํค๋ง๋ฅผ ํ์ฉํด ๊ฐ๋ ์ฑ์ด ์ข๊ณ ๋ชจ๋๋ก์ ํ์ฉ๋ ์ข์ Joi๋ฅผ ์ ํ | 17.6.0 |
node-cron | ํญ์ ์คํ๋์ด ์๋ App์์ ์ผ์ ์๊ฐ๋ง๋ค ํน์ ํจ์๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด node-cron์ ํ์ฉ. node-schedule๋ณด๋ค ์ ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฌ์ฉ | 3.0.1 |
eslint | ์ฝ๋๋ฅผ ๋ถ์ํด ๋ฌธ๋ฒ์ ์ธ ์ค๋ฅ๋ฅผ ์ฐพ์์ฃผ๊ฑฐ๋ ํ๋ก์ ํธ ๋ด์์ ์ผ๊ด๋ ์ฝ๋ ์คํ์ผ์ ์ ์งํ๊ธฐ ์ํด ์ฌ์ฉ. ํ๋ก์ ํธ์๋ Airbnb์ ์ฝ๋ฉ ์ปจ๋ฒค์ ์ ์ ์ฉ. | 8.19.0 |
socket.io | ๋ธ๋ก๊ฑฐ์ 1๋1 ์ค์๊ฐ ์ฑํ ๋ฐ WebRTC signaling server๋ก ํ์ฉํ๊ธฐ ์ํด Socket.io๋ฅผ ์ฌ์ฉ. ๋ธ๋ผ์ฐ์ ํ๊ฒฝ์ ๋ง๊ฒ ๊ฐ์ฅ ์ ํฉํ ํต์ ๋ฐฉ์์ ์์์ ์ ํํ๊ณ WebSocket์ด ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณตํ์ง ์๋ namespace, room ๊ธฐ๋ฅ, ๋ค์ํ ๋ฐ์ดํฐ ์ ์ก ๊ฐ๋ฅ ๋ฑ์ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์ Socket.io๋ฅผ ์ ํ | 4.5.1 |
artillery | ์ฝ๋์ ๋ณํ์ ๋ฐ๋ฅธ ์ฑ๋ฅ์ ๋น๊ตํ๊ธฐ ์ํด ์ฌ์ฉ. ํ ์คํธ ์๋๋ฆฌ์ค๋ฅผ ์์ฑํ๊ณ ํ ์คํธ ๊ฒฐ๊ณผ๋ฅผ ํ์ผ๋ก ์ ์ฅํ ์ ์์ | 2.0.0-20 |
jest | ๋ฐฐํฌ ์ ์์ฑํ ์ฝ๋๊ฐ ์์ํ ๋๋ก ์คํํ๋์ง ์ฒดํฌํ๊ณ ์ฝ๋ ํ์ง ํฅ์ ๋ฐ ์ฝ๋ ๋ฌธ์ํ๋ฅผ ์ํด ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑ. ์ฌ๋ฌ ํ ์คํธ ํ๋ ์์ํฌ ์ค Jest๋ ์ฝ๋ ์์ฑ์ด ์ฌํํ๊ณ ํ ์คํธ๋ฅผ ๋ณ๋ ฌ๋ก ์คํํด ํ ์คํธ ์คํ ์๋๊ฐ ๋น ๋ฅด๋ค๋ ์ฅ์ ์ด ์์ด ์ ํ | 28.1.2 |
- feat : ์๋ก์ด ๊ธฐ๋ฅ ์ถ๊ฐ
- fix : ๋น๋ ๊ด๋ จ ํ์ผ ์์
- build : ๋น๋ ๊ด๋ จ ํ์ผ ์์
- chore : ๊ทธ ์ธ ์์ํ ์์
- ci : CI ๊ด๋ จ ์ค์ ์์
- docs : ๋ฌธ์ ์์
- style : ์ฝ๋ ์คํ์ผ ํน์ ํฌ๋งท ์์
- refactor : ์ฝ๋ ๋ฆฌํฉํ ๋ง
- test : ํ ์คํธ ์ฝ๋ ์์
๋ฌธ์ ์
- ๋ฉ์ธ ํ์ด์ง๋ ์๋น์ค๋ฅผ ์ด์ฉํ๋ ๋ชจ๋ ์ ์ ๋ค์ด ๋ฐฉ๋ฌธํ๊ธฐ ๋๋ฌธ์ API ์ฌ์ฉ๋์ด ๋งค์ฐ ๋ง๋ค.
- DB์์ ๋ชจ๋ ๊ฒ์๊ธ์ ์กฐํํ๊ณ 1์ฃผ์ผ๊ฐ ์ข์์๋ฅผ ๋ง์ด ๋ฐ์ ์์๋ก ์ ๋ ฌํ๋ ๋ก์ง์ ๋งค๋ฒ ์คํํ๋ค.
- ๋๋ฆฐ ๋ก๋ฉ ์๋๋ก ์ ์ ๊ฐ ๋๋ผ๋ ๋ถํธํจ์ ๊ฐ์ ํ๊ณ ์ด์ ์ธก๋ฉด์์๋ ์๋ฒ ๋น์ฉ์ ๊ฐ์ถํ ํ์๊ฐ ์๋ค.
ํด๊ฒฐ๋ฐฉ์
- ๋ ๋์ค์ ๊ฐ๊ณต๋ ๋ฐ์ดํฐ๋ฅผ ๋ฏธ๋ฆฌ ์ ์ฅํ๊ณ API ํธ์ถ ์ DB์ ์ ๊ทผํ์ง ์๊ณ ๋ ๋์ค์์ ๋ฐ๋ก ํด๋น ๋ฐ์ดํฐ๋ฅผ ์ ์กํ๋ค.
- 10๋ถ ๋จ์๋ก ์บ์์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ค.
๊ฒฐ๊ณผ
Artillery๋ก ํ ์คํธํด๋ณธ ๊ฒฐ๊ณผ, ๊ธฐ์กด ๋ฐฉ์์ ๋นํด ๋ ๋์ค๋ฅผ ๊ฐ์ด ํ์ฉํ์ ๋ ์๋ฒ ์๋ต ์๋๊ฐ 70% ๊ฐ๋ ๋จ์ถ๋์๋ค.
์์ฌ์ด์
10๋ถ๋ง๋ค ์ธ๊ธฐ ๊ฒ์๊ธ์ ์ ๋ฐ์ดํธ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ์ค์๊ฐ์ผ๋ก ์ ๋ฐ์ดํธ๋ ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํ ์ ์๋ค๋ ํ๊ณ์ ์ด ์๋ค.
์์ฉ
- ์ผ์ผ ์กฐํ์๋ฅผ ๋ ๋์ค์ ์ ์ฅํ๊ณ ์ค์ 12์์ ํฉ์ฐํ์ฌ DB์ ์ ๋ฐ์ดํธํ๋ค. ๋ ๋์ค์ ๋ฐ์ดํฐ ํ์ set์ ํ์ฉํ์ฌ ์ค๋ณต ์ง๊ณ๋ฅผ ๋ฐฉ์งํ๋ค.
- ๋ ๋์ค๋ฅผ ์ธ์ ์ ์ฅ์๋ก ํ์ฉํ์ฌ JWT ํ ํฐ์ ์ ์ฅํ๊ณ ์ค๋ณต ๋ก๊ทธ์ธ์ ๋ฐฉ์งํ๋ค.
๋ฌธ์ ์
- 1:N์ ๊ด๊ณ๋ฅผ ๊ฐ๋ ๋ฐ์ดํฐ(๊ฒ์๊ธ : ๋๊ธ, ์ข์์, ํ๊ทธ ๋ฑ) ์กฐํ์ Eager Loading์ ํ์ฉํ๋ค.
- ์ฌ๋ฌ ๋ฒ์ ํ ์ด๋ธ JOIN์ผ๋ก ์ฑ๋ฅ ์ ํ๋๋ค.
ํด๊ฒฐ๋ฐฉ์
- Lazy Loading์ ํ์ฉํ์ฌ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๊ฐ ํ ์ด๋ธ์์ ์กฐํํ๋ค.
๊ฒฐ๊ณผ
- ์ฝ๋ ๊ฐ๋ ์ฑ์ด ์ข์์ก๋ค.
// Eager Loading
const paper = await Paper.findOne({
where: { postId },
include: [
{
model: Comment,
include: {
model: User,
as: 'Users',
attributes: ['userId', 'blogId', 'nickname', 'profileImage'],
},
},
{ model: Tag, attributes: ['name'] },
{ model: User, as: 'Users', attributes: ['blogId', 'nickname', 'profileImage'] },
{ model: User, as: 'Likes', attributes: ['blogId'] },
],
});
// Lazy Loading
const paper = await Paper.findOne({ where: { postId } })
const comments = await Comment.findAll({
where: { postId },
include: {
model: User,
as: 'Users',
attributes: ['userId', 'blogId', 'nickname', 'profileImage'],
},
});
const tags = await paper.getTags({ attributes: ['name'] });
const user = await paper.getUsers({ attributes: ['blogId', 'nickname', 'profileImage'] });
const likes = await paper.getLikes({ attributes: ['blogId'] });
- ๊ธฐ์กด ๋ฐฉ์์ ๋นํด ์๋ฒ ์๋ต ์๋๊ฐ 50% ๊ฐ๋ ๋จ์ถ๋์๋ค.
๋ฌธ์ ์
๋ก์ปฌ์์ ๋ฌธ์ ์์ด ๋์๊ฐ๋ ์๋ฒ๊ฐ ๋ฐฐํฌ ํ ์คํ์ ํ๋ฉด reify fsevents ํ๋ฆฌ์ง ๋ฌธ์ ๋ฐ์
๊ตฌ๊ธ๋ง์ ํตํด ๋ ธ๋ ๋ฒ์ ๋ฌธ์ ๋ก ์ธํ ์๋ฌ๋ผ๋ ์ฌ์ค ๋ฐ๊ฒฌ
ํด๊ฒฐ๋ฐฉ์
- ๋ ธ๋ ๋ฒ์ ์ ๋ก์ปฌํ๊ฒฝ๊ณผ ๋ง์ถฐ์ฃผ๋ ๋ฐฉ๋ฒ๋ ์์ง๋ง ์ถ๊ฐ ์ธ์คํด์ค๋ฅผ ์์ฑํ ๋๋ง๋ค ๋ง์ถฐ์ค์ผํ๋ ๋ฒ๊ฑฐ๋ก์ ๋ฐ์
- ๋ก์ปฌํ๊ฒฝ์ ๋์ปค ์ด๋ฏธ์ง๋ฅผ ์์ฑํด ์ธ์คํด์ค์์ ์คํ
๊ฒฐ๊ณผ
๋ก์ปฌ์ ์์ ํ ๊ฑธ ์ด๋ฏธ์ง๋ก ๋น๋ํด ์คํํ๋ ๋ฐฐํฌํ๊ฒฝ์์ ๋ฒ์ ์ด์ ๋ฑ์ผ๋ก ์ธํ ์๋ฌ๋ฅผ ๊ฑฑ์ ํ์ง ์๊ณ ๋ฐฐํฌ ๊ฐ๋ฅ
๋ฌธ์ ์
์ด๋ฏธ์ง๋ฅผ ์ฒจ๋ถ(์ ๋ก๋)ํ๊ณ ๊ฒ์๊ธ์ ์์ฑํ๋ค๊ฐ ์ค๊ฐ์ ํ์ด์ง๋ฅผ ๋ฒ์ด๋๋ค๋ฉด ์ฌ์ฉ๋์ง ์๋ ์ด๋ฏธ์ง๊ฐ S3์ ๋จ์์๊ฒ ๋จ ๊ฒ์๊ธ์ ์์ ํ๋ฉด์ ๊ธฐ์กด์ ์ฌ์ฉํ ์ด๋ฏธ์ง๋ฅผ ์ญ์ ํ ๋๋ ๋๊ฐ์ ๋ฌธ์ ๊ฐ ์๊น
ํด๊ฒฐ๋ฐฉ์
- image ํ ์ด๋ธ์ ์ถ๊ฐ
- ์ด๋ฏธ์ง ์ ๋ก๋ ์ image ํ ์ด๋ธ์ postId๊ฐ null์ธ ์ํ๋ก ์ถ๊ฐ
- ๊ฒ์๊ธ ๋๋ก ์ ๋ณธ๋ฌธ์ ์ ๊ท์์ผ๋ก ์ด๋ฏธ์ง url๋ค์ ํํฐ๋งํ๊ณ ๋ฐฐ์ด์ ์ ์ฅ ๋ฐฐ์ด ๋ด ๊ฐ๋ค๊ณผ ์ผ์นํ๋ row๋ค์ postId๋ฅผ ๋ถ์ฌ
- node-cron์ผ๋ก postId๊ฐ null์ด๊ณ updateAt์ด ํ๋ฃจ ์ ์ด์์ธ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ธฐ์ ์ผ๋ก ์ญ์
Backend | |||
๋ฌธ๊ด๋ฏผ | ์ก๋ฏผ์ง | ๋ฐ์ ์ฐ | ๊น์ฑ์ค |
Frontend | ||
๊ตฌ์๋ | ์์ด์ฒ | ์ ๋๊ท |