Notice
Recent Posts
Recent Comments
Link
ยซ   2024/05   ยป
์ผ ์›” ํ™” ์ˆ˜ ๋ชฉ ๊ธˆ ํ† 
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
๊ด€๋ฆฌ ๋ฉ”๋‰ด

lgvv98

[Node.js] ๋ชฝ๊ณ ๋””๋น„ ๋ณธ๋ฌธ

๐Ÿ›ฐ๏ธ Node.js

[Node.js] ๋ชฝ๊ณ ๋””๋น„

๐Ÿฅ• ์บ๋Ÿฟ๋งจ 2023. 8. 10. 22:26

๋ชฝ๊ณ ๋””๋น„

 

์ด ์žฅ์—์„œ๋Š” ๋ชฝ๊ณ ๋””๋น„๋ฅผ ์•Œ์•„๋‘”๋‹ค๋ฉด ๋”์šฑ ๋” ๋‹ค์–‘ํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

 

๋ชฝ๊ณ ๋””๋น„์˜ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๋Š” ์ž์Šค ๋ฌธ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ชฝ๊ณ ๋””๋น„ ์‚ฌ์šฉํ•˜๋ฉด ์ž์Šค๋งŒ์œผ๋กœ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Œ.

 

 

# NoSQL vs SQL

MySQL์€ SQL์„ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋‹ค. ๋ฐ˜๋ฉด์— SQL ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” NoSQL(Not Only SQL)์ด๋ผ๊ณ  ๋ถ€๋ฅด๋Š” ๋ฐ๋ฒ ๋„ ์žˆ๋‹ค.

 

์—ฌ๋Ÿฌ ์ธก๋ฉด์—์„œ ๋‹ค๋ฅด์ง€๋งŒ ๋ช‡๊ฐ€์ง€๋งŒ ์•Œ์•„๋ณด์ž.

์ฐจ์ด์ 

 

NoSQL์—๋Š” ๊ณ ์ •๋œ ํ…Œ์ด๋ธ” ์—†์Œ. ํ…Œ์ด๋ธ”์— ์‚ฌ์‘ํ•˜๋Š” ์ปฌ๋ ‰์…˜์ด๋ž€ ๊ฐœ๋…์€ ์žˆ์œผ๋‚˜ ์นผ๋Ÿผ์„ ๋”ฐ๋กœ ์ •์˜ํ•˜์ง€ ใ…‡๋‚ณ์Œ

 

MySQL์€ users ํ…Œ์ด๋ธ”์„ ๋งŒ๋“ค ๋•Œ name, age, married ๋“ฑ์˜ ์นผ๋Ÿผ๊ณผ ์ž๋ฃŒํ˜• ์˜ต์…˜๋“ฑ์„ ์ •์˜ํ•˜์ง€๋งŒ ๋ชฝ๊ณ ๋””๋น„๋Š” ๊ทธ๋ƒฅ users ์ปฌ๋ ‰์…˜์„ ๋งŒ๋“ค๊ณ  ๋. ์–ด๋– ํ•œ ๋ฐ์ดํ„ฐ๋„ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ.

 

๋ชฝ๊ณ ๋””๋น„๋Š” JOIN์—†๋‹ค. ๊ทธ๋Ÿผ์—๋„ ์“ฐ๋Š” ์ด์œ ๋Š” ํ•™์žฅ์„ฑ๊ณผ ๊ฐ€์šฉ์„ฑ.

 

ํ•ญ๊ณต์‚ฌ ์˜ˆ์•ฝ ํ”„๋กœ๊ทธ๋žจ ๋งŒ๋“ ๋‹ค๋ฉด ์˜ˆ์•ฝ์ •๋ณด๋Š” MySQL ์ฑ„ํŒ…๊ฐ™์€ ๋ถ€๋ถ„์€ NoSQL

 

# ๋ชฝ๊ณ ๋””๋น„์„ค์น˜

brew tap mongodb/brew
brew install mongodb-community
brew install mongosh

๋งฅ์˜ ๊ฒฝ์šฐ /usr/local/var/mongodb

 

๋ชฝ๊ณ ๋””๋น„ ์‹คํ–‰

brew services start mongodb-community

์ด์ œ ๋ชฝ๊ณ ๋””๋น„ ํ”„๋กฌํ”„ํŠธ์— ์ ‘์†ํ•˜์ž. ์ฝ˜์†”์— mongosh ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•ด๋ณด์ž

mongosh
test>

ํ˜น์‹œ ์ ‘์†์ด ๋˜์ง€ ์•Š๋Š”๋‹ค๋ฉด brew services restart mongodb-community๋กœ ์„œ๋น„์Šค๋ฅผ ์žฌ์‹œ์ž‘ํ•œ ๋’ค ๋‹ค์‹œ mongodb๋กœ ์ ‘์†ํ•ฉ๋‹ˆ๋‹ค.

 

์ง€๊ธˆ์€ ๋ˆ„๊ตฌ๋‚˜ ์ ‘์†ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ๊ด€๋ฆฌ์ž ๊ณ„์ •์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

use admin
switched to db admin
admin> db.createUser({ user: '์ด๋ฆ„', pwd: '๋น„๋ฐ€๋ฒˆํ˜ธ', roles: ['root']})
{ ok: 1 }

db.createUser๋กœ ๊ณ„์ •์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

roles๋กœ๋Š” ๋ชจ๋“  ๊ถŒํ•œ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” root๋ฅผ ๋ถ€์—ฌํ–ˆ๋‹ค.

 

๋ชฝ๊ณ ๋””๋น„ ์ข…๋ฃŒํ•˜๊ณ 

brew services stop mongodb-community

 

์‹œํ๋ฆฌํ‹ฐ ์„ค์ •

์ธํ…”
vim /usr/local/etc/mongod.conf

์‹ค๋ฆฌ์ฝ˜
vim /opt/homebrew/etc/mongod.conf

ํ•œ ํ›„
...
sercurity:
	authorization: enabled
    
    ์ž…๋ ฅํ›„ ์ €์žฅ(wq)

 

๋‹ค์‹œ ์‹คํ–‰startํ•˜๊ณ 

monogsh admin -u ์ด๋ฆ„ -p ๋น„๋ฐ€๋ฒˆํ˜ธ

์ž…๋ ฅํ•˜๋ฉด

admin> ๋ ๊ฑฐ์ž„.

 

# ์ปดํผ์Šค ์„ค์น˜

brew install --cask mongodb-compass-community

https://www.mongodb.com/try/download/compass

 

Try MongoDB Tools - Download Free Here

Free download for MongoDB tools to do more with your database. MongoDB Shell, Compass, CLI for Cloud, BI Connector and other database tools available.

www.mongodb.com

์„ค์น˜ํ•˜๋ฉด ๋Ÿฐ์น˜ํŒจ๋“œ์— ๋‚˜ํƒ€๋‚˜๋Š”๋ฐ ์•ˆ๋ ๋•Œ๋Š” ํ•ด๋‹น ์‚ฌ์ดํŠธ ์ง์ ‘ ๋“ค์–ด๊ฐ€์„œ ํ•˜๋ฉด ๋ผ

 

Advanced Connection Options -> Username/Password๋กœ ๋ฐ”๊พธ๊ณ 

 

Username์ด๋ž‘ password ๋นˆ ์นธ์œผ๋กœ ๋‘” ์ฑ„ ์ž…๋ ฅํ•˜๋ฉด ์„ธ์ด๋ธŒ

 

๋‹ค์‹œ ์ฝ˜์†”์—์„œ

brew services start mongodb-community
mongosh

 

๋ฐ์ดํ„ฐ ๋ฒ ์ด์Šค ๋งŒ๋“œ๋Š” ๋ช…๋ น์–ด๋Š”

use nodejs

 

๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋ชฉ๋ก์„ ํ™•์ธํ•˜๋Š” ๋ช…๋ น์–ด๋Š”

show dbs

 

ํ˜„์žฌ ์‚ฌ์šฉ์ค‘์ธ ๋ฐ๋ฒ  ํ™•์ธํ•˜๋Š” ๋ช…๋ น์–ด๋Š”

db

๋ฐ๋ฒ  ๋ชฉ๋ก์€ ์—†์ง€๋งŒ nodejs ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ ์•Œ ์ˆ˜ ์žˆ์Œ.

 

์ปฌ๋ ‰์…˜ ๋งŒ๋“ค๋ ค๋ฉด

nodejs> db.createCollection('users')
nodejs> db.createCollection('comments')

 

# CRUD ์ž‘์—…ํ•˜๊ธฐ

 

๋ชฝ๊ณ ๋””๋น„์—์„œ CRUD์ž‘์—…ํ•ด๋ณด์ž.

 

# Create(์ƒ์„ฑ)

Date๋‚˜ ์ •๊ทœํ‘œํ˜„์‹๊ณผ ๊ฐ™์€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๊ฐ์ฒด๋ฅผ ์ž๋ฃŒํ˜•์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ. Binary Data, OjectId, Int, Long, Demical, Timestamp, JavaScript ๋“ฑ ์ถ”๊ฐ€์ ์ธ ์ž๋ฃŒํ˜• ์กด์žฌ. ๊ทธ๋Ÿฌ๋‚˜ ObjectId, Binary Data, Timestamp ์™ธ์—๋Š” ์ž˜ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  Undefined์™€ Symbol์€ ๋ชฝ๊ณ ๋””๋น„์—์„œ ์ž๋ฃŒํ˜•์œผ๋กœ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ.

 

ObjectId๋Š” MySQL์—์„œ ํ‚ค ๊ฐ’๊ณผ ๊ฐ™๋‹ค.

 

์ œ๋กœ์ถ”๊ฐ€

db.users.insertOne({ name: 'zero', age: 24, married: false, comment: '์•ˆ๋…•ํ•˜์„ธ์š”. ๋ชฝ๊ณ ๋””๋น„ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž', createAt: new Date()  })

๋„ค๋กœ์ถ”๊ฐ€

 

 

db.users.insertOne({ name: 'nero', age: 32, married: true, comment: '์•ˆ๋…•ํ•˜์„ธ์š”. zero์นœ๊ตฌ nero์ž…๋‹ˆ๋‹ค', createAt: new Date() }

 

๋Œ“๊ธ€ ์ถ”๊ฐ€

db.comments.insertOne({ commenter: ObjectId('64d477ea74ecde1716e7628e'), comment: '์•ˆ๋…•ํ•˜์„ธ์š” zero์ž…๋‹ˆ๋‹ค', createAt: new Date()})

 

# Read(์กฐํšŒ)

 

find({});๋Š” ์ปฌ๋ ‰์…˜ ๋‚ด์˜ ๋ชจ๋“  ๋‹คํ๋จผํŠธ๋ฅผ ์กฐํšŒํ•˜๋ผ๋Š” ์˜๋ฏธ

db.users.find({});

// ๊ฒฐ๊ณผ
[
  {
    _id: ObjectId("64d477ea74ecde1716e7628e"),
    name: 'zero',
    age: 24,
    married: false,
    comment: '์•ˆ๋…•ํ•˜์„ธ์š”. ๋ชฝ๊ณ ๋””๋น„ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์ž',
    createAt: ISODate("2023-08-10T09:38:50.539Z")
  },
  {
    _id: ObjectId("64d4783974ecde1716e7628f"),
    name: 'nero',
    age: 32,
    married: true,
    comment: '์•ˆ๋…•ํ•˜์„ธ์š”. zero์นœ๊ตฌ nero์ž…๋‹ˆ๋‹ค',
    createAt: ISODate("2023-08-10T09:40:09.292Z")
  }
]

 

ํŠน์ • ํ•„๋“œ๋งŒ ์กฐํšŒํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด

 

find๋ฉ”์„œ๋“œ์˜ ๋‘๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ์กฐํšŒํ•  ํ•„๋“œ๋ฅผ ๋„ฃ๋Š”๋‹ค 1๋˜๋Š” true๋กœ ํ‘œ์‹œํ•œ ํ•„๋“œ๋งŒ ๊ฐ€์ ธ์˜จ๋‹ค.

_id๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜์—ˆ์–ด์„œ 0๋˜๋Š” false ์ž…๋ ฅํ•ด ๊ฐ€์ ธ์˜ค์ง€ ์•Š๊ฒŒ ํ–‰ํ–ํ•œ๋‹ค.

db.users.find({}, {_id: 0, name: 1, married: 1});

[ { name: 'zero', married: false }, { name: 'nero', married: true } ]

 

์กฐํšŒ์‹œ ์กฐ๊ฑด์„ ์ข€ ๋” ์ค˜๋ณด์ž

 

$gt๋Š” ์ดˆ๊ณผ์ด๋ž€ ๋œป

gt ์ดˆ๊ณผ

gte ์ด์ƒ

lt ๋ฏธ๋งŒ

lte ์ดํ•˜

ne ๊ฐ™์ง€ ์•Š์Œ

or ๋˜๋Š”

in ๋ฐฐ์—ด ์† ์š”์†Œ ์ค‘ํ•˜๋‚˜

 

 db.users.find({age: { $gt: 30 }, married: true} ,{_id: 0, name: 1, married: 1});
 
 // ๊ฒฐ๊ณผ
 [ { name: 'nero', married: true } ]

 

or์„ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ๋‹ค.

 

db.users.find({ $or: [{ age: { $gt: 30 } }, { married: false }] }, { _id: 0, name: 1, age: 1 });

// ๊ฒฐ๊ณผ
[ { name: 'zero', age: 24 }, { name: 'nero', age: 32 } ]

 

์ด๋ฒˆ์—๋Š” ์ •๋ ฌ

db.users.find({}, { _id: 0, name: 1, age: 1 }).sort({ age: -1 })

// ๊ฒฐ๊ณผ
[ { name: 'nero', age: 32 }, { name: 'zero', age: 24 } ]

 

๊ฐœ์ˆ˜์ œํ•œ

db.users.find({}, { _id: 0, name: 1, age: 1 }).sort({ age: -1 }).limit(1)

// ๊ฒฐ๊ณผ
[ { name: 'nero', age: 32 } ]

 

๋‹คํ๋จผํŠธ ๊ฐœ์ˆ˜ ๋ช‡๊ฐœ ๊ฑด๋„ˆ๋›ฐ๊ธฐ๋„ ๊ฐ€๋Šฅ

db.users.find({}, { _id: 0, name: 1, age: 1 }).sort({ age: -1 }).limit(1).skip(1)

// ๊ฒฐ๊ณผ
[ { name: 'zero', age: 24 } ]

 

# Update(์ˆ˜์ •)

 

db.users.updateOne( { name: 'nero' }, { $set: { comment: '์•ˆ๋…•ํ•˜์„ธ์š”. ์ด ํ•„๋“œ๋ฅผ ๋ฐ”๊ฟ”๋ด…์‹œ๋‹ค' } });

// ๊ฒฐ๊ณผ
{
  acknowledged: true,
  insertedId: null,
  matchedCount: 1,
  modifiedCount: 1,
  upsertedCount: 0
}

$set์ด๋ผ๋Š” ์—ฐ์‚ฐ์ž๋Š” ์–ด๋–คํ•„๋“œ๋ฅผ ์ˆ˜์ •ํ• ์ง€ ์ •ํ•˜๋Š” ์—ฐ์‚ฐ์ž ์ด๊ฑฐ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ผ๋ฐ˜ ๊ฐ์ฒด๋ฅผ ๋„ฃ๋Š”๋‹ค๋ฉด ๋‹คํ๋จผํŠธ ํ†ต์จฐ๋กœ ๋‘๋ฒˆ์จฐ ์ธ์ˆ˜๋กœ ์ฃผ์–ด์ง„ ๊ฐ์ฒด๋กœ ์ˆ˜์ •๋œ๋‹ค.

 

set

#  Delete(์‚ญ์ œ)

db.users.deleteOne({ name: 'nero' })

์‚ญ์ œํ•  ๋‹คํ๋จผํŠธ์— ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๊ฐ์ฒด ์ œ๊ณตํ•˜๋ฉด ๋œ๋‹ค.

 

#  ๋ชฝ๊ตฌ์Šค ์‚ฌ์šฉํ•˜๊ธฐ

MySQL์—๋Š” ์‹œํ€„๋ผ์ด์ €? ๊ทธ๋Ÿผ ๋ชฝ๊ณ ๋””๋น„๋Š” ๋ชฝ๊ตฌ์Šค

๋ชฝ๊ตฌ์Šค๋Š” ์‹œํ€„๋ผ์ด์ฆˆ์™€ ๋‹ฌ๋ฆฌ ODM์ด๋ผ๊ณ  ๋ถˆ๋ฆผ. ๋ชฝ๊ณ  ๋””๋น„๋Š” ๋ฆด๋ ˆ์ด์…˜์ด ์•„๋‹ˆ๋ผ ๋‹คํ๋จผํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ORM์ด ์•„๋‹ˆ๋ผ ODM์ž„.

 

๋จผ์ € ์Šคํ‚ค๋งˆ๋ผ๋Š”๊ฒŒ ์ƒ๊น€ ๋ชฝ๊ณ ๋””๋น„๋Š” ํ…Œ์ด๋ธ”์ด ์—†์–ด์„œ ์ž์œ ๋กญ๊ฒŒ ํ…Œ์ด๋ธ” ๋ฐ์ดํ„ฐ๋ฅผ ๋„ฃ์„ ์ˆ˜ ์žˆ์ง€๋งŒ ์ž์œ ๋กœ์›€์ด ๋ถˆํŽธํ•จ์„ ์ดˆ๋ž˜ํ•˜๊ธฐ๋„ ํ•จ. 

 

JOIN๊ธฐ๋Šฅ์„ populate๋ผ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์–ด๋Š ์ •๋„ ๋ณด์™„

 

package.json์ƒ์„ฑ

{
  "name": "learn-sequelize",
  "version": "0.0.1",
  "description": "์‹œํ€„๋ผ์ด์ฆˆ๋ฅผ ๋ฐฐ์šฐ์ž",
  "main": "app.js",
  "scripts": {
    "start": "nodemon app"
  },
  "author": "ZeroCho",
  "license": "MIT",
  "dependencies": {
    "express": "^4.17.1",
    "morgan": "^1.10.0",
    "mysql2": "^2.1.0",
    "nunjucks": "^3.2.2",
    "sequelize": "^6.3.4",
    "sequelize-cli": "^6.2.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.4"
  }
}
npm i express morgan nunjucks mongoose
npm i -D nodemon

๋ชฝ๊ตฌ์Šค์— ํ•„์š”ํ•œ ํŒจํ‚ค์ง€ ์„ค์น˜

 

๋ชฝ๊ณ ๋””๋น„ ์—ฐ๊ฒฐํ•˜๊ธฐ

๋ชฝ๊ณ ๋””๋น„๋Š” ์ฃผ์†Œ๋ฅผ ์‚ฌ์šฉํ•ด ์—ฐ๊ฒฐ

mongodb://[username:password@]host[:port][/[database][?options]]

mongodb://์ด๋ฆ„:๋น„๋ฐ€๋ฒˆํ˜ธ@localhost:27017/admin

์ด ํ˜•ํƒœ์™€ ๊ฐ™๋‹ค. [ ] ๋ถ€๋ถ„์€ ์žˆ์–ด๋„ ๋˜๊ณ  ์—†์–ด๋„ ๊ทธ๋งŒ!

 

schemas ํด๋”๋ฅผ ๋งŒ๋“  ๋‹ค์Œ์— index.jsํŒŒ์ผ์„ ์ƒ์„ฑ

const mongoose = require('mongoose');

const connect = () => {

	if (process.env.NODE_ENV != 'production') { 
        mongoose.set('debug', true);
    }
    
    mongoose.connect('mongodb://localhost:27017'), { // โœ… ์ด๊ฑฐ ๊ฐœ์ค‘์š”
        dbName: 'nodejs',
        useNewUrlParser: true,
    }, (error) => { 
        if error { 
           console.log('๋ชฝ๊ณ ๋””๋น„ ์—ฐ๊ฒฐ', error);
        } else { 
           console.log('๋ชฝ๊ณ ๋””๋น„ ์—ฐ๊ฒฐ ์„ฑ๊ณต');
        }
    });
};

mongoose.connection.on('error', (error) => { 
	console.error('๋ชฝ๊ณ ๋””๋น„ ์—ฐ๊ฒฐ ์—๋Ÿฌ', error);
});

mongoose.connection.on('error', (error) => { 
	console.error('๋ชฝ๊ณ ๋””๋น„ ์—ฐ๊ฒฐ์ด ๋Š๊ฒผ์Šตใ„ด๋””ใ…. ์—ฐ๊ฒฐ์„ ์žฌ์‹œ๋„ ํ•ฉ๋‹ˆ๋‹ค.', error);
});

module.exports = connect;

๊ฐœ๋ฐœ ํ™˜๊ฒฝ์ผ ๋•Œ๋งŒ ์ฝ˜์†”์„ ํ†ตํ•ด ๋ชฝ๊ตฌ์Šค๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ์ฟผ๋ฆฌ ๋‚ด์šฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ์ฝ”๋“œ

 

 

 

 

์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ํ•ด๋ณด์ž 

const mongoose = require('mongoose');

const { Schema } = mongoose;
const userSchema = new Schema({
  name: {
    type: String,
    required: true,
    unique: true,
  },
  age: {
    type: Number,
    required: true,
  },
  married: {
    type: Boolean,
    required: true,
  },
  comment: String,
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

module.exports = mongoose.model('User', userSchema);
const mongoose = require('mongoose');

const { Schema } = mongoose;
const userSchema = new Schema({
  name: {
    type: String,
    required: true,
    unique: true,
  },
  age: {
    type: Number,
    required: true,
  },
  married: {
    type: Boolean,
    required: true,
  },
  comment: String,
  createdAt: {
    type: Date,
    default: Date.now,
  },
});

module.exports = mongoose.model('User', userSchema);

์ปฌ๋ ‰์…˜ ์ด๋ฆ„ ๋ฐ”๊พธ๊ธฐ

mongoose.model('User', userSchema, 'user_table');

User์ผ ๊ฒฝ์šฐ user๋กœ ๊ฐ•์ œ๋กœ ์ƒ์„ฑ๋˜๋Š”๋ฐ ์œ„์ฒ˜๋Ÿผ ๋ฐ”๊พธ๊ธฐ ๊ฐ€๋Šฅ

 

 

# ์ฟผ๋ฆฌ ์ˆ˜ํ–‰ํ•˜๊ธฐ

// ์‚ฌ์šฉ์ž ์ด๋ฆ„ ๋ˆŒ๋ €์„ ๋•Œ ๋Œ“๊ธ€ ๋กœ๋”ฉ
document.querySelectorAll('#user-list tr').forEach((el) => {
  el.addEventListener('click', function () {
    const id = el.querySelector('td').textContent;
    getComment(id);
  });
});
// ์‚ฌ์šฉ์ž ๋กœ๋”ฉ
async function getUser() {
  try {
    const res = await axios.get('/users');
    const users = res.data;
    console.log(users);
    const tbody = document.querySelector('#user-list tbody');
    tbody.innerHTML = '';
    users.map(function (user) {
      const row = document.createElement('tr');
      row.addEventListener('click', () => {
        getComment(user._id);
      });
      // ๋กœ์šฐ ์…€ ์ถ”๊ฐ€
      let td = document.createElement('td');
      td.textContent = user._id;
      row.appendChild(td);
      td = document.createElement('td');
      td.textContent = user.name;
      row.appendChild(td);
      td = document.createElement('td');
      td.textContent = user.age;
      row.appendChild(td);
      td = document.createElement('td');
      td.textContent = user.married ? '๊ธฐํ˜ผ' : '๋ฏธํ˜ผ';
      row.appendChild(td);
      tbody.appendChild(row);
    });
  } catch (err) {
    console.error(err);
  }
}
// ๋Œ“๊ธ€ ๋กœ๋”ฉ
async function getComment(id) {
  try {
    const res = await axios.get(`/users/${id}/comments`);
    const comments = res.data;
    const tbody = document.querySelector('#comment-list tbody');
    tbody.innerHTML = '';
    comments.map(function (comment) {
      // ๋กœ์šฐ ์…€ ์ถ”๊ฐ€
      const row = document.createElement('tr');
      let td = document.createElement('td');
      td.textContent = comment._id;
      row.appendChild(td);
      td = document.createElement('td');
      td.textContent = comment.commenter.name;
      row.appendChild(td);
      td = document.createElement('td');
      td.textContent = comment.comment;
      row.appendChild(td);
      const edit = document.createElement('button');
      edit.textContent = '์ˆ˜์ •';
      edit.addEventListener('click', async () => { // ์ˆ˜์ • ํด๋ฆญ ์‹œ
        const newComment = prompt('๋ฐ”๊ฟ€ ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”');
        if (!newComment) {
          return alert('๋‚ด์šฉ์„ ๋ฐ˜๋“œ์‹œ ์ž…๋ ฅํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค');
        }
        try {
          await axios.patch(`/comments/${comment._id}`, { comment: newComment });
          getComment(id);
        } catch (err) {
          console.error(err);
        }
      });
      const remove = document.createElement('button');
      remove.textContent = '์‚ญ์ œ';
      remove.addEventListener('click', async () => { // ์‚ญ์ œ ํด๋ฆญ ์‹œ
        try {
          await axios.delete(`/comments/${comment._id}`);
          getComment(id);
        } catch (err) {
          console.error(err);
        }
      });
      // ๋ฒ„ํŠผ ์ถ”๊ฐ€
      td = document.createElement('td');
      td.appendChild(edit);
      row.appendChild(td);
      td = document.createElement('td');
      td.appendChild(remove);
      row.appendChild(td);
      tbody.appendChild(row);
    });
  } catch (err) {
    console.error(err);
  }
}
// ์‚ฌ์šฉ์ž ๋“ฑ๋ก ์‹œ
document.getElementById('user-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const name = e.target.username.value;
  const age = e.target.age.value;
  const married = e.target.married.checked;
  if (!name) {
    return alert('์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”');
  }
  if (!age) {
    return alert('๋‚˜์ด๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”');
  }
  try {
    await axios.post('/users', { name, age, married });
    getUser();
  } catch (err) {
    console.error(err);
  }
  e.target.username.value = '';
  e.target.age.value = '';
  e.target.married.checked = false;
});
// ๋Œ“๊ธ€ ๋“ฑ๋ก ์‹œ
document.getElementById('comment-form').addEventListener('submit', async (e) => {
  e.preventDefault();
  const id = e.target.userid.value;
  const comment = e.target.comment.value;
  if (!id) {
    return alert('์•„์ด๋””๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”');
  }
  if (!comment) {
    return alert('๋Œ“๊ธ€์„ ์ž…๋ ฅํ•˜์„ธ์š”');
  }
  try {
    await axios.post('/comments', { id, comment });
    getComment(id);
  } catch (err) {
    console.error(err);
  }
  e.target.userid.value = '';
  e.target.comment.value = '';
});

 

comments.js๋ฅผ ๋ณด์ž

const express = require('express');
const Comment = require('../schemas/comment');

const router = express.Router();

router.post('/', async (req, res, next) => {
  try {
    const comment = await Comment.create({
      commenter: req.body.id,
      comment: req.body.comment,
    });
    console.log(comment);
    const result = await Comment.populate(comment, { path: 'commenter' });
    res.status(201).json(result);
  } catch (err) {
    console.error(err);
    next(err);
  }
});

router.route('/:id')
  .patch(async (req, res, next) => {
    try {
      const result = await Comment.update({
        _id: req.params.id,
      }, {
        comment: req.body.comment,
      });
      res.json(result);
    } catch (err) {
      console.error(err);
      next(err);
    }
  })
  .delete(async (req, res, next) => {
    try {
      const result = await Comment.remove({ _id: req.params.id });
      res.json(result);
    } catch (err) {
      console.error(err);
      next(err);
    }
  });

module.exports = router;

๋Œ“๊ธ€์— ๊ด€๋ จ๋œ CRUD ์ž‘์—…์„ ํ•˜๋Š” ๋ผ์šฐํ„ฐ์ž…๋‹ˆ๋‹ค.

 

 

ใ…‹ใ…‹ ใ…Žใ…Ž ใ…‹ใ…‹

Comments