await User.findOnd({id}).exec()
위와 같은 코드를 보았다.
.exec()이 없어도 결과는 똑같았는데 왜 exec()을 사용하는지 궁금해 공식문서를 찾아보았다.
몽구스 오퍼레이터인 .save()와 queries는 thenables한 값을 리턴해준다고 나와있다.
.then() 을 사용할 수 있다는 뜻인데, 마치 프로미스처럼 보인다.
.save()는 promise를 리턴한다.
그러나 query는 프로미스를 리턴하지 않는다.
갑자기 query는 뭐지? 라는 생각이 들 수 있다.
Model.findById()
위 메서드는 몽구스를 사용한다면 정말 많이 쓰게 되는 메서드이다.
Return이 Query 임을 볼 수 있다.
공식 문서를 보면 query는 프로미스가 아니지만, async/await을 사용할 수 있도록 .then()을 갖고있다고 한다.
또 promise와 완전히 동일하게 만드려면 .exec() 함수를 사용하라고 나와있다.
const query = Band.findOne({ name: 'Guns N\' Roses' });
assert.ok(!(query instanceof Promise)); // Promise 가 아니다.
// A query is not a fully-fledged promise, but it does have a `.then()`.
query.then(function(doc) {
// use doc
});
// `.exec()` gives you a fully-fledged promise
const promise = Band.findOne({ name: 'Guns N\' Roses' }).exec();
assert.ok(promise instanceof Promise); // .exec()을 사용하면 promise가 된다.
promise.then(function(doc) {
// use doc
});
queries는 프로미스가 아니지만, thenable하다.
promise chaning을 사용하거나 async await을 사용할 수 있다는 뜻이다.
await User.findOne();
await User.findOne().exec();
기능적으로 동일하다.
그러나 공식 문서에서는 .exec()을 붙여 사용하길 권장한다.
.exec()을 사용할 경우, 에러 검증 시 더 상세한 stack traces를 제공한다.
공식문서의 예시
const doc = await Band.findOne({ name: 'Guns N\' Roses' }); // works
const badId = 'this is not a valid id';
try {
await Band.findOne({ _id: badId });
} catch (err) { .exec()가 없는 경우, 코드 어디서 에러가 발생했는지 정확히 말해주지 않는다.
// Without `exec()`, the stack trace does **not** include the
// calling code. Below is the stack trace:
//
// CastError: Cast to ObjectId failed for value "this is not a valid id" at path "_id" for model "band-promises"
// at new CastError (/app/node_modules/mongoose/lib/error/cast.js:29:11)
// at model.Query.exec (/app/node_modules/mongoose/lib/query.js:4331:21)
// at model.Query.Query.then (/app/node_modules/mongoose/lib/query.js:4423:15)
// at process._tickCallback (internal/process/next_tick.js:68:7)
err.stack;
}
try {
await Band.findOne({ _id: badId }).exec();
} catch (err) { .exec()을 사용한 경우, 코드 어디서 에러가 났는지 말해준다.
// With `exec()`, the stack trace includes where in your code you
// called `exec()`. Below is the stack trace:
//
// CastError: Cast to ObjectId failed for value "this is not a valid id" at path "_id" for model "band-promises"
// at new CastError (/app/node_modules/mongoose/lib/error/cast.js:29:11)
// at model.Query.exec (/app/node_modules/mongoose/lib/query.js:4331:21)
// at Context.<anonymous> (/app/test/index.test.js:138:42) <- 여기서 에러가 났음!
// at process._tickCallback (internal/process/next_tick.js:68:7)
err.stack;
}
exec()을 사용하도록 하자.
참고자료