😎 κ³΅λΆ€ν•˜λŠ” μ§•μ§•μ•ŒνŒŒμΉ΄λŠ” μ²˜μŒμ΄μ§€?

[CRUD을 μ΄μš©ν•œ File upload Web] (9) user 데이터 μˆ˜μ •ν•˜κΈ° & 동기와 비동기 λ³Έλ¬Έ

πŸ‘©‍πŸ’» λ°±μ—”λ“œ(Back-End)/Node js

[CRUD을 μ΄μš©ν•œ File upload Web] (9) user 데이터 μˆ˜μ •ν•˜κΈ° & 동기와 비동기

μ§•μ§•μ•ŒνŒŒμΉ΄ 2023. 3. 11. 17:33
728x90
λ°˜μ‘ν˜•

<λ³Έ λΈ”λ‘œκ·ΈλŠ” DCodeMania 의 유튜브λ₯Ό μ°Έκ³ ν•΄μ„œ κ³΅λΆ€ν•˜λ©° μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆ :-)>

=> CRUD App With Image Upload Using NodeJs, ExpressJs, MongoDB & EJS Templating Engine

 

 

πŸ₯• 동기(synchronous)

: 직렬적으둜 νƒœμŠ€ν¬λ₯Ό μˆ˜ν–‰

: μš”μ²­μ„ 보낸 ν›„ 응닡을 λ°›μ•„μ•Όμ§€λ§Œ λ‹€μŒ λ™μž‘μ΄ μ΄λ£¨μ–΄μ§€λŠ” 방식 (νƒœμŠ€ν¬λ₯Ό μ²˜λ¦¬ν•  λ™μ•ˆ λ‚˜λ¨Έμ§€ νƒœμŠ€ν¬λŠ” λŒ€κΈ°)

https://velog.io/@khy226/%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0%EB%9E%80-Promise-asyncawait-%EA%B0%9C%EB%85%90 μ°Έκ³ 

 

πŸ₯• 비동기 (asynchronous)

: λ³‘λ ¬μ μœΌλ‘œ νƒœμŠ€ν¬λ₯Ό μˆ˜ν–‰

: μš”μ²­μ„ 보낸 ν›„ μ‘λ‹΅μ˜ 수락 μ—¬λΆ€μ™€λŠ” 상관없이 λ‹€μŒ νƒœμŠ€ν¬κ°€ λ™μž‘ν•˜λŠ” 방식 (a νƒœμŠ€ν¬κ°€ μ‹€ν–‰λ˜λŠ” μ‹œκ°„ λ™μ•ˆ b νƒœμŠ€ν¬ 함)

: 비동기 μš”μ²­μ‹œ 응닡 ν›„ μ²˜λ¦¬ν•  '콜백 ν•¨μˆ˜' μ•Œλ €μ€Œ => ν•΄λ‹Ή νƒœμŠ€ν¬κ°€ μ™„λ£Œλ˜μ—ˆμ„ λ•Œ, '콜백 ν•¨μˆ˜'κ°€ 호좜됨

https://velog.io/@khy226/%EB%8F%99%EA%B8%B0-%EB%B9%84%EB%8F%99%EA%B8%B0%EB%9E%80-Promise-asyncawait-%EA%B0%9C%EB%85%90 μ°Έκ³ 

 

βž• 후속 처리 λ©”μ†Œλ“œ
1) Promise 
then (Promise λ°˜ν™˜)
: 두 개의 콜백 ν•¨μˆ˜λ₯Ό 인자둜 전달 λ°›μŒ
: 첫 번째 콜백 ν•¨μˆ˜λŠ” 성곡(fulfilled, resolve ν•¨μˆ˜κ°€ 호좜된 μƒνƒœ) μ‹œ 호좜되고
두 번째 ν•¨μˆ˜λŠ” μ‹€νŒ¨(rejected, reject ν•¨μˆ˜κ°€ 호좜된 μƒνƒœ) μ‹œ 호좜
: then λ©”μ†Œλ“œλŠ” Promiseλ₯Ό λ°˜ν™˜
// Promise 객체의 생성
const promise = new Promise((resolve, reject) => {
  // 비동기 μž‘μ—…μ„ μˆ˜ν–‰ν•œλ‹€.

  if (/* 비동기 μž‘μ—… μˆ˜ν–‰ 성곡 */) {
    resolve('result');
  }
  else { /* 비동기 μž‘μ—… μˆ˜ν–‰ μ‹€νŒ¨ */
    reject('failure reason');
  }
});

catch μ˜ˆμ™Έ
: 비동기 μ²˜λ¦¬μ—μ„œ λ°œμƒν•œ μ—λŸ¬μ™€ then λ©”μ†Œλ“œμ—μ„œ λ°œμƒν•œ μ—λŸ¬κ°€ λ°œμƒν•˜λ©΄ 호좜
: catch λ©”μ†Œλ“œλŠ” Promiseλ₯Ό λ°˜ν™˜

3) async와 await
async
: function μ•žμ— asyncλ₯Ό 뢙이면 ν•΄λ‹Ή ν•¨μˆ˜λŠ” 항상 ν”„λΌλ―ΈμŠ€λ₯Ό λ°˜ν™˜

await
: async ν•¨μˆ˜ μ•ˆμ—μ„œλ§Œ λ™μž‘, ν”„λΌλ―ΈμŠ€κ°€ 처리될 λ•Œ κΉŒμ§€ κΈ°λ‹€λ¦¬λŠ” μ—­ν•  => κ²°κ³ΌλŠ” κ·Έ 이후 λ°˜ν™˜

async function ν•¨μˆ˜λͺ…() {
  await 비동기_처리_λ©”μ„œλ“œ_λͺ…();
}

 

 

πŸ₯• user λ°μ΄ν„° μˆ˜μ •ν•˜κΈ°

🐧 routes/routes.js

const express = require("express");
const router = express.Router();
const User = require("../models/user");
const multer = require("multer");
const fs = require("fs");

// image upload
var storage = multer.diskStorage({
  // 파일이 μ—…λ‘œλ“œλ  경둜 μ„€μ •
  destination: function (req, file, cb) {
    cb(null, "./uploads");
  },
  // timestampλ₯Ό μ΄μš©ν•΄ μƒˆλ‘œμš΄ 파일λͺ… μ„€μ •
  filename: function (req, file, cb) {
    cb(null, file.fieldname + "_" + Date.now() + "_" + file.originalname);
  }
})

var upload = multer({
  storage: storage,
}).single("image");   // ν•œ 개의 이미지 처리

// Insert an user into database route
router.post("/add", upload, (req, res) => {
  const user = new User({
    name: req.body.name,
    email: req.body.email,
    phone: req.body.phone,
    image: req.file.filename,
  });

  user.save().then((err) => {
    // index.js 에 res.locals.message 있음
    req.session.message = {
      type: "success",
      message: "User added successsfull!"
    };
    // μ§€μ •λœ λ‹€λ₯Έ URL둜 μž¬μš”μ²­ (ν™ˆ)
    res.redirect("/");
  }).catch((err) => {
    res.json({ message: err.message, type: "danger" });
  })
});

// 1) Get all users route
router.get("/", async (req, res) => {
  const user = await User.find();

  try {
    // Queryλ₯Ό μ΄μš©ν•  λ•Œ ν”„λ‘œλ―ΈμŠ€λ₯Ό 리턴받고 μ‹Άλ‹€λ©΄ exec() λ©”μ„œλ“œλ₯Ό 이용
    // find()λ₯Ό μ‹€ν–‰ν•˜μ—¬ Query의 μΈμŠ€ν„΄μŠ€λ₯Ό 리턴
      res.render("index", {
        title: "Home Page",
        // ꢁ금 : λ„ˆ μ™œ error μž‘νžˆλ‹ˆ?
        users: user
      });
  } catch (error) {
    (error) => {
      res.json({ message: error.message });
    }
  };
});

router.get("/add", (req, res) => {
  res.render("addUsers", { title: "Add users" });
})

// 2) Edit an user routes
router.get("/edit/:id", async (req, res) => {
  let id = req.params.id;
  const user = await User.findById(id);

  try {
    if (user == null) {
      res.redirect("/");
    } else {
      res.render("editUsers", {
        title: "Edit User",
        user: user,
      });
    }
  } catch (err) {
    res.redirect("/");
  }
});

// 3) Update user route
router.post("/update/:id", upload , async (req, res) => {
  let id = req.params.id;
  let new_image = "";

  if (req.file) {
    new_image = req.file.filename;
    try {
      // 동기 λ°©μ‹μœΌλ‘œ 파일 정보 읽기
      fs.readFileSync("./uploads/" + req.body.old_image);
    } catch(err) {
      console.log(err);
    }
  } else {
    req.image = req.body.old_image;
  }
    
  //  첫 번째 μΈμžλŠ” μ—…λ°μ΄νŠΈ ν•˜κ³ μž ν•˜λŠ” λ¬Έμ„œμ˜ id, 두 번째 μΈμžλŠ” μ—…λ°μ΄νŠΈ ν•  정보 ν˜Ήμ€ λ‚΄μš©
  const user = await User.findByIdAndUpdate(id, {
    name : req.body.name,
    email : req.body.email,
    phone : req.body.phone,
    image : new_image
  });
  
  try {
    req.session.message = {
      type : "success",
      message :"User updated successfully!",
    };
    res.redirect("/");
  } catch (err) {
    res.json({ message : err.message, type : "danger"});
  }
  
});

module.exports = router;

 

🐧 views/editUsers.ejs

<%- include("layout/header") %>

    <div class="container">
        <div class="row">
            <div class="col-lg-6 mx-auto mt-4">
                <div class="card shadow">
                    <div class="card-header bg-success">
                        <h3 class="text-light">Edit User (<%= user.name %>)</h3>
                    </div>
                    <div class="card-body p-4">
                        <!-- addλž‘ router 경둜 κ°™μ•„μ•Ό 될듯? -->
                        <form action="/update/<%= user._id %>" method="post" id="add-form"
                            enctype="multipart/form-data">
                            <div class="mb-3">
                                <label for="name">Name</label>
                                <input type="text" name="name" class="form-control form-control-lg"
                                    placeholder="Enter name" value="<%= user.name %>" required />
                            </div>
                            <div class="mb-3">
                                <label for="email">Email</label>
                                <input type="email" name="email" class="form-control form-control-lg"
                                    placeholder="Enter email" value="<%= user.email %>" required />
                            </div>
                            <div class="mb-3">
                                <label for="phone">Phone</label>
                                <input type="tel" name="phone" class="form-control form-control-lg"
                                    placeholder="Enter phone" value="<%= user.phone %>" required />
                            </div>
                            <div class="mb-3">
                                <label for="image" class="form-label">Select Image</label>
                                <input type="file" name="image" class="form-control form-control-lg" />
                                <img src="/<%= user.image %>" width="100" class="img-thumbnail mt-1">
                            </div>
                            <input type="hidden" name="old_image" value="<%= user.image %>">
                            <div class="mb-3 d-grid">
                                <input type="submit" name="submit" value="Update User" class="btn btn-success btn-lg" />
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <%- include("layout/footer") %>

 

728x90
λ°˜μ‘ν˜•
Comments