티스토리 뷰
사용 Node.js 라이브러리
🌝express-async-handler
Express.js에서 비동기식 요청 핸들러를 처리하기 위한 미들웨어(async error handleing middleware for Express)
Express.js의 기본 요청 핸들러는 예외 처리를 하지 못하는 경우가 많기 떄문에, 이를 해결하기 위해 만들어진 미들웨어 라이브러리이다. 이 라이브러리를 사용하면 예외 처리가 가능한 비동기식 요청 핸들러를 쉽게 작성할 수 있다.
- async를 쉽게 사용할 수 있고, Request Handler를 처리하는데 공통적으로 오류처리를 할 수 있거나 간단하게 구현할 수 있다.
1-1. request handler의 오류처리
Q. What is request handler in Express?
A. A request handler is a function that will be executed every time the server receives a particular request, usually defined by HTTP method. It accepts two parameters request and response.
- promise().catch(next)
- async function, try ~ catch, next
1-2. async request handler
- async의 비동기 처리는 매우 편리하지만, 매번 try ~ catch 구문을 작성하는 것은 귀찮고 실수하기 쉽다.
- request handler를 async function 으로 작성하면서 try- catch, next를 자동으로 할 수 있도록 구상한 아이디어다.
사용법:
const asyncHandler = require('express-async-handler')
express.get('/', asyncHandler(async (req, res, next) => {
const bar = await foo.findAll();
res.send(bar)
}))
without express-async-handler
express.get('/',(req, res, next) => {
foo.findAll()
.then ( bar => {
res.send(bar)
} )
.catch(next); // error passed on to the error handling route
})
async-handler 가 동작하는지 postman으로 확인해보기
🌝bcrypt
해싱: 일방향성 암호화의 일종으로, 입력된 데이터를 고정된 길이의 문자열로 바꾸는 것
비밀번호를 해싱(hashing)하기 위한 라이브러리이다. 해싱 알고리즘 중 하나인 bcrypt 알고리즘을 사용하며, 안전하고 강력한 해싱을 제공한다.
- 주로 사용자 비밀번호를 해싱하여 데이터 베이스에 저장하는 용도로 사용된다.
- 비밀번호를 검증할 때에는 입력된 비밀번호를 해싱하여 디비에 저장된 해시값과 비교한다. 이를 통한 원본 비밀번호를 보호할 수 있다.
몽구스(ODM)란?
시퀄라이즈(관계형 데이터베이스 a.k.a. RDBMS와를 다룰 때 유용한 도구, SQL 쿼리를 자동으로 생성해주는 등의 기능을 제공한다. SQL 데이터베이스를 다루는 라이브러리므로 NoSQL과는 호환되지 않음)와 달리 릴레이션(DB의 `테이블`과 유사개념)이 아닌 도큐멘트를 사용하므로 ORM이 아니라 ODM(Object Document Mapping)이라고 불린다.
Q. 몽고디비 자체가 JS인데 왜 굳이 JS객체와 매핑해서 사용할까?
A. 몽고디비에 없어서 불편한 점들을 몽구스가 보완해주어 서버단에서 NoSQL DB를 프로그래밍하는데 최적화하기 때문이다.
몽고디비에는 없던 `스키마`라는 개념이 생김(DB의 스키마를 말하는 것)
원래 몽고디비에는 테이블 개념이없어(collection) 자유롭게 데이터를 넣을 수 있지만, 이 자유분방함이 오히려 독이 된다.
e.g.) 실수로 잘못된 자료형의 데이터를 넣거나 다르 도큐멘트에는 없는 필드의 데이터를 넣을 수도 있기 때문이다.
몽구스는 몽고디비에 데이터를 넣기 전 노드 서버 단에서 데이터를 한 번 필터링하는 역할을 해준다.
또한, 몽고디비 쿼리를 프로미스 객체로 만들어주어 강력하고 가독성이 높은 쿼리 빌더를 지원하는 것도 장점
*몽구스 ODM 문법 자체가 몽고디비 SQL문이기 때문에 몽고 DB의 종합적인 지식이 필요함
all ref: 인파 dev님 mongoose 사용법 정리
몽구스 쿼리 메서드를 사용하여 User 모델 API 만들기
만들어놓은 모델 User과 Note를 가져온다. express의 기본 요청 핸들러는 예외 처리를 하지 못하는 경우가 많기 때문에 express-async-handler를 가져와서 사용해준다.
controllers/userController.js
const User = require("../models/User");
const Note = require("../models/Note"); // 컨트롤러 내부에서 참조할 수도 있으니까 가져온다.
const asyncHandler = require("express-async-handler");
const bcrypt = require("bcrypt");
// @desc GEt all users
// @route GET /users
// @access Private
const getAllUsers = asyncHandler(async (req, res) => {
//find, select, lean 메서드는 mongoose의 메서드
const users = await User.find().select("-password").lean();
if (!users) {
return res.status(400).json({ message: "No users found" });
}
res.json(users);
});
- get 요청을 유저 컨트롤러에 만들어본 모습이다. User.find()를 처음봤을 때는 array.find()인줄 알았으나 select와 lean을 보고 JS 내장 메서드가 아닌 거 같았다. 당연하게도 User은 몽구스 스키마로 만들어진 모델이다. 그렇다면 `find(), select(), lean()`은 몽구스에서 제공하는 메서드(쿼리 메서드 or 체이닝 메서드 라고 불린다)이다.
- 코드 설명: find()로 User 모델을 조회하고, select("-password")로 조회된 결과에서 password 필드를 제외한 필드만 조회하고, lean()로 조회된 결과를 JS객체(POJO)로 변환한다.
- 마지막 줄의 `res.json(users)` => 에서 명시적인 상태 코드가 없는 이유: Express에서 명시적으로 상태 코드를 설정하지 않고 `res.json()` 또는 `res.send()` 메소드를 호출하면, 기본적으로 200 OK 상태 코드가 반환된다. 또한, 클라이언트 측에서도 서버에서 지정한 상태코드가 없을 시, 기본적으로 200 OK 상태 코드를 받게 된다.
- JavaScript Object = POJO
Q. 조회된 결과를 왜 JS객체로 변환해야하나?
A. `몽구스 쿼리`를 통해서 조회된 데이터는(다른 말로하면 `리턴값`이) 단순한 Plain Old JavaScript Objects(POJO)가 아닌 Mongoose Document 형태이기 때문이다.
-> 다른 정보나 메서드를 사용하지 않는다면 굳이 `몽구스 도큐멘트`를 사용할 필요가 없다. 보통은 toObject() 메서드를 사용하여 POJO로 변환해도 된다. 하지만, lean() 메서드를 사용하면 훨씬 더 효율적이다.
*Mongoose Document > POJO => 용량 10배 이상의 차이를 가짐
toObject() : Query 결과를 몽구스 도큐멘트로 만들기 위한 과정을 거쳤다가 다시 POJO로 변환
lean(): 중간 과정없이 바로 POJO 반환
Mongoose Document 가 포함하는 것들
- Change tracking
- Casting and validation
- Getters and setters
- Virtuals
- `save()`
추가 정보와 메서드를 포함하고 있어 Query 결과 값을 가지고 수정한 후, `save()` 메서드를 통해 수정된 내용을 DB에 반영할 수 있다.
e.g.)
const findAndUpdateName = async (oldName, newName) => {
const user = await User.findOne({ name: oldName });
user.name = newName;
const savedUser = await user.save();
return savedUser;
};
몽구스 쿼리(유사 프로미스)와 exec()메서드
몽구스 메서드들은 유사 프로미스를 반환하여 프로미스 체이닝이 가능하게 만들어주는데, 이때, 반환되는 유사 프로미스를 몽구스에서 Query 라고 부른다. 대부분의 몽구스 메서드들이 쿼리를 반환하며 then()을 사용할 수 있게 한다(유사 프로미스라서). 하지만, 이 쿼리를 반환하는 메서드에 exec() 메서드를 사용하면 `쿼리`가 아니라 `온전한` 프로미스를 반환값으로 얻을 수 있다.
+ 추가 설명: exec() 메서드는 몽구스의 쿼리 메서드에서 마지막으로 사용되는 메서드로, 실제 쿼리를 실행시키는 역할을 한다. 그리고 exec()는 콜백을 받아들일 수 있는 콜백 스타일로 실행할 수 있으며 그렇지않으면 프로미스 스타일로 실행된다. 따라서 쿼리 메서드를 호출한 뒤 exec()를 붙여주는 것은 해당 쿼리를 실행시키기 위한 명령어를 추가하는 것이다. 이를 통해 몽구스에서 지원하는 콜백 스타일과 프로미스 스타일 중에서 원하는 방식으로 결과를 받을 수 있다.
그러나 만약에 lean() 메서드를 사용한다면, exec()를 생략하고 바로 프로미스를 반환받을 수 있다. lean()메서드는 쿼리 결과를 JS객체로 바꿔주어, 데이터를 더 가볍게 처리할 수 있게 해준다.
> 몽구스에서 쿼리를 실행하면 Promise를 반환한다고 한다.
이렇게 되면 에러가 났을 때, stack trace에 오류가 발생한 코드의 위치가 포함되기 때문에 디버깅에 좋다. docs에서도 exec()의 사용이 권장된다.
const user = await User.findById(id).exec();
'프로그래밍 > Node.js' 카테고리의 다른 글
[Node.js | DB] Sequelize와 MySQL (0) | 2023.05.16 |
---|---|
[mongoDB | mongoose] node프로젝트에 mongoDB 연결하기 (0) | 2023.05.07 |
[Node.js] cors() 라이브러리와 프리플라이트 (0) | 2023.04.28 |
[Node.js] date-fns JS 날짜 라이브러리와 CommonJS module vs ES module (0) | 2023.04.28 |
[Node.js] Express는 무엇인가 (0) | 2023.04.27 |
- Total
- Today
- Yesterday
- && 셸 명령어
- 프리온보딩 프론트엔드 챌린지 3월
- 원티드 프리온보딩 프론트엔드 챌린지 3일차
- 틸드와 캐럿
- ~ ^
- 원티드 FE 프리온보딩 챌린지
- is()
- nvm 설치순서
- tilde caret
- 형제 요소 선택자
- float 레이아웃
- text input pattern
- 항해99프론트후기
- 원티드 3월 프론트엔드 챌린지
- 항해99추천비추천
- 타입스크립트 DT
- getServerSideProps
- 부트캠프항해
- 프리렌더링확인법
- D 플래그
- fs모듈 넥스트
- Prittier
- reactAPI
- 원티드 프리온보딩 FE 챌린지
- 항해99프론트
- 타입스크립트 장점
- getStaticPaths
- nvm경로 오류
- grid flex
- aspect-ratio
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |