[Node.js & MySQL] ํšŒ์› CRUD

Yunhye Parkยท2023๋…„ 11์›” 2์ผ
0
post-thumbnail
post-custom-banner

MVC ํŒจํ„ด์œผ๋กœ ํด๋”๋ฅผ ๋‚˜๋ˆ„๊ณ , ๊ฐ ๋ถ„๋ฅ˜์— ๋งž๊ฒŒ ๋‚ด์šฉ์„ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๊นŒ์ง€ ์ˆ˜์—…์—์„œ ๋ฐฐ์› ๋‹ค. ์ด์ œ ๋Œ€๋ง์˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์—ฐ๊ฒฐ์ด๋‹ค. ํšŒ์›๊ฐ€์ž…๋ถ€ํ„ฐ ๋กœ๊ทธ์ธ, ์ •๋ณด ์กฐํšŒ ํ›„ ์ˆ˜์ •๊ณผ ์‚ญ์ œ๊นŒ์ง€ ๊ตฌํ˜„ํ•ด๋ณด๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ ๊ณผ์ œ์˜€๋‹ค.

ํ๋ฆ„

์ด๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋„์‹ํ™” ํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

์‚ฌ์šฉ์ž๊ฐ€ ์›น ํŽ˜์ด์ง€์— ์ ‘์†ํ–ˆ์„ ๋•Œ ๊ฐ€์žฅ ๋จผ์ € ๋ฉ”์ธ ํ™ˆํ™”๋ฉด(home.ejs)์„ ๋ณด์—ฌ์ค€๋‹ค. ์—ฌ๊ธฐ์—” ํšŒ์›๊ฐ€์ž…๊ณผ ๋กœ๊ทธ์ธ ๊ฐ๊ฐ์œผ๋กœ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋Š” ํ™”๋ฉด์ด ์ฃผ์–ด์ง„๋‹ค.

  • ํšŒ์›๊ฐ€์ž… : ์•„์ด๋””/๋น„๋ฐ€๋ฒˆํ˜ธ/์ด๋ฆ„์„ ์ž…๋ ฅ ํ›„ ๋ฒ„ํŠผ ํด๋ฆญ -> ๋กœ๊ทธ์ธ ํ™”๋ฉด ์ด๋™
  • ๋กœ๊ทธ์ธ : ์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ ์ž…๋ ฅ ํ›„ ๋ฒ„ํŠผ ํด๋ฆญ -> ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ๋‹ด๊ธด ํ”„๋กœํ•„ ํ™”๋ฉด ์ด๋™
  • ํ”„๋กœํ•„ : ์ด๋ฆ„/๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ํšŒ์› ํƒˆํ‡ด๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋ฒ„ํŠผ ๊ตฌํ˜„

๋จผ์ € ORM ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  sql๋ฌธ์„ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ•ด๋ดค๋‹ค. ๊ทธ ๊ณผ์ •์—์„œ ๋งž๋‹ฅ๋œจ๋ฆฐ ์—๋Ÿฌ๋ฅผ ๊ณ๋“ค์—ฌ ์˜ˆ์ œ ์ฝ”๋“œ์™€ ์ •๋ฆฌํ•ด๋ณด๋ ค ํ•œ๋‹ค.

์ˆœ์„œ

1. ๊ธฐ๋ณธ ์„ธํŒ…

cd ํ”„๋กœ์ ํŠธ ์ƒ์„ฑํ•  ์œ„์น˜
mkdir ์ƒˆ ํ”„๋กœ์ ํŠธ
npm i express, ejs, mysql

2. MVC ํŒจํ„ด์œผ๋กœ ํด๋” ๊ตฌ์กฐํ™”

3. ์—”ํŠธ๋ฆฌ๊ฐ€ ๋  ํŒŒ์ผ(index.js) ์ƒ์„ฑ

express๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ฑฐ๋‚˜ app.listen ์‚ฌ์šฉ์€ ์ด์ „์— ๊ณ„์† ๋ฐ˜๋ณตํ–ˆ๋˜ ๊ฑฐ๋ผ ์ƒ๋žตํ•˜๊ณ  ๋ผ์šฐํ„ฐ ์ง„์ž…์  ๋ถ€๋ถ„๋งŒ ๊ธฐ๋กํ•ด๋‘๊ฒ ๋‹ค.

// ์œ„ ์•„๋ž˜ ์ฝ”๋“œ ์ƒ๋žต

const router = require("./routes");
app.use("/", router);

app.get("*", (req, res)=>{
    res.render("404");
});

๐Ÿ’ก 404ํŽ˜์ด์ง€๋Š” ๋ผ์šฐํ„ฐ ๋‹ค์Œ์— ์ž‘์„ฑ!

๋ผ์šฐํ„ฐ๋กœ ์„ค์ •ํ•œ ํŽ˜์ด์ง€ ์™ธ์— ๋‹ค๋ฅธ url ์ ‘๊ทผ ์‹œ ํ•ด๋‹น ํŽ˜์ด์ง€๋ฅผ ๋ณด์—ฌ์ค„ ์š”๋Ÿ‰์œผ๋กœ ์ „์ฒด ๋ผ์šฐํ„ฐ๋ฅผ ์ง€์ •("*")ํ•œ ๊ฒƒ์ด๊ธฐ์— ๋ผ์šฐํ„ฐ๋กœ ์„ค์ •ํ•œ ์ฃผ์†Œ๋ฅผ ๋จผ์ € ๊ธฐ์ž…ํ•ด์•ผ ์˜๋„๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค. ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์—”์ง„์€ ์œ„์—์„œ๋ถ€ํ„ฐ ์•„๋ž˜๋กœ ํ•œ ์ค„์”ฉ ํ‰๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ๋ ‡๋‹ค.

4. ๋ผ์šฐํ„ฐ ์ž‘์„ฑ

const express = require("express");
const router = express.Router();
const user = require("../controller/Cuser");

// Main
router.get("/", user.home);

// Sign Up render & Click
router.get("/signup", user.signup);
router.post("/signup", user.post_signup);

// Sign In render & Click
router.get("/signin", user.signin);
router.post("/signin", user.post_signin);

// Profile* : Update, Delete
router.post("/profile", user.profile);
router.patch("/profile/edit/:id", user.profile_edit);
router.delete("/profile/edit/:id", user.profile_del);

module.exports = router;

์•ž์„œ ์ •๋ฆฌํ•ด ๋‘” ํŽ˜์ด์ง€์™€ ๊ธฐ๋Šฅ ๊ฐ๊ฐ์— ํ•„์š”ํ•œ ๋ผ์šฐํ„ฐ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค. ๋ผ์šฐํ„ฐ๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋ž‘ ์—ฐ๊ฒฐํ•ด์•ผ ํ•˜๋‹ˆ๊นŒ ํ•ด๋‹น ํŒŒ์ผ๋„ ๋ถˆ๋Ÿฌ์™”๋‹ค.

๐Ÿ’ก router ๋ชจ๋“ˆ ๋‚ด๋ณด๋‚ด๊ธฐ

์•„๋ฌด๋ฆฌ ์ž˜ ์ž‘์„ฑํ•ด๋„ ๋งˆ์ง€๋ง‰์— ๋ชจ๋“ˆ๋กœ ๋‚ด๋ณด๋‚ด์ง€ ์•Š์œผ๋ฉด (๋‹น์—ฐํ•˜๊ฒŒ๋„) ๋ชจ๋“ˆ์„ ์ธ์‹ํ•˜์ง€ ๋ชปํ•ด ์—๋Ÿฌ๊ฐ€ ๋œฌ๋‹ค. Error: Cannot find module

5. ๋ผ์šฐํ„ฐ์— ์—ฐ๊ฒฐํ•  ์ปจํŠธ๋กค๋Ÿฌ ๋ผˆ๋Œ€ ์ž‘์„ฑ

const Users = require("../model/User");

// ํ™ˆ ๋ Œ๋” GET
exports.home = (req, res) => {
    res.render("home");
};

// ํšŒ์›๊ฐ€์ž… ๋ Œ๋” GET
exports.signup = (req, res) => {
    res.render("signup");
};
// ํšŒ์›๊ฐ€์ž… ๊ธฐ๋Šฅ POST
exports.post_signup = (req, res) => {};

// ๋กœ๊ทธ์ธ ๋ Œ๋” GET
exports.signin = (req, res) => {
    res.render("signin");
};
// ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ POST
exports.post_signin = (req, res) => {};

// ํ”„๋กœํ•„ (temporary) POST
exports.profile = (req, res) => {}
// ์ˆ˜์ • PATCH
exports.profile_edit = (req, res) => {};
// ์‚ญ์ œ DELETE
exports.profile_del = (req, res) => {};

๐Ÿ’ก ๋ผ์šฐํ„ฐ์— ์—ฐ๊ฒฐํ•œ ์ปจํŠธ๋กค๋Ÿฌ ์ž‘์„ฑ ์•ˆ ํ•˜๋ฉด

Error: Route.patch() requires a callback function but got a [object Undefined]

์ฝœ๋ฐฑ ํ•จ์ˆ˜, ์ฆ‰ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์—†๋‹ค๋Š” ์—๋Ÿฌ๊ฐ€ ๋œฌ๋‹ค. ๋ผ์šฐํ„ฐ๋ฅผ ๋‹ค ์ž‘์„ฑํ•ด๋‘๊ณ  ์‹ถ๋‹ค๋ฉด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ฝœ๋ฐฑํ•จ์ˆ˜ ํ‹€๋งŒ ์™„์„ฑํ•˜๊ฑฐ๋‚˜ ์•„์ง ์™„์„ฑํ•˜์ง€ ์•Š์€ ๊ธฐ๋Šฅ์€ ์ฃผ์„ ์ฒ˜๋ฆฌํ•˜๊ธธ.

๊ทผ๋ฐ ์ฃผ์„ ์ฒ˜๋ฆฌํ–ˆ๋‹ค๋Š” ๊ฒƒ๋„ ๊นŒ๋จน๋‹ˆ๊นŒ ๋ผ์šฐํ„ฐ์™€ ์ปจํŠธ๋กค๋Ÿฌ๋Š” ๋ฏธ๋ฆฌ ๋‹ค ์—ฐ๊ฒฐ ์ง“๋Š” ๊ฒŒ ์ข‹์€ ๊ฒƒ ๊ฐ™๋‹ค.

6. ๋ชจ๋ธ & ์ปจํŠธ๋กค๋Ÿฌ ๋‚ด์šฉ ์ž‘์„ฑ ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต

sql๋ฌธ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด mysql ๋ชจ๋“ˆ์„ ๋ถˆ๋Ÿฌ์™€ DB์™€ ์—ฐ๊ฒฐํ•˜๋Š” ์ž‘์—…์ด ํ•„์š”ํ•˜๋‹ค.

const mysql = require("mysql");
const conn = mysql.createConnection({
    host: '127.0.0.1',
    user: 'user',
    password: 'mysql ๋น„๋ฐ€๋ฒˆํ˜ธ',
    database: 'db_study'
});

๐Ÿ’ก ์™œ localhost๋ฅผ ์•ˆ ์“ฐ๊ณ ?

์ƒˆ์‹น ์บ ์—์„œ ํ•˜๋˜ ๋Œ€๋กœ ํ˜ธ์ŠคํŠธ์— 'localhost' ๊ธฐ์ž…ํ–ˆ๋”๋‹ˆ ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค.

Error: Connect ECONNREFUSED::1::3000

์—ฌ๊ธฐ์„œ ::1์ด ํฌ์ธํŠธ์˜€๋‹ค. ์ด๋Š” 0:0:0:0:0:0:0:1์˜ ์ค„์ž„๋ง ์ฆ‰ IPv6์„ ๋‚˜ํƒ€๋‚ธ๋‹ค. ํ•˜์ง€๋งŒ mysql์€ IPv4๋งŒ์„ ํ—ˆ์šฉํ•˜๋ฏ€๋กœ IPv6์œผ๋กœ ํ˜ธ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜์ž ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด์—ฌ์ค€ ๊ฑฐ๋‹ค.

์œˆ๋„์šฐ ํ™˜๊ฒฝ์—์„œ๋Š” 'localhost'๋ฅผ ์ž‘์„ฑํ•ด๋„ ๋ฌธ์ œ ์—†์—ˆ๋‹ค. ๊ธ€์„ ์ฐธ์กฐํ•ด๋ณด๋‹ˆ ์šด์˜์ฒด์ œ์˜ ์ฐจ์ด ๊ฐ™๋‹ค. ์ง‘์—์„œ๋Š” ๋งฅ๋ถ์„ ์“ฐ๋Š”๋ฐ OS๋Š” DNS Resolver๊ฐ€ IPv6๋ฅผ ์šฐ์„ ํ•ด์„œ ํƒ์ƒ‰ํ•˜๋Š” ๋“ฏํ•˜๋‹ค.

IPv4๋กœ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋„๋ก 127.0.0.1๋กœ ์ž‘์„ฑํ•˜๋ฉด ๊ฐ„๋‹จ ํ•ด๊ฒฐ!

๐Ÿ’ก ํด๋ผ์ด์–ธํŠธ๊ฐ€ ๊ถŒํ•œ์ด ์—†๋‹ค๋‹ˆ

code: 'ER_NOT_SUPPORTED_AUTH_MODE', errno: 1251, sqlMessage: 'Client does not support authentication protocol requested by server; consider upgrading MySQL client',

๋…ธ๋“œ ํ™˜๊ฒฝ์—์„œ mysql DB ์ ‘์† ์‹œ์—” root ๊ณ„์ •์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ณ„์ •์„ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ํ•˜์—ฌ, user๋ผ๋Š” ์ƒˆ๋กœ์šด ์‚ฌ์šฉ์ž๋ฅผ ๋งŒ๋“ค์–ด์คฌ๋Š”๋ฐ mysql์—์„œ๋Š” localhost ์ฆ‰ ๋‚ด๋ถ€ ํ˜ธ์ŠคํŠธ๋กœ ์„ค์ •๋˜์–ด์žˆ์–ด ํด๋ผ์ด์–ธํŠธ ๊ฐ™์€ ์™ธ๋ถ€ ํ˜ธ์ŠคํŠธ๋Š” ์ ‘๊ทผํ•˜์ง€ ๋ชปํ–ˆ๋˜ ๊ฑฐ๋‹ค.

์•„๋ž˜์ฒ˜๋Ÿผ ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ตฌ๋ฌธ์„ ์‹คํ–‰ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

mysql alter user 'user'@'localhost' identified by mysql_native_password by 'user';

์ˆ˜์—… ์ž๋ฃŒ์—๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆ˜์ • ์‹œ์— ์‚ฌ์šฉํ•  ๊ตฌ๋ฌธ์œผ๋กœ ์ ํ˜€์žˆ๊ธธ๋ž˜ ๋„˜๊ฒผ์—ˆ๋Š”๋ฐ mysql์˜ ๊ธฐ๋ณธ db์— ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด ์™ธ๋ถ€ ํ˜ธ์ŠคํŠธ์˜ ์ ‘๊ทผ์„ ๊ฐ€๋Šฅ์ผ€ํ•˜๋Š” ์„ค์ •์ด์—ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๋ชจ๋ธ์—์„œ sql๋ฌธ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ ๊ธฐ๋Šฅ์— ๋งž๊ฒŒ ์ถ”๊ฐ€/์กฐํšŒ/์ˆ˜์ •/์‚ญ์ œ ํ•ด์ค€๋‹ค. ํด๋ผ์ด์–ธํŠธ์—์„œ ์š”์ฒญ๊ณผ ํ•จ๊ป˜ ์ „๋‹ฌํ•ด ์ค€ ๋ฐ์ดํ„ฐ๋ฅผ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ๋ธ๊ณผ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์„œ๋กœ ์—ฐ๊ฒฐ์ง€์–ด์•ผ ํ•œ๋‹ค. ๋ชจ๋ธ์˜ ๊ฐ ๋ชจ๋“ˆ์„ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํ˜ธ์ถœํ•˜๋ฉด์„œ ํ•„์š”ํ•œ ์ธ์ž๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ์‹์œผ๋กœ ๋ง์ด๋‹ค.

data๋Š” POST/PATCH/DELETE ์š”์ฒญ์„ ํ†ตํ•ด ๋“ค์–ด์˜จ req.body์—์„œ, ์ด๋ ‡๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜จ ํ›„์— ์‘๋‹ต์„ ๋Œ๋ ค์ฃผ์–ด์•ผ undefined ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ cb์— ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋„˜๊ฒจ์ค€๋‹ค.

๋ชจ๋ธ์—์„œ sql๋กœ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•ด์•ผ ํ•  ๊ฒฝ์šฐ, ์ฝœ๋ฐฑํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๊ฒฐ๊ณผ๋ฅผ ์ „๋‹ฌํ•ด ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์ด๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

exports.newUser = function (data, cb) {
    const sql = `INSERT INTO still_user (userid, name, pw)
              VALUES ('${data.userid}', '${data.name}', '${data.pw}')`

    conn.query(sql, (err) => {
        if(err) throw err;
        cb();
    });
}

exports.signIn = function (data, cb) {
    const sql = `select * from still_user
			where userid='${data.userid}'
			and pw='${data.pw}' limit 1`
    
    conn.query(sql, (err, rows) => {
        if(err) throw err;
        cb(rows);
    })
}

exports.get_user = function (id, cb) {
    const sql = `select * from still_user where id='${id}' limit 1`
    
    conn.query(sql, (err, rows) => {
        if(err) throw err;
        cb(rows);
    })
}

exports.editUser = function (data, cb) {
    const sql = `update still_user set userid='${data.userid}',
                  pw='${data.pw}',
                  name='${data.name}'
                  where id='${data.id}' limit 1`
    
    conn.query(sql, (err) => {
        if(err) throw err;
        cb();
    });
}

exports.deleteUser = function (id, cb) {
    const sql = `delete from still_user where id='${id}'`
    
    conn.query(sql, (err) => {
        if(err) throw err;
        cb();
    })
}

์•„๋ž˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋‹ค. ์ด๋•Œ sql๋ฌธ์„ ํ†ตํ•ด ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋Š” ๋ฌด์กฐ๊ฑด ๋ฐฐ์—ด์— ๋‹ด๊ธด๋‹ค. ๊ทธ๋ž˜์„œ ์„ธ๋ถ€ key(ex. id, name)์— ์ ‘๊ทผํ•˜๋ ค๋ฉด ์ธ๋ฑ์‹ฑ์ด ํ•„์ˆ˜๋‹ค. limit 1์œผ๋กœ ์ œํ•œํ•˜๊ธฐ๋„ ํ–ˆ๊ณ , ๋ฌด์—‡๋ณด๋‹ค ๊ธฐ๋ณธ์ ์œผ๋กœ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์„ค์ •ํ•ด์•ผ ํ•˜๋‹ˆ๊นŒ ์–ธ์ œ๋‚˜ ์ธ๋ฑ์‹ฑ ๋„˜๋ฒ„๊ฐ€ 0์ด๋‹ค.

๋ฐฐ์—ด์ด๋ผ๋Š” ์ ์„ ์ด์šฉํ•ด์„œ length ๋ฉ”์„œ๋“œ๋กœ ๊ฒฐ๊ณผ๊ฐ€ ์กด์žฌํ•˜๋ฉด ๋ธŒ๋ผ์šฐ์ €์— ๋ณด์—ฌ์ค„ ๊ฐ’๊ณผ ํ•จ๊ป˜ true๋ฅผ ์ „๋‹ฌํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์„ ๊ฒฝ์šฐ์—” false ๊ฐ’์„ ์ „๋‹ฌํ•˜๊ฒŒ ํ–ˆ๋‹ค.

// ํšŒ์›๊ฐ€์ž… ๊ธฐ๋Šฅ POST
exports.post_signup = (req, res) => {
    Users.newUser(req.body, () => {
        res.send({ result: true });
    });
};

// ๋กœ๊ทธ์ธ ๊ธฐ๋Šฅ POST
exports.post_signin = (req, res) => {
    Users.signIn(req.body, (rows) => {
        if(rows.length > 0) {
            res.send({result: true, id: rows[0].id});
        } else {
            res.send({result: false});
        }
    })
};

// ๋กœ๊ทธ์ธ ํ”„๋กœํ•„ (temporary) POST
exports.profile = (req, res) => {
    Users.get_user(req.body.id, (row) => {
        if(row.length > 0) {
            res.render("profile", {data: row[0]});
        }
        else {
            res.redirect("/signin");
        }
    });
}
// ์ˆ˜์ • PATCH
exports.profile_edit = (req, res) => {
    const data = {
        ...req.body,
        id: req.params.id
    };
    Users.editUser(data, () => {
        res.send({ result: true });
    })
};
// ์‚ญ์ œ DELETE
exports.profile_del = (req, res) => {
    Users.deleteUser(req.params.id, () => {
        res.send({result: true});
    });
};

๐Ÿ”† ๊ด€๊ฑด์€ ๋กœ๊ทธ์ธ ํ™”๋ฉด๊ณผ ํ”„๋กœํ•„ ํ™”๋ฉด์˜ ์—ฐ๊ฒฐ

๋กœ๊ทธ์ธ ํ›„, ํ”„๋กœํ•„ ํ™”๋ฉด์œผ๋กœ ๋„˜์–ด๊ฐˆ ๋•Œ ๊ธฐ์กด ๋กœ๊ทธ์ธ ์ •๋ณด๊ฐ€ ๊ทธ๋Œ€๋กœ ๋‹ด๊ฒจ์•ผ ํ•œ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ ์„ธ์…˜ ๊ฐ™์€ ๋ฐฉ์‹์„ ์•„์ง ๋ฐฐ์šฐ์ง€ ์•Š์•„์„œ ๋กœ๊ทธ์ธ์„ ์œ ์ง€ํ•  ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฅธ๋‹ค..

๋Œ€์‹  ์ผ๋ฐ˜ ํผ ์ „์†กํ•˜๋ฉด ์ˆจ๊ฒจ์ง„ input์œผ๋กœ ํŠน์ • ๊ฐ’์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ๋‹ค๊ฐ€ ์ƒˆ๋กœ์šด ํ™”๋ฉด์„ ๋ Œ๋”ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฑธ ํ™œ์šฉํ–ˆ๋‹ค. ์‚ฌ์šฉ์ž์˜ ๊ณ ์œ ํ•œ ์ •๋ณด์ด์ž PKํ‚ค์ธ id๋ฅผ hidden input์— ์ €์žฅํ•ด๋‘์–ด ํ”„๋กœํ•„ ํ™”๋ฉด์„ ๋ Œ๋”ํ•˜๋ฉด value์— ํ•ด๋‹น ๊ฐ’์ด ์ž…๋ ฅ๋˜๋„๋ก ์„ธํŒ…ํ•œ๋‹ค.

๊ทธ๋ž˜์„œ ๋กœ๊ทธ์ธ ๊ฒฐ๊ณผ์— id ๊ฐ’๋„ ๋„˜๊ธฐ๊ณ , ํ”„๋กœํ•„ ๋ Œ๋”ํ•  ๋•Œ input์— ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ ํ•  ์œ ์ € ์ •๋ณด๋„ ๋„˜๊ฒผ๋‹ค.

7. ๋ทฐ ์ž‘์„ฑ (+๋ฒ„ํŠผ ์ด๋ฒคํŠธ)

// signin.ejs

// ์ƒ๋žต

    <form name="user-form">
        <div>
            <input type="text" name="userid" placeholder="ID" />
            <input type="password" name="pw" placeholder="PASSWORD" />
            <button type="button" onclick="signIn()">Sign In</button>
        </div>
    </form>
    <form name="hidden-form" action="/profile" method="post">
        <input type="hidden" name="id" />
    </form>

// ์ƒ๋žต

        function signIn() {
            const form = document.forms["user-form"]
                const data = {
                userid: form.userid.value,
                pw: form.pw.value,
            };

            axios({
                method: "POST",
                url: "/signin",
                data: data
            }).then((res) => {
                if (res.data.result) {
                    alert("๋กœ๊ทธ์ธ ์„ฑ๊ณต!");
                    const form = document.forms["hidden-form"];
                    form.id.value = res.data.id
                    form.submit();
                } else {
                    alert("์•„์ด๋””๋‚˜ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ™•์ธํ•˜์„ธ์š”.");
                };
            });
        };

์„œ๋ฒ„์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„ axios๋กœ ์š”์ฒญ์„ ๋ณด๋‚ธ ๋’ค, ์„œ๋ฒ„์—์„œ ๋ณด๋‚ด์˜จ ์‘๋‹ต์„ ๋ฐ›๊ณ  ๊ทธ ์‘๋‹ต ์ค‘ ํ•˜๋‚˜์ธ ์‚ฌ์šฉ์ž์˜ id๋ฅผ ํžˆ๋“  ํผ input์˜ ๊ฐ’์œผ๋กœ ์ง€์ •ํ•œ๋‹ค. ๊ทธ ์ƒํƒœ๋กœ submit ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํผ ์ „์†ก ์™„๋ฃŒ๋‹ค.

์•ž์„œ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํ”„๋กœํ•„ ํ™”๋ฉด์„ ๋ Œ๋”ํ•  ๋•Œ ์‚ฌ์šฉ์ž์˜ ๋ฐ์ดํ„ฐ๋„ ํ•จ๊ป˜ ๋ณด๋ƒˆ๊ธฐ ๋•Œ๋ฌธ์— ejs ๋ฌธ๋ฒ•์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ ํ•  ์ˆ˜ ์žˆ๋‹ค.

// profile.ejs
  
// ์•ž ๋’ค ์ฝ”๋“œ ์ƒ๋žต
 <input type="hidden" name="id" value=<%= data.id %> />

๐Ÿ’ก ์ˆ˜์ •/ํŽธ์ง‘ url์€ params๋ฅผ ์“ฐ๋”๋งŒ

ํšŒ์› ์ˆ˜์ •๊ณผ ์‚ญ์ œ๋Š” ๊ฐ ํšŒ์›์˜ ๊ณ ์œ  ๊ฐ’์ธ id๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌ๋ถ„ํ•˜๋ฏ€๋กœ ํ”„๋ก ํŠธ์—”๋“œ ๋‹จ์—์„œ ์š”์ฒญํ•  axios์˜ url์—๋„ ๊ฐœ๋ณ„์ ์ธ id๋ฅผ ๋‹ด์•„์•ผ ํ•œ๋‹ค.

ํ”„๋กœํ•„ ํ™”๋ฉด์„ ๋ Œ๋”ํ•˜๋ฉด์„œ ํ•ด๋‹น ์‚ฌ์šฉ์ž์˜ ๋ชจ๋“  ์ •๋ณด๋ฅผ input์— ๋ฐ”์ธ๋”ฉํ–ˆ๋˜ ๊ฑธ ๊ณ ๋ คํ•ด ๊ทธ value๋ฅผ ๋ณ€์ˆ˜๋กœ ์ž‘์„ฑํ•ด์ฃผ๋ฉด ๋œ๋‹ค.

        function userEdit() {
            const form = document.forms["user-form"];
            const data = {
                userid: form.userid.value,
                pw: form.pw.value,
                name: form.name.value
            }
            axios({
                method: "patch",
                url: `/profile/edit/${form.id.value}`,
                data: data
            }).then((res) => {
                if(res.data.result) {
                    alert("ํšŒ์› ์ •๋ณด ์ˆ˜์ •");
                } else {
                    alert("๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.");
                };
            });
        };

input์˜ id๋งŒ ๋ฐ์ดํ„ฐ๋ฐ”์ธ๋”ฉ์„ ์•ˆ ํ•ด์ค˜์„œ ๊ณ„์† 404 ์„œ๋ฒ„ ์—๋Ÿฌ๊ฐ€ ๋‚ฌ์—ˆ๋‹ค. ํผ์˜ id ๋ถ€๋ถ„์€ disabled๋กœ ๋งŒ๋“ค์–ด๋‘ฌ์„œ ์‚ฌ์šฉ์„ ๋ชปํ•œ๋‹ค๊ณ  ์ฐฉ๊ฐํ•˜๋Š” ๋ฐ”๋žŒ์— ๋Œ€์ฒด id์˜ value๋ฅผ ์–ด๋””์„œ ๊ฐ€์ ธ์˜ค๋ฉด ๋ ์ง€ ์˜ค๋ž˜ ๊ณ ๋ฏผํ–ˆ๋‹ค.

์ •๋ฆฌํ•˜์ž๋ฉด

ํฐ ๋งฅ๋ฝ์„ ์ด๋ ‡๊ฒŒ ์จ๋ณผ ์ˆ˜๋„ ์žˆ๊ฒ ๋‹ค.

  • ์–ด๋–ค ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค์ง€ ๊ธฐํšํ•˜๊ณ 
  • ์ด ๊ธฐ๋Šฅ์ด ๋‹ด๊ธธ ์ „์ฒด ๊ตฌ์กฐ์™€ ํ๋ฆ„์„ ํŒŒ์•…ํ•˜๊ณ 
  • ๊ฐ ๊ธฐ๋Šฅ์— ํ•„์š”ํ•œ ํŽ˜์ด์ง€๋ฅผ ๋งŒ๋“ค์–ด
  • ํŽ˜์ด์ง€๋งˆ๋‹ค ๋ฌด์–ผ ๋ณด์—ฌ์ค„์ง€ ์ƒ๊ฐํ•ด
  • ์–ด๋–ค ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฐ€๊ณตํ•˜์—ฌ
  • ํ™”๋ฉด ๊ตฌํ˜„ํ•˜๊ธฐ

๋ง๋ถ™์ด๋Š” ๋ง

๐ŸŒฑ ์ด ์˜ˆ์ œ๋ฅผ 4๋ฒˆ ์ •๋„ ๊ตฌํ˜„ํ•ด๋ดค๋‹ค. ํ•œ ๋ฒˆ์€ CR๋งŒ ์™„์„ฑํ–ˆ๊ณ , ๊ทธ ๋‹ค์Œ์—” CRUD ๋ชจ๋‘๋ฅผ ํ•ด๋ดค๊ณ , ์ง‘์—์„œ sequelize๋กœ ์™„์„ฑํ•ด๋ณด๊ณ , ์˜ค๋Š˜ ์ˆ˜์—…์—์„œ๋Š” sequelize๋กœ ํ•˜๋˜ ์ƒˆ ํ”„๋กœ์ ํŠธ๊ฐ€ ์•„๋‹Œ ์ง€๋‚œ ํ”„๋กœ์ ํŠธ์— ๊ทœ๋ชจ๋ฅผ ํ‚ค์šฐ๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ–ˆ๋‹ค.

๐ŸŒฑ ์ „๋‚  ์ง‘์—์„œ ์‹ค์Šต์„ ํ•œ ๋ฒˆ ํ–ˆ์œผ๋‹ˆ ๋‹ค์‹œ ํ•ด๋ณด๋ฉด ์ˆ˜์›”ํ•  ๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ... ๊ธฐ์กด ํ”„๋กœ์ ํŠธ๋ฅผ ์œ ์ง€ํ•˜๋ฉฐ ๋ชธ์ง‘์„ ํ‚ค์šฐ๋Š” ๊ฒŒ ์ƒ๊ฐ๋ณด๋‹ค ๊นŒ๋‹ค๋กœ์› ๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ์˜คํƒˆ์ž๊ฐ€ ์™œ์ด๋ฆฌ ๋งŽ์ด ๋‚˜๋˜์ง€! ๋Œ€๋ฌธ์ž ํ•˜๋‚˜ ๋•Œ๋ฌธ์— ์‹ค์Šต ์‹œ๊ฐ„์„ ๊ฑฐ์˜ ๋‹ค ์ผ๊ณ , ํ•œ ๋ฒˆ ํ๋ฆ„์ด ๊นจ์ง„ ํ›„์— ๋‹ค์‹œ ํ•˜๋ ค๋‹ค ๋ณด๋‹ˆ๊นŒ ํ๋ฆ„์ด ๋„ˆ๋ฌด ํ—ท๊ฐˆ๋ ธ๋‹ค.

๐ŸŒฑ ๋•๋ถ„์— ๋ธ”๋กœ๊ทธ ์ฃผ์ œ๋ฅผ ์ •ํ–ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๊ธ€๋กœ ์ ์œผ๋ฉฐ ์ˆœ์„œ๋ฅผ ํ™•์ธํ•˜๋‹ˆ๊นŒ ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋””๋กœ ๋„˜์–ด๊ฐ€์„œ ์–ด๋–ป๊ฒŒ ๋ณด์—ฌ์ง€๋Š”์ง€ ํ๋ฆ„์ด ์žกํžŒ๋‹ค. ์•„์ฃผ ์‹ ๋‚˜๋Š” ๋ฐœ๊ฒฌ!

๐ŸŒฑ ์ด์ „๊นŒ์ง„ ์—๋Ÿฌ ๋งŒ๋‚˜๋ฉด (ํ—‰) ํ–ˆ๋Š”๋ฐ ์•„๋ฌด๋ฆฌ ๋งŽ์€ ์—๋Ÿฌ๋ฅผ ๋งŒ๋‚˜๋„ ๊ฒฐ๊ตญ์—” ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹จ ๋ฏฟ์Œ์ด ์ƒ๊ฒผ๋Š”์ง€.. ์›์ธ ์ฐพ๊ณ  ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์— ์ง‘์ค‘ํ•˜๊ฒŒ ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—๋Ÿฌ ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” ์™„๋ฒฝํ•œ ์ƒํƒœ๋ณด๋‹ค ํ’€์–ด๊ฐ€๋Š” ๊ณผ์ •์ด ๋” ์žฌ๋ฐŒ๋Š” ๋“ฏ.

profile
์ผ๋‹จ ํ•ด๋ณด๋Š” ํŽธ
post-custom-banner

0๊ฐœ์˜ ๋Œ“๊ธ€