์ƒ์„ธ ์ปจํ…์ธ 

๋ณธ๋ฌธ ์ œ๋ชฉ

[๋…ธ๋“œ 2ํŒ€] #10. ์ต์Šคํ”„๋ ˆ์Šค๋กœ SNS ์„œ๋น„์Šค ๋งŒ๋“ค๊ธฐ

24-25/Node.js 2

by sksmsyena 2025. 1. 3. 11:21

๋ณธ๋ฌธ

728x90

 

 

 

 ๐ŸŒŸํ‚ค์›Œ๋“œ:  npm ํŒจํ‚ค์ง€, ์ปจํŠธ๋กค๋Ÿฌ, ๊ด€๊ณ„, Passport ๋ชจ๋“ˆ, multer ํŒจํ‚ค์ง€

 

 


 

1. ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ๊ฐ–์ถ”๊ธฐ

npm init
npm i sequelize mysql2 sequelize-cli
npx sepuelize init
  • npm init์„ ํ˜ธ์ถœํ•˜๋ฉด package.json์„ ์ƒ์„ฑํ•จ
  • npm i๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด node_modules ํด๋”์™€ package-lock.json์ด ์ƒ์„ฑ๋จ
  • npm sequelize init๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด config, migrations, models, seeders ํด๋”๊ฐ€ ์ƒ์„ฑ๋จ
  • ์ถ”๊ฐ€๋กœ ํ•„์š”ํ•œ npm ํŒจํ‚ค์ง€๋“ค์„ ์„ค์น˜ํ•˜๊ณ  app.js๋ฅผ ์ž‘์„ฑ

 

 

2.  ์ปจํŠธ๋กค๋Ÿฌ

exports.renderProfile = (req, res) => {
  res.render('profile', { title: '๋‚ด ์ •๋ณด - NodeBird' });
};

exports.renderJoin = (req, res) => {
  res.render('join', { title: 'ํšŒ์›๊ฐ€์ž… - NodeBird' });
};

exports.renderMain = (req, res, next) => {
  const twits = [];
  res.render('main', {
    title: 'NodeBird',
    twits,
  });
};
  • ๋ผ์šฐํ„ฐ ๋งˆ์ง€๋ง‰์— ์œ„์น˜ํ•ด ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต์„ ๋ณด๋‚ด๋Š” ๋ฏธ๋“ค์›จ์–ด      ex) renderProfile, renderJoin, renderMain
  • res.send, res.join, res.redirect, res.render ๋“ฑ์ด ์กด์žฌํ•˜๋Š” ๋ฏธ๋“ค์›จ์–ด
  • ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋ถ„๋ฆฌํ•˜๋ฉด ์‹ค๋ฌด์—์„œ ์ฝ”๋“œ๋ฅผ ํŽธํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ

 

 

3. 1:N๊ด€๊ณ„์™€ N:M ๊ด€๊ณ„

โ‘  1:N ๊ด€๊ณ„

User ๋ชจ๋ธ๊ณผ Post ๋ชจ๋ธ์€ 1(User):N(Post) ๊ด€๊ณ„์— ์žˆ์œผ๋ฏ€๋กœ hasMany๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์Œ

static associate(db) {
	db.User.hasMany(db.Post);
    db.User.belongsToMany(db.User, {
    	foreignKey: 'followingId',
        as: 'Followers',
        through: 'Follow',
    });
    db.User.belongsToMany(db.User, {
    	foreignKey: 'followerId',
        as: 'Follwings',
        through: 'Follow',
    });
}

 

โ‘ก N:M ๊ด€๊ณ„

  • ๊ฐ™์€ ๋ชจ๋ธ๋ผ๋ฆฌ๋„ N:M ๊ด€๊ณ„๋ฅผ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Œ
  • ํŒ”๋กœ์ž‰ ๊ธฐ๋Šฅ์ด N:M ๊ด€๊ณ„ → ์‚ฌ์šฉ์ž ํ•œ ๋ช…์ด ํŒ”๋กœ์›Œ๋ฅผ ์—ฌ๋Ÿฌ ๋ช… ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ๊ณ , ํ•œ ์‚ฌ๋žŒ์ด ์—ฌ๋Ÿฌ ๋ช…์„ ํŒ”๋กœ์ž‰ ํ•  ์ˆ˜ ์žˆ์Œ
  • ๊ฐ™์€ ํ…Œ์ด๋ธ” ๊ฐ„ N:M ๊ด€๊ณ„์—์„œ๋Š” ๋ชจ๋ธ ์ด๋ฆ„๊ณผ ์ปฌ๋Ÿผ ์ด๋ฆ„์„ ๋”ฐ๋กœ ์ •ํ•ด์•ผ ํ•˜๊ณ , as ์˜ต์…˜๋„ ๋„ฃ์–ด์•ผ ํ•จ

 

 

4. Passport ๋ชจ๋“ˆ

  • ํšŒ์› ๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ ๊ตฌํ˜„ ์‹œ ์„ธ์…˜๊ณผ ์ฟ ํ‚ค ์ฒ˜๋ฆฌ ๋“ฑ ๋ณต์žกํ•œ ์ž‘์—…์ด ๋งŽ์œผ๋ฏ€๋กœ Passport ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•œ๋‹ค.
  • Passport๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์•„์ด๋”” & ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  SNS๊ณ„์ •์œผ๋กœ ๋กœ๊ทธ์ธํ•˜๋Š” ๋ฐฉ๋ฒ• ๊ตฌํ˜„ ๊ฐ€๋Šฅ
const passport = require('passport');
const local = require('./localStrategy');
const kakao = require('./kakaoStrategy');
const User = require('../models/user');

module.exports = () => {
  passport.serializeUser((user, done) => {
    done(null, user.id);
  });

  passport.deserializeUser((id, done) => {
    User.findOne({ where: { id } })
      .then(user => done(null, user))
      .catch(err => done(err));
  });

  local();
  kakao();
};

 

 

 

 

5. multer ํŒจํ‚ค์ง€๋กœ ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ตฌํ˜„

  • multer ํŒจํ‚ค์ง€๋Š” ์ด๋ฏธ์ง€๋ฅผ ์„œ๋ฒ„ ๋””์Šคํฌ์— ์ €์žฅ
  • ๋””์Šคํฌ์— ์ €์žฅํ•˜๋ฉด ๊ฐ„๋‹จํ•˜์ง€๋งŒ, ์ด๋ฏธ์ง€ ์†์‹ค ์œ„ํ—˜์ด ์žˆ์–ด ํด๋ผ์šฐ๋“œ ์Šคํ† ๋ฆฌ์ง€๊ฐ™์€ ์ •์  ํŒŒ์ผ ์ œ๊ณต ์„œ๋น„์Šค ์‚ฌ์šฉ ํ•„์š”

โ€‹

์˜ˆ์ œ ์ฝ”๋“œ

// POST /post/img
router.post('/img', isLoggedIn, upload.single('img'), afterUploadImage);
  • POST /post/img ๋ผ์šฐํ„ฐ์—์„œ๋Š” ์ด๋ฏธ์ง€ ํ•˜๋‚˜๋ฅผ ์—…๋กœ๋“œ๋ฐ›์€ ๋’ค ์ด๋ฏธ์ง€์˜ ์ €์žฅ ๊ฒฝ๋กœ๋ฅผ ํด๋ผ์ด์–ธํŠธ๋กœ ์‘๋‹ต
  • static ๋ฏธ๋“ค์›จ์–ด๊ฐ€ /img ๊ฒฝ๋กœ์˜ ์ •์  ํŒŒ์ผ์„ ์ œ๊ณตํ•˜๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์—…๋กœ๋“œํ•œ ์ด๋ฏธ์ง€์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.

 

// POST /post
const upload2 = multer();
router.post('/', isLoggedIn, upload2.none(), uploadPost);

module.exports = router;
  • POST /post ๋ผ์šฐํ„ฐ๋Š” ๊ฒŒ์‹œ๊ธ€ ์—…๋กœ๋“œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ์—…๋กœ๋“œ
  • ์ด์ „ ๋ผ์šฐํ„ฐ์—์„œ ์ด๋ฏธ์ง€๋ฅผ ์—…๋กœ๋“œํ–ˆ๋‹ค๋ฉด ์ด๋ฏธ์ง€ ์ฃผ์†Œ๋„ req.body.url๋กœ ์ „์†ก๋จ

 

 

 

6. ํ•ต์‹ฌ ์ •๋ฆฌ

  • ์„œ๋ฒ„๋Š” ์š”์ฒญ์— ์‘๋‹ตํ•˜๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ ์ž„๋ฌด์ด๋ฏ€๋กœ ์š”์ฒญ์„ ์ˆ˜๋ฝํ•˜๋“  ๊ฑฐ์ ˆํ•˜๋“  ์ƒ๊ด€์—†์ด ๋ฐ˜๋“œ์‹œ ์‘๋‹ตํ•ด์•ผ ํ•จ. ์ด๋•Œ ํ•œ ๋ฒˆ๋งŒ ์‘๋‹ตํ•ด์•ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์Œ

โ€‹

  • dotenv ํŒจํ‚ค์ง€์™€ .env ํŒŒ์ผ๋กœ ์œ ์ถœ๋˜๋ฉด ์•ˆ ๋˜๋Š” ๋น„๋ฐ€ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•จ

 

  • ๋ผ์šฐํ„ฐ๋Š” routes ํด๋”์—, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” models ํด๋”์—, html ํŒŒ์ผ์€ views ํด๋”์— ๊ฐ๊ฐ ๊ตฌ๋ถ„ํ•ด์„œ ์ €์žฅํ•˜๋ฉด ํ”„๋กœ์ ํŠธ ๊ทœ๋ชจ๊ฐ€ ์ปค์ ธ๋„ ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฌ์›€

โ€‹

  • ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•˜๊ธฐ ์ „์— ๋ฐ์ดํ„ฐ ๊ฐ„ 1:1, 1:N, N:M ๊ด€๊ณ„๋ฅผ ์ž˜ ํŒŒ์•…ํ•ด์•ผ ํ•จ

โ€‹

  • ํ”„๋ก ํŠธ์—”๋“œ form ํƒœ๊ทธ์˜ ์ธ์ฝ”๋”ฉ ๋ฐฉ์‹์ด multipart์ผ ๋•Œ๋Š” multer ๊ฐ™์€ multipart ์ฒ˜๋ฆฌ์šฉ ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ

โ€‹


 

quiz

 

1. ๋ผ์šฐํ„ฐ ๋งˆ์ง€๋ง‰์— ์œ„์น˜ํ•ด ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต์„ ๋ณด๋‚ด๋Š” ๋ฏธ๋“ค์›จ์–ด๋ฅผ (      ) ๋ผ๊ณ  ํ•œ๋‹ค.

โ€‹

2. User ๋ชจ๋ธ๊ณผ Post ๋ชจ๋ธ์€ (      ) ๊ด€๊ณ„์— ์žˆ๊ณ , ํŒ”๋กœ์ž‰ ๊ธฐ๋Šฅ์€ (      ) ๊ด€๊ณ„์— ์žˆ๋‹ค.

โ€‹

3. ํšŒ์› ๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ์„ ๊ตฌํ˜„ํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“ˆ์€ (      ) ๋ชจ๋“ˆ์ด๋‹ค.

โ€‹

4. (      ) ํŒจํ‚ค์ง€๋Š” ์ด๋ฏธ์ง€๋ฅผ ์„œ๋ฒ„ ๋””์Šคํฌ์— ์ €์žฅํ•œ๋‹ค.

โ€‹

5. ์„œ๋ฒ„๋Š” ์š”์ฒญ์— ๋ฐ˜๋“œ์‹œ ์‘๋‹ตํ•ด์•ผํ•˜๋ฉฐ, ์—ฌ๋Ÿฌ ๋ฒˆ ์‘๋‹ตํ•  ์ˆ˜ ์žˆ๋‹ค. [ O/X ]

โ€‹

6. (      ) ํŒจํ‚ค์ง€์™€ (      ) ํŒŒ์ผ๋กœ ์œ ์ถœ๋˜๋ฉด ์•ˆ ๋˜๋Š” ๋น„๋ฐ€ ํ‚ค๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

โ€‹

7. ๊ทœ๋ชจ๊ฐ€ ํฐ ํ”„๋กœ์ ํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋ผ์šฐํ„ฐ๋Š” (      ) ํด๋”์—, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋Š” (      ) ํด๋”์—, html ํŒŒ์ผ์€ (      ) ํด๋”์— ๊ตฌ๋ถ„ํ•ด์„œ ์ €์žฅํ•œ๋‹ค.

โ€‹

โ€‹

programming quiz

โ€‹

8. Node.js์™€ Express๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ POST /post/img ๋ผ์šฐํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์‹œ์˜ค. (์ด ๋ผ์šฐํ„ฐ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์—…๋กœ๋“œํ•œ ๋‹จ์ผ ์ด๋ฏธ์ง€๋ฅผ ์„œ๋ฒ„์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ , ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๋งŒ ๊ธฐ๋Šฅ์„ ๊ธฐ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.)

 

9. GET /profile ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด 'profile' ํ…œํ”Œ๋ฆฟ์„ ๋ Œ๋”๋งํ•˜๊ณ , title๋กœ '๋‚ด ์ •๋ณด - NodeBird'๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜์‹œ์˜ค.

 


 

Answer

1. ์ปจํŠธ๋กค๋Ÿฌ
2.  1:N / N:M
3. Passport 
4. multer
5. X, ์—ฌ๋Ÿฌ ๋ฒˆ ์‘๋‹ตํ•˜๋ฉด ์—๋Ÿฌ ๋ฐœ์ƒ
6. dotenv / .env 
7. routes / modules / views

 

8.

router.post('/img', isLoggedIn, upload.single('img'), afterUploadImage);

 

9.

exports.renderProfile = (req, res) => {
  res.render('profile', { title: '๋‚ด ์ •๋ณด - NodeBird' });
};

 

 


 

์ถœ์ฒ˜) ์กฐํ˜„์ •, ใ€ŒNode.js ๊ต๊ณผ์„œ ๊ฐœ์ • 3ํŒใ€, ๊ธธ๋ฒ—(2022), 9์žฅ

 

Corner node.js 2ํŒ€

Editor : Pujimbao

728x90

๊ด€๋ จ๊ธ€ ๋”๋ณด๊ธฐ