NodeJS - mongoose middleware
Middleware
이 글은 mongoose middleware를 한글로 요약 정리한 것이다. 실제 본문을 요약하여 번역해 정리했으므로 이해가 안되는 부분은 위 링크의 내용을 참조하기 바란다.
mongoose middleware
pre, post hook 이라고 불리는 mongoose middleware는 비동기 함수의 실행중 제어권을 다룰 수 있다. 미들웨어는 스키마 수순에서 사용고 plugins 를 작성하는데 유용하다.
Mongoose 4.x 은 4종류의 미들웨어를 지원한다:
- document middleware
- model middleware
- aggregate middleware
- query middleware
Document middleware는 아래 도큐멘트 함수를 지원한다. 도큐멘트 미들웨어에서 this
는 도큐멘트를 가르킨다.
- init
- validate
- save
- remove
Query middleware 는 아래 모델과 쿼리 함수를 지원한다. 쿼리 미들웨어 함수에서 this
는 쿼리를 가르킨다.
- count
- find
- findOne
- findOneAndRemove
- findOneAndUpdate
- update
Aggregate middleware 는 MyModel.aggregate()
를 위한것이다. Aggregate middleware는 aggregate 객체에서 exec()
를 호출할 때 실행된다.. 여기서 this
는 aggregation object를 가르킨다.
- aggregate
Model middleware 는 아래 모델 함수에 대해 지원한다. 여기서 this
는 모델을 가르킨다.
- insertMany
Note: There is no query hook for remove(), only for documents. If you set a ‘remove’ hook, it will be fired when you call myDoc.remove(), not when you call MyModel.remove(). Note: The create() function fires save() hooks.
모든 미들웨어 형식은 pre
와 post
훅(hook)을 지원한다.
### Pre middleware
Serial과 parallel 이라는 두가지 pre
훅이 있다.
#### Serial
Serial middleware는 각 미들웨어가 next()
를 호출하면 하나 다음 다른 하나를 실행한다.
1 | var schema = new Schema(..); |
그렇지만 next()
함수가 미들웨어의 다음 코드 실행을 멈추지 않기 때문에 return
패턴을 사용해서 코드 진행을 멈추면 된다.
1 | var schema = new Schema(..); |
#### Parallel
Parallel middleware는 제어를 더욱 정밀하게 할 수 있다.
아래는 Pre 훅에 true
인자를 전달해 parallel 미들웨어를 사용하게 하고, 이것은 save
인 경우 각 미들웨어에서 done 호출 전까지 실행하지 않는다는 의미이다.
1 | var schema = new Schema(..); |
#### Use Cases
미들웨어는 원자화 모델과 비동기 코드의 중첩을 회피하는데 유용한다. 아래 같은 사례:
- 복합 유효성 확인
- 의존하는 문서 삭제 (사용자에 관련한 모든 문서를 삭제)
- asynchronous defaults
- asynchronous tasks that a certain action triggers
- triggering custom events
- notifications
#### 에러 처리
미들웨어에서 Error
형식 매개변수로 next(), done() 을 호출할 때 에러로 처리가 가로채지면 콜백 함수에 에러가 전달된다.
아래 같이 에러 발생시 new Error()
를 생성해야 다음 next()
가 호출되지 않는다.
1 | schema.pre("save", function (next) { |
### Post middleware
post middleware 는 pre middle 웨어가 완료되어 훅 메서드가 처리된 뒤에 실행된다. post 는 제어를 직접 하지 못한다. 예를 들어 next(), done() callback이 전달되면 post 훅은 이들 메서드를 이벤트 리스너에 등록하는 방법이다.
1 | schema.post("init", function (doc) { |
#### Asynchronous Post Hooks
post가 선언된 순서에 따라 post hook이 비동기 적으로 실행되는데, callback function에 두 개의 인자를 전달하면 mongoose는 두번째를 next()
로 가정하고 순서에 따라 next를 트리거 호출한다.
1 | // Takes 2 parameters: this is an asynchronous post hook |
#### Save/Validate Hooks
The save()
함수는 validate()
hook을 유발하는데 이것은 pre('save')
hook이 호출되면서 pre('validate')
와 post('validate')
hook이 호출된다는 것이다.
1 | schema.pre("validate", function () { |
#### Notes on findAndUpdate() and Query Middleware
Pre 와 post save() hook은 update()
, findOneAndUpdate()
등에서 호출되지 않는다. Mongoose 4.0 은 이들 함수에 다른 훅을 가지고 있다.
1 | schema.pre("find", function () { |
document middleware에서 this
는 갱신하는 도큐멘트를 가르킨다. 그래서 update()
에 타임스탬프를 추가하고자 하면 아래 pre hook을 사용한다.
1 | schema.pre("update", function () { |
Error Handling Middleware
New in 4.5.0
일반적으로 next() 호출시 첫번째 error에서 멈추는데 특별한 post middleware로 “error handling middleware” 가 있다.
Error handling middleware는 부가적으로 콜백 함수의 매개변수에 error
가 전달되는데, 첫번째 인자로 error
를 전달한다.
1 | var schema = new Schema({ |
Error handling middleware는 query middleware와도 동작한다. 예를 들어 update() 호출시 키 중철 에러를 처리하는 훅를 고려하면:
1 | // The same E11000 error can occur when you call `update()` |
## 참조
NodeJS - mongoose middleware
https://blog.thinkbee.kr/2017-12-20-mongodb-mongoose-middleware-871f925b40c0/