Mongoose: ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ: ๊ฐ€์ƒ ๋น„๋™๊ธฐ

์— ๋งŒ๋“  2017๋…„ 10์›” 27์ผ  ยท  42์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: Automattic/mongoose

์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ virtual async , ์ง€์›ํ•ด์ฃผ์„ธ์š”!

const User = new Schema(
  {
    username: {
      type: String,
      index: true,
      unique: true
    },
    encryptedPassword: {
      type: String,
      required: true,
      minlength: 64,
      maxlength: 64
    },
    passwordSalt: {
      type: String,
      required: true,
      minlength: 32,
      maxlength: 32
    }
})

User.virtual('password').set(async function generate(v) {
  this.passwordSalt = await encryptor.salt()
  this.encryptedPassword = await encryptor.hash(v, this.passwordSalt)
})
  const admin = new User({
    username: 'admin',
    password: 'admin'
  })
  admin.save()

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ฝ”๋“œ์— ์•„์ฃผ ์ข‹์€ ์•„์ด๋””์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๋ช‡ ๋ฒˆ ๋ณด์•˜์ง€๋งŒ ์กฐ์‚ฌํ•  ์‹œ๊ฐ„์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด ์•„์ด๋””์–ด๋ฅผ ์ข‹์•„ํ•˜์ง€๋งŒ, ๋‹ค์Œ ์ถœ์‹œ๋ฅผ ์œ„ํ•ด ๊ณ ๋ คํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ชจ๋“  42 ๋Œ“๊ธ€

ํ˜„์žฌ, ๋‚˜๋Š” ๋”๋Ÿฌ์šด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

User.virtual('password').set(function(v) {
  this.encryptedPassword = v
})

User.pre('validate', function preValidate(next) {
  return this.encryptPassword().then(next)
})

User.method('encryptPassword', async function encryptPassword() {
  this.passwordSalt = await encryptor.salt()
  this.encryptedPassword = await encryptor.hash(
    this.encryptedPassword,
    this.passwordSalt
  )
})

+1

+1

์ฝ”๋“œ์— ์•„์ฃผ ์ข‹์€ ์•„์ด๋””์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๋ช‡ ๋ฒˆ ๋ณด์•˜์ง€๋งŒ ์กฐ์‚ฌํ•  ์‹œ๊ฐ„์ด ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ด ์•„์ด๋””์–ด๋ฅผ ์ข‹์•„ํ•˜์ง€๋งŒ, ๋‹ค์Œ ์ถœ์‹œ๋ฅผ ์œ„ํ•ด ๊ณ ๋ คํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฌธ์ œ๋Š” .. ์‚ฌ์šฉ ๊ตฌ๋ฌธ์ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ์Šต๋‹ˆ๊นŒ?

await (user.password = 'some-secure-password');

์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ECMA262 12.15.4 ์— ๋”ฐ๋ฅด๋ฉด user.password = 'some-secure-password' ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์€ _rval_ ์ด์–ด์•ผ ํ•˜๋ฉฐ ์ด ๊ฒฝ์šฐ 'some-secure-password' ์ž…๋‹ˆ๋‹ค.

๋‹น์‹ ์˜ ๋ฐ˜ํ™˜ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์ œ์•ˆํ•˜๋Š” someVar = object ๊ฐ€ ์ˆ˜ Promise , ๊ทธ๋ฆฌ๊ณ ์— ๋”ฐ๋ผ ์ด ์Šค๋ ˆ๋“œ , ๊ทธ๋ฆฌ๊ณ  ์œ„์˜ ๋งํฌ ๋œ ES262 ์‚ฌ์–‘, ๊ทธ๊ฒƒ์€์ด๋‹ค "ES ์˜๋ฏธ ๊นŠ์€ ์œ„๋ฐ˜."

๋˜ํ•œ, ๋‹จ์ˆœํžˆ ํŽธ์˜ ๊ธฐ๋Šฅ์„ ๊ฐ–๊ธฐ ์œ„ํ•ด ์ด๋Ÿฌํ•œ ์˜๋ฏธ๋ก ์  ์œ„๋ฐ˜ ๋ฌธ์ œ๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋Š” ์‹œ๋„๋Š” ์ƒ๋‹นํžˆ ๋‚˜์œ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ๋ชฝ๊ตฌ์Šค ์ฝ”๋“œ๋ฒ ์ด์Šค ์ „์ฒด์— ์ž ์žฌ์ ์œผ๋กœ ๋ชจ๋“  ์ข…๋ฅ˜์˜ ๋‚˜์œ ๊ฒƒ์„ ์˜๋ฏธํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ƒฅ ํ•˜์ง€ ์•Š๋Š” ์ด์œ :

const hashPassword = require('./lib/hashPassword');

const password = await hashPassword('some-secure-password');
User.password = password; // This is completely normal.

๋ฌธ์ž ๊ทธ๋Œ€๋กœ ์ด๋ ‡๊ฒŒ ๊ฐ„๋‹จํ•œ ์› ๋ผ์ด๋„ˆ๋ฅผ ์œ„ํ•ด ์ฒ˜์Œ๋ถ€ํ„ฐ ํ•˜๋ฉด ์•ˆ ๋˜๋Š” async setter๋ฅผ ๋งŒ๋“ค๋ ค๊ณ  ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

User.methods.setPassword = async function (password) {
  const hashedPassword = await hashPassword(password);
  this.password = hashedPassword;
  await this.save();
  return this;
};
const myUser = new User();
await myUser.setPassword('mypassword...');

๊ฐ€์ƒ ์ž‘์—…, ์‚ฌ์ „ ์ €์žฅ ํ›„ํฌ ๋“ฑ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ๊ฒช๊ณ  ์žˆ๋Š” ์ด์œ ๋ฅผ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค...

@heisian๋‹˜ ๋ง์”€์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ IMHO์—๊ฒŒ ๊ธฐ๋Šฅ/API ํŒฝ์ฐฝ์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋Œ€์•ˆ์ด ์–ผ๋งˆ๋‚˜ ๋ถˆํŽธํ•œ์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์— ๋Œ€ํ•ด ๊ฝค ์ค‘์š”ํ•œ ๊ตฌ๋ฌธ ์ง€์›์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ํ™•์‹คํžˆ ๋ถ€ํ’€๋ ค์ง„ ๊ฒƒ์ฒ˜๋Ÿผ ๋Š๊ปด์ง‘๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋งค์šฐ ๊ฐ„๋‹จํ•œ ๊ธฐ๋Šฅ์ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

User.virtual('password').set((value, done) => {
  encryptValueWithAsyncFunction
    .then(response => done(null, value))
    .catch(reason => done(reason))
  ;
})

@gcanu ๋‹น์‹ ์€ ๋‚ด๊ฐ€ ๊ฒŒ์‹œํ•œ ๊ฒƒ์„ ์™„์ „ํžˆ ๋ฌด์‹œํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๋‹น์‹ ์ด ์ œ์•ˆํ•˜๋Š” ๊ฒƒ์€ ํ• ๋‹น ํ˜ธ์ถœ์—์„œ Promise๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ  Javascript/ECMA262 ์‚ฌ์–‘์„ ์™„์ „ํžˆ ์œ„๋ฐ˜ํ•ฉ๋‹ˆ๋‹ค. ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์ด ์ž‘๋™ํ•˜๋ ค๋ฉด setter ํ•จ์ˆ˜๊ฐ€ Promise์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์ •์˜์— ๋”ฐ๋ผ ์‚ฌ์–‘์— ๋”ฐ๋ผ ํ—ˆ์šฉ๋˜์ง€ ์•Š์œผ๋ฉฐ ์–ด์จŒ๋“  ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๋ƒฅ ํ•˜๋Š” ๊ฒŒ ๋ฌด์Šจ ์ž˜๋ชป์ด์•ผ:

await User.setPassword('password');

???

์ด์ „์— ๋ณด์ง€ ๋ชปํ•œ ๊ฒฝ์šฐ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค .

await (User.password = 'password');

@vkarpov15 ์ด๊ฒƒ์€ ๋ชฝ๊ตฌ์Šค ๊ด€๋ จ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ ํ˜„์žฌ ECMAScript ์‚ฌ์–‘์˜ ์œ ํšจ์„ฑ์— ๋Œ€ํ•œ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด "๊ธฐ๋Šฅ ์š”์ฒญ"์„ ๋‹ซ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค...

์•„๋ž˜ ์ฝ”๋“œ๋Š” ๋งค์šฐ ๋‚˜์œ ์ƒ๊ฐ์ž…๋‹ˆ๋‹ค! ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค์ •์— save ์ž‘์—…์ด ํฌํ•จ๋œ ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

User.methods.setPassword = async function (password) {
  const hashedPassword = await hashPassword(password);
  this.password = hashedPassword;
  await this.save();
  return this;
};

const myUser = new User();
await myUser.setPassword('mypassword...');

๋ชฝ๊ตฌ์Šค๋Š” ๋” ํ˜„๋Œ€์ ์ด๊ณ  ๋” ์šฐ์•„ํ•œ ๊ฒƒ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

@heisian ์ข‹์•„, ๋‚ด ์‹ค์ˆ˜, ๋‚ด๊ฐ€ ์„ธํ„ฐ ์‚ฌ์šฉ์„ ๋Œ๋ณด์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค ...

@heisian Plz๋Š” https://github.com/Automattic/mongoose/blob/master/lib/virtualtype.js๋ฅผ ์ฐธ์กฐ

ํ˜„์žฌ Mongoose IMPL์—์„œ getter ๋˜๋Š” setter ํ•จ์ˆ˜๋ฅผ ๋“ฑ๋กํ•œ ๋‹ค์Œ ํ˜ธ์ถœํ•˜๋ฉด https://tc39.github.io/ecma262/#sec -assignment-operators-runtime-semantics๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. -ํ‰๊ฐ€ ๋ฐ https://github.com/tc39/emascript-asyncawait/issues/82. ๊ทธ๊ฑด ๋‹ฌ๋ผ.

๊ทธ๋Ÿฌ๋‹ˆ ์ด ์š”์ฒญ์„ ์—ฌ์‹ญ์‹œ์˜ค.

@fundon , ์•Œ๋ ค์ฃผ์„ธ์š”: ๊ฐ€์ƒ ์„ธํ„ฐ๋ฅผ ์ •ํ™•ํžˆ ์–ด๋–ป๊ฒŒ ๋ถ€๋ฅผ๊นŒ์š”? ์‚ฌ์šฉ๋ฒ•์„ ๋ณด์—ฌ์ฃผ์„ธ์š”. async ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒฝ์šฐ ์•ฝ์†์œผ๋กœ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์›๋ž˜ ์˜ˆ์ œ๋Š” setter/assignment ํ˜ธ์ถœ์˜ ์–ด๋””์—๋„ await ํ‘œ์‹œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‚ด ์˜ˆ์ œ ์ฝ”๋“œ๋Š” ๋‹จ์ง€ ์˜ˆ์ผ ๋ฟ์ž…๋‹ˆ๋‹ค... ๋‹น์‹ ์€ ๋˜ํ•œ ์ด๊ฒƒ์„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค:

User.methods.setPassword = async function (password) {
  const hashedPassword = await hashPassword(password);
  this.password = hashedPassword;
  return this;
};

const myUser = new User();
await myUser.setPassword('mypassword...');
await myUser.save();

ํ™•์‹คํžˆ..

๋‹น์‹ ์˜ ๋ชจ๋ฒ”์€ ๋‚˜์—๊ฒŒ ์ข‹์€ ๋ฐฉ๋ฒ•์ด ์•„๋‹™๋‹ˆ๋‹ค.

์›ํ•ด์š”

await new User({ password }).save()

๋” ๊ฐ„๋‹จํ•˜๊ณ  ์šฐ์•„ํ•œ ๋ชจ๋“œ์—์„œ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ•ด์‹œํ•˜์‹ญ์‹œ์˜ค.

์™œ์š”? ๋ช‡ ์ค„์˜ ์ฝ”๋“œ๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ทธ ์ด์œ ๋Š” ๋ชจ๋“  ์ถ”๊ฐ€ ์ž‘์—…์„ ์ •๋‹นํ™”ํ•˜๊ธฐ์— ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ฝ”๋“œ๋ฒ ์ด์Šค์— ๋Œ€ํ•œ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊นจ๋œจ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ํ•˜๋ฃจ๊ฐ€ ๋๋‚˜๋ฉด ์–ด๋–ป๊ฒŒ ํ‘œํ˜„ํ•˜๋“  Mongoose ๋‚ด์—์„œ ๋‚ด๋ถ€์ ์œผ๋กœ ์ง„ํ–‰๋˜๋Š” ๊ฒƒ์€ ๋น„๋™๊ธฐ/๋Œ€๊ธฐ๊ฐ€ ๋  ์ˆ˜ ์—†๋Š” setter๋ผ๋Š” ์‚ฌ์‹ค์„ ๊นจ๋‹ฌ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@heisian์— ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋ชฝ๊ตฌ์Šค๋Š” ์˜ค๋ž˜๋œ ๊ฒƒ์ด ๋„ˆ๋ฌด ๋งŽ์Šต๋‹ˆ๋‹ค. ๋ชฝ๊ตฌ์Šค๋Š” ๋ฆฌํŒฉํ† ๋ง์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค!
๋ชฝ๊ตฌ์Šค๋Š” ํ˜„๋Œ€๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๊ฐ€ ์ข…๋ฃŒ๋œ ๊ฒฝ์šฐ. Mongoose๋ฅผ ํฌํฌํ•˜๊ณ  ๋ฆฌํŒฉํ† ๋งํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค! ์•ˆ๋…•ํžˆ ๊ณ„์„ธ์š”!

์—„์ฒญ๋‚œ! ๊ทธ๊ฒƒ์ด ์˜คํ”ˆ์†Œ์Šค์˜ ํ•ต์‹ฌ์ด๋‹ค. ๊ณ„์†ํ•ด์„œ ํŠธ๋ฆฌ๋ฐ๋œ ๋ฒ„์ „์œผ๋กœ ํฌํฌ๋ฅผ ๋งŒ๋“œ์‹ญ์‹œ์˜ค. ์šฐ๋ฆฌ ๋ชจ๋‘์—๊ฒŒ ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

await (User.password = 'password'); ํ•„์š”์— ๋Œ€ํ•ด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์œ ์ผํ•œ ์ง„์งœ ๋‹จ์ ์€ user.password = 'password'; ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ผ๋ถ€ ๋น„๋™๊ธฐ ์ž‘์—…์ด ์žˆ์Œ์„ ์˜๋ฏธํ•˜๋ฏ€๋กœ user.passwordSalt ๊ฐ€ ์„ค์ •๋˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์ด ํ›„ํฌ์™€ ์–ด๋–ป๊ฒŒ ๊ด€๋ จ๋˜๋Š”์ง€๋„ ํฅ๋ฏธ๋กœ์šด ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค. pre('validate') ๋˜๋Š” pre('save') ํ›„ํฌ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ user.password ๋น„๋™๊ธฐ ์ž‘์—…์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๊นŒ?

๋‚˜๋Š” ์ด ๋ฌธ์ œ๋ฅผ ์†์—์„œ ๋–ผ๊ณ  ์‹ถ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. .save() , .find() ๋“ฑ ๋’ค์— ์žˆ๋Š” ๋น„๋™๊ธฐ ๋™์ž‘์„ ํ†ตํ•ฉํ•˜๋Š” ๋ฐ๋Š” ๋งŽ์€ ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€ API์™€ ์ž˜ ๋งž๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์˜ค๋Š˜๋‚  ๋น„๋™๊ธฐ getter์™€ setter๋Š” ๋‚˜์—๊ฒŒ ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋…์  ์•”ํ˜ธํ™” ๋ฐฉ๋ฒ•์œผ๋กœ ํ•„๋“œ๋ฅผ ๋ณตํ˜ธํ™”/์•”ํ˜ธํ™”ํ•˜๊ธฐ ์œ„ํ•ด getter ๋ฐ setter์—์„œ HTTP ์š”์ฒญ์„ ๋ณด๋‚ด์•ผ ํ•˜๋Š”๋ฐ ํ˜„์žฌ๋กœ์„œ๋Š” ๊ทธ๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ๋‹ฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

@gcanu ๋‚˜๋Š” ๊ทธ๊ฒƒ๋“ค์„ ๋ฉ”์†Œ๋“œ ๋กœ ๊ตฌํ˜„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์–ธ๊ธ‰ํ•œ ์ด์œ ์™€ ํ•„์š”ํ•œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค ๋•Œ๋ฌธ์— async ๋™์ž‘์„ ํ†ตํ•ฉํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ๋Š” ์—†์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ await (User.password = 'password') ๋Š” ECMAScript ๊ทœ์น™์„ ์œ„๋ฐ˜ํ•˜๊ณ  ์ €๋Š” ์šฐ์•„ํ•˜๊ฒŒ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ด ์–ด๋ ต๊ณ  ๊ฐ€์น˜๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค ...

๋‹น์‹  ๋ง์ด ๋งž์•„, ๊ทธ ํŒจํ„ด์€ ์šฐ๋ฆฌ๊ฐ€ ๊ตฌํ˜„ํ•  ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. ์ €์žฅํ•˜๊ธฐ ์ „์— ๋น„๋™๊ธฐ ๊ฐ€์ƒ์ด ํ•ด๊ฒฐ๋˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์•„์ด๋””์–ด๋Š” ํฅ๋ฏธ๋กญ์Šต๋‹ˆ๋‹ค.

toJSON({virtuals: true}) ๊ตฌํ˜„์— ์ ํ•ฉํ•ฉ๋‹ˆ๋‹ค. ์ง๋ ฌํ™”ํ•œ ํ›„์—๋งŒ ์‹คํ–‰ํ•˜๊ณ  ์‹ถ์€ db์— ๋Œ€ํ•œ ๋‹ค๋ฅธ ์ฟผ๋ฆฌ๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ์–ป์€ ๊ฐ€์ƒ ํ•„๋“œ ์ค‘ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค.

@gabzim JSON.stringify๊ฐ€ ์•ฝ์†์„ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ฝค ์ง€์ €๋ถ„ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ res.json()์€ ํ‘œํ˜„ํ•  ์ถ”๊ฐ€ ๋„์šฐ๋ฏธ๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๋Š” ํ•œ ๋น„๋™๊ธฐ ๊ฐ€์ƒ์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์•„ ์˜ˆ, ์ดํ•ด๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค @vkarpov15

get ์ฝœ๋ฐฑ ๋‚ด์—์„œ ์ฟผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์ด ์ข‹์€ ๋ฐฉ๋ฒ•์ผ๊นŒ์š”?
๋‚˜๋Š” ์ด๊ฒƒ์ด ์–ด๋–ค ๊ฒฝ์šฐ์— ์œ ์šฉํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.

Github URL ๊ฒฝ๋กœ์™€ ๊ฐ™์ด ๋ฌธ์„œ๊ฐ€ ์ค‘์ฒฉ๋  ์ˆ˜ ์žˆ๋Š” ์›น ํŽ˜์ด์ง€(๋˜๋Š” ๋ฌธ์„œ)์˜ ์ „์ฒด ๊ฒฝ๋กœ๋ฅผ ์–ป๊ณ  ์‹ถ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

const Doc = require('./Doc.js');
//...
subDocSchema.virtual('fullpath').get(async function(){
    const doc = await Doc.findById(this.doc); //doc is a Doc ref of type _id
    return `/${ doc.path }/${ this.path }`
})

์ฟผ๋ฆฌ ์ž‘์—…์ด ๋น„๋™๊ธฐ์‹์ด๋ฏ€๋กœ ์—ฌ๊ธฐ์„œ async/await๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

@JulianSoto ์ด ๊ฒฝ์šฐ ๊ฐ€์ƒ์ด ์•„๋‹Œ ๋ฉ”์†Œ๋“œ ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ฐ€์ƒ ์„ ์‚ฌ์šฉํ•˜๋Š” ์ฃผ๋œ ์ด์œ  toJSON() ๋ฐ toObject() ๋Š” ๋™๊ธฐ์‹์ด๋ฏ€๋กœ ๋น„๋™๊ธฐ ๊ฐ€์ƒ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์ด๊ฒƒ์— ๋Œ€ํ•œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋„ ๋งŒ๋‚ฌ๊ณ  ์ข‹์€ ์†”๋ฃจ์…˜์„ ์ƒ๊ฐํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์•„์ด๋””์–ด์— ๋งค์šฐ ๊ฐœ๋ฐฉ์ ์ด๋ฉฐ setter ์˜๋ฏธ๋ฅผ ๊นจ๋œจ๋ฆฌ์ง€ ์•Š๋Š”๋‹ค๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

JSON ํŒจ์น˜ ์„ธํŠธ๋ฅผ ๋ชฝ๊ตฌ์Šค ๋ชจ๋ธ์— ์ž๋™์œผ๋กœ ์ ์šฉํ•˜๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค. ๊นŠ์€ ๊ฒฝ๋กœ๋กœ ์ž๋™ ์ฑ„์šฐ๊ธฐ๋ฅผ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค: https://github.com/claytongulick/mongoose-json-patch

์•„์ด๋””์–ด๋Š” https://github.com/claytongulick/json-patch-rules ์™€ ๊ฐ™์€ ๋ช‡ ๊ฐ€์ง€ ๊ทœ์น™๊ณผ ํ•จ๊ป˜ JSON ํŒจ์น˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ '์ž๋™' API๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๋งค์šฐ ๊ทผ์ ‘ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‚ด ๊ณ„ํš์€ ๋‹จ์ˆœ ํ• ๋‹น์ด ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๊ฐ€์ƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ํŒจ์น˜๊ฐ€ ์ ์šฉ๋˜๋ฉด ๊ฐ€์ƒ์ด ์›ํ•˜๋Š” ๋ชจ๋“  ๊ฒƒ์„ ์„ ํƒํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ธํ„ฐํŽ˜์ด์Šค ๊ฐœ์ฒด๊ฐ€ ์‹ค์ œ ๋ชฝ๊ตฌ์Šค ๋ชจ๋ธ/db ๊ฐœ์ฒด์™€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

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

ํ•˜์ง€๋งŒ ๊ฐœ๋…์  ๋ชจ๋ธ์ธ ์ธํ„ฐํŽ˜์ด์Šค ๋ชจ๋ธ์ด JSON ํŒจ์น˜ '์ถ”๊ฐ€' ์ž‘์—…์œผ๋กœ ํŒจ์น˜๋  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋น„๋™๊ธฐ ์„ธํ„ฐ๊ฐ€ ์—†์œผ๋ฉด ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์œ ์ผํ•œ ์˜ต์…˜์€ ๋” ๋‚˜์€ ์•„์ด๋””์–ด๊ฐ€ ์—†๋Š” ํ•œ mongoose-json-patch๊ฐ€ ๊ฒฝ๋กœ, ์ž‘์—… ๋ฐ ๋ชฝ๊ตฌ์Šค ๋ฉ”์„œ๋“œ ๊ฐ„์˜ ์ผ์ข…์˜ ๋งคํ•‘์„ ์˜ต์…˜์œผ๋กœ ์ˆ˜๋ฝํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@claytongulick ๋น„๋™๊ธฐ ์ž‘์—…์— await ๋Œ€์‹  ๋น„๋™๊ธฐ ์„ค์ • ๊ธฐ๊ฐ€ ํ•„์š”ํ•œ ๋‹ค์Œ ๋™๊ธฐ์ ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

@vkarpov15 ๊ธฐ๋ณธ์  ์œผ๋กœ toObject() ๋ฐ toJSON() ๋™๊ธฐํ™” ํ•˜๊ณ  toObjectSync() ๋ฐ toJSONSync() ๊ธฐ๋Šฅ์„ ๋„์ž…ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋–ป์Šต๋‹ˆ๊นŒ? Sync ๋ณ€ํ˜•์€ async ๊ฐ€์ƒ์„ ๊ฑด๋„ˆ๋›ฐ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (์ด ํŒจํ„ด์€ ์–ด๋”˜๊ฐ€ ๋ชฝ๊ตฌ์Šค์—์„œ ์‚ฌ์šฉ๋˜์—ˆ๋˜ ๊ฒƒ์œผ๋กœ ๊ธฐ์–ตํ•˜๋Š”๋ฐ, ๊ฐ€์ง€๊ณ  ์žˆ์–ด๋„ ์ด์ƒํ•˜์ง€ ์•Š์„ ๊ฒƒ์ด๋‹ค.)

๋‚ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋ชจ๋ธ์—์„œ find() ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฐ€์ƒ์ด ์žˆ๋Š” ์Šคํ‚ค๋งˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(๋‹จ์ˆœํžˆ ID๋ฅผ ์ฑ„์šฐ๋Š” ๊ฒƒ๋ณด๋‹ค ์กฐ๊ธˆ ๋” ๋ณต์žกํ•จ). ๋ฌผ๋ก  ์ €์žฅ/์‚ญ์ œ ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ธฐ๋ณธ ๋ชจ๋ธ์— ์›ํ•˜๋Š” ํ•ญ๋ชฉ์„ ๋น„์ •๊ทœํ™”ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์œ ์ง€ ๊ด€๋ฆฌ ๋น„์šฉ์ด ๋งŽ์ด ๋“ญ๋‹ˆ๋‹ค(์ด ํŠน์ • ๊ฒฝ์šฐ์—๋Š” ์„ฑ๋Šฅ ์ด์ ์ด ์‹ค์ œ๋กœ ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค). ๊ทธ๋ž˜์„œ ๊ฐ€์ƒ์œผ๋กœ ์ €๋ฅผ ์œ„ํ•ด ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์ž์—ฐ์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

JSON.stringify() ๋Š” ๋น„๋™๊ธฐ toJSON() ์ง€์›ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๋ถˆํ–‰ํžˆ๋„ toJSONSync() ์•„์ด๋””์–ด๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

find() ๊ฐ€ ๊ฝค ๋ณต์žกํ•˜๋‹ค๊ณ  ๋ง์”€ํ•˜์…จ์ง€๋งŒ ๋งŒ์ผ์„ ๋Œ€๋น„ํ•˜์—ฌ ๊ฐ€์ƒ ์ฑ„์šฐ๊ธฐ๋ฅผ ์‚ดํŽด๋ณด๊ณ  ์‹ถ์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฟผ๋ฆฌ ๋ฏธ๋“ค์›จ์–ด๋ฅผ ์‚ฌ์šฉํ•ด ๋ณผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ๋น„๋™๊ธฐ ๊ฐ€์ƒ์—๋Š” setter ๋˜๋Š” getter @isamert ๋งŒ ์žˆ์Šต๋‹ˆ๊นŒ?

์ด ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์‚ฌ๋žŒ๋“ค์„ ์œ„ํ•œ ์†”๋ฃจ์…˜:

setter๋งŒ ๋น„๋™๊ธฐ์ธ ๊ฒฝ์šฐ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ์•˜์Šต๋‹ˆ๋‹ค. ์•ฝ๊ฐ„ ์ง€์ €๋ถ„ํ•˜์ง€๋งŒ ์ž˜ ์ž‘๋™ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์•„์ด๋””์–ด๋Š” ์ฝœ๋ฐฑ ์†Œํ’ˆ์œผ๋กœ ์•ฝ์† ํ™•์ธ์ž์™€ ์„ค์ •ํ•  ๊ฐ€์ƒ ์†์„ฑ์„ ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ๊ฐ€์ƒ setter์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. setter๊ฐ€ ์™„๋ฃŒ๋˜๋ฉด ์ฝœ๋ฐฑ์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ์™ธ๋ถ€์— ๊ฐœ์ฒด๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ์งˆ๋ฌธ์—์„œ ์˜๊ฐ์„ ์–ป์€ ๊ธฐ๋ณธ ์˜ˆ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด:

const User = new Schema(
  {
    username: {
      type: String,
      index: true,
      unique: true
    },
    encryptedPassword: {
      type: String,
      required: true,
      minlength: 64,
      maxlength: 64
    }
})

User.virtual('password').set(function generate(inputWithCb, virtual, doc) {
  let cb = inputWithCb.cb;
  let password = inputWithCb.password;
  encryptor.hash(password)
  .then((hash) => {
    doc.set("encryptedPassword", hash);
    cb && cb();
  });
})
// create the document
const admin = new User({
  username: 'admin'
});
// setup the promise for setting the async virtuals
const pwdProm = new Promise((resolve) => {
  admin.set("password", {cb: resolve, password: "admin"});
})

//run the promise and save only when the virtual setters have finished executing
pwdProm
.then(() => {
  admin.save();
});

์ด๊ฒƒ์€ ์›์น˜ ์•Š๋Š” ๊ฒฐ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ž์‹ ์˜ ์ฑ…์ž„ํ•˜์— ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค.

@silto ๊ทธ๋ƒฅ ์•ฝ์†์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์Šคํ‚ค๋งˆ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

@vkarpov15 ๋ณดํ†ต ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ฒ ์ง€๋งŒ, ๋‚ด๊ฐ€ ํ•œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” json "๊ณ„ํš"์—์„œ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ ์Šคํ‚ค๋งˆ, ๊ฐ€์ƒ ๋ฐ graphQL ๋์ ์ด ์žˆ์œผ๋ฏ€๋กœ ํŠน์ • ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ๋ฐฉ๋ฒ• ๋Œ€์‹  ๊ท ์ผํ•œ ๊ฐ€์ƒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

@silto ์ฝ”๋“œ ์ƒ˜ํ”Œ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋‚˜๋Š” ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ƒ๊ฒผ๋Š”์ง€ ๋ณด๊ณ  ์‹ถ๋‹ค

setter์˜ ๊ฒฝ์šฐ ์ €์žฅ์„ ํ•˜๊ฑฐ๋‚˜ ๊ทธ๋ƒฅ ๋ฌธ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์•„๋ณด๊ณ  ์ €์žฅํ•˜๋ฉด ํ”„๋ผ๋ฏธ์Šค์ด๋ฏ€๋กœ ํ”„๋ผ๋ฏธ์Šค์ธ ํ•„๋“œ๋ฅผ ํ™•์ธํ•˜๊ณ  ํ•ด๊ฒฐํ•œ ํ›„ ์ €์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ๊ณ  ์‹ถ๋‹ค๋ฉด ์Šคํ‚ค๋งˆ ์˜ต์…˜์œผ๋กœ ์ด Model์ด Promise ์œ ํ˜•์ด ๋˜๋„๋ก ์ •์˜ํ•˜๊ฑฐ๋‚˜ ๋ชจ๋ธ์„ ์ƒ์„ฑํ•  ๋•Œ ์Šคํ‚ค๋งˆ๋ฅผ ํ™•์ธํ•˜๊ณ  Promise์ธ setter, getter ๋˜๋Š” virtual์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•œ ๋‹ค์Œ ๊ทธ๊ฒƒ์„ ์•ฝ์†์œผ๋กœ.

๋˜๋Š” ์ด๋ฏธ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”(execPopulate) ํ•จ์ˆ˜์™€ ๊ฐ™์€ exec๋ฅผ ๊ฐ„๋‹จํžˆ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ ฅ์„œ์—์„œ setter, getter ๋˜๋Š” virtual์ด ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€์ฐฐํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ํ•ด๋‹น ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•จ์ˆ˜๋ฅผ ๋นŒ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋ ค๋ฉด ์ด๋ฏธ ์•ฝ์†์ด๋ฏ€๋กœ ๋™์ผํ•œ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €์žฅํ•˜๊ธฐ ์ „์—.

๋‚˜๋Š” ์•ฝ์†๊ณผ ํ•จ๊ป˜ ๊ฐ€์ƒ์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋ช…์‹œ์  ์•ฝ์†์„ ์‚ฌ์šฉํ•  ๋•Œ ๊ฑฐ์˜ ํ•ญ์ƒ ์•ฝ์†์— ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์ง€๋งŒ ์–ด๋–ค ๊ฒฝ์šฐ์—๋Š” Doc์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค..then(), ๋‚˜๋Š” ์•ฝ์†์ด ์žˆ๋Š” setter๋ฅผ ์‚ฌ์šฉํ•œ ์ ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค...

์–ด๋Š ์ชฝ์ด๋“  ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ด๋ฏธ ํ™•์ธํ•˜๊ณ  ์•ฝ์†๋œ setter๋ฅผ ์ •์˜ํ•œ ํ›„ ๋ชจ๋“  ์•ฝ์†๋œ ๊ฐ€์ƒ ๋ฐ ๊ฒŒํ„ฐ์—์„œ "then"์„ ์‚ฌ์šฉํ•  ํ•„์š”๊ฐ€ ์—†๋Š” ์ผ์ข…์˜ ๋ž˜ํผ๊ฐ€ ์žˆ์œผ๋ฉด ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ์ ‘๊ทผ ๋ฐฉ์‹์„ ๋„์™€๋“œ๋ฆด ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์นœ์• ํ•˜๋Š”.

์ถ”์‹ : Promisifed virtuals ์‚ฌ์šฉ์˜ ์ผ๋ฐ˜์ ์ธ ์˜ˆ, ์ œ ๊ฒฝ์šฐ์—๋Š” 2๊ฐœ์˜ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ด ๋ฌธ์„œ๋ฅผ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ์™ธ๋ถ€ ๋ฐ์ดํ„ฐ์— ๋”ฐ๋ผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. . ์•ž์„œ ๋งํ–ˆ๋“ฏ์ด ๋ช…์‹œ์  ์•ฝ์†์ด ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ์ฃผ์ง€๋งŒ ์ด๋Ÿฌํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋‚ด๋ถ€์ ์œผ๋กœ ํ™•์ธํ•˜๋ ค๋ฉด ๋จผ์ € ์ด ์•ฝ์†์„ ํ•ด๊ฒฐํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค.

@chumager ๋ช‡ ๊ฐ€์ง€ ์ฝ”๋“œ ์ƒ˜ํ”Œ์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

์•ˆ๋…•ํ•˜์„ธ์š”, ์˜ˆ๋ฅผ ๋“ค์–ด, ์•„๋ž˜ ๋‚ด ์˜๊ฒฌ์— ๋”ฐ๋ฅด๋ฉด 2๊ฐœ์˜ ๊ฐ€์ƒ _update ๋ฐ _delete์™€ ์Šคํ‚ค๋งˆ์— ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์€ ๊ฒฝ์šฐ ํ•ด๋‹น ๊ฐ€์ƒ์„ ์ •์˜ํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‚ฌ์šฉํ•˜์—ฌ true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

ํฌ๋ ˆ๋”ง์„ ์ •์˜ํ•˜๋Š” ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋ธ๊ณผ mkt ๋ฐ์ดํ„ฐ๋กœ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ๊ฒŒ์‹œํ•˜๋Š” ํ”„๋กœ์ ํŠธ ๋ชจ๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
์‹œ๋ฎฌ๋ ˆ์ด์…˜๊ณผ ์—ฐ๊ฒฐ๋œ ํ”„๋กœ์ ํŠธ๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์‚ญ์ œํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ํ”„๋กœ์ ํŠธ๊ฐ€ ํˆฌ์ž์šฉ์œผ๋กœ ๊ฒŒ์‹œ๋œ ๊ฒฝ์šฐ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์‹œ๋ฎฌ๋ ˆ์ด์…˜์—์„œ ๊ฐ€์ƒ _update์˜ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด ์ฐธ์กฐ๋˜๊ณ  ์ƒํƒœ๊ฐ€ "En Financiamiento"์ธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ฐพ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ฟผ๋ฆฌ๊ฐ€ ์ฐธ์ด๋ฉด ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค... ๋ถ„๋ช…ํžˆ "์ฐพ๊ธฐ"๋Š” ์•ฝ์†, ๊ทธ๋ž˜์„œ ๊ฐ€์ƒ๋„ ...

์ผ๋ฐ˜์ ์œผ๋กœ ํ”„๋ก ํŠธ์—”๋“œ์—์„œ ์ด ๊ฐ€์ƒ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๋Š” ๊ฐ์ฒด๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ชจ๋“ˆ์— ์˜ํ•ด ๊ตฌ๋ฌธ ๋ถ„์„๋ฉ๋‹ˆ๋‹ค(co ๋˜๋Š” express-promise์— ๋”ฐ๋ผ ํ•˜๋‚˜ ๋˜๋Š” ๊ฒฐ๊ณผ ๋ฐฐ์—ด).

๋ฌธ์„œ๋ฅผ ๋ณด๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ๋‚ด ๊ฐ€์ƒ์ด ์•ฝ์†์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋  ๊ฒƒ์ด๋ฏ€๋กœ co ๋ชจ๋“ˆ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜์ง€๋งŒ ์ด๋ฏธ ๊ฒฐ๊ณผ๋ฅผ ์•ฝ์†์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ–ˆ์Šต๋‹ˆ๋‹ค... ์•„๋งˆ๋„ ๊ฒฐ๊ณผ์— co๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋งˆ๋ฒ•์„ ์ˆ˜ํ–‰ํ•˜๊ฑฐ๋‚˜ ์ฐพ๊ธฐ ํ›„์— co๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์œผ๋กœ ... ํ•˜์ง€๋งŒ ๊ฒฐ๊ณผ ์„ธํŠธ๊ฐ€ ์ด๋ฏธ ์ž‘์—…์„ ์™„๋ฃŒํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋” ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋ชฝ๊ตฌ์Šค์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด ๋งŽ์€ ๋์ ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. si ๋‚˜๋Š” ๊ทธ ๊ธฐ๋Šฅ์„ ์–ด๋””์—์„œ๋‚˜ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ์ฐพ๊ธฐ๋ฅผ ์œ„ํ•ด ํฌ์ŠคํŠธ ํ›„ํฌ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

getter์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ›„ํฌ๋Š” ์‚ฌ์ „ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•˜์ง€๋งŒ ๋ฌธ์„œ์— ์ˆœํ™˜ ์ฐธ์กฐ ๋ฐ ์ƒ์„ฑ์ž์™€ ๊ฐ™์€ ๊ธฐํƒ€ ์†Œํ’ˆ์ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์„œ์˜ ๋‹ค๋ฅธ ์†Œํ’ˆ์„ ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์•ˆ ์ธ์‚ฌ...

์ถ”์‹ : ์˜ˆ์ œ codo๊ฐ€ ์ •๋ง๋กœ ํ•„์š”ํ•˜๋ฉด ์ €์—๊ฒŒ ์•Œ๋ ค์ฃผ์‹ญ์‹œ์˜ค.

@chumager ์‚ฐ๋ฌธ์˜ ํฐ ๋ฒฝ !== ์ฝ”๋“œ ์ƒ˜ํ”Œ. ์ฝ”๋“œ ์ƒ˜ํ”Œ์„ ์ •๋ง ์„ ํ˜ธํ•ฉ๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰