(Node.js) MongoDB : Document를 JavaScript Object로 변환하기

호두파파·2021년 8월 9일
1

Node.js

목록 보기
16/25

![]

빠르고 간단하게 API를 개발할 때는 Node.js + Express.js + mongoDB 조합을 많이 사용하는 편이다. 추가로 mongoDB ODM(Object Document Mapping)인 mongoose를 활용해 DB를 관리한다.

mongoose를 이용해서 데이터를 조회한 후 해당 데이터를 json 형태로 변환해서 바로 response를 보낼 때에는 별 문제가 없지만, 해당 데이터를 spread operator로 분해하거나 unit 테스트할 때 종종 원치않는 데이터가 포함된 것을 확인할 수 있다.

예상했던 모습

{
    "name": "hodoopapa",
    "position": "개발자",
    "roles": [
      "ADMIN"
    ]
}

실제로 담겨 있는 모습

{
  "$__": {
    "$options": {
      "defaults": true
    },
    "$setCalled": {},

    // ... (생략)

    "backup": {
      "activePaths": {
        "default": {
          "_id": true
        },
        "modify": {
          "name": true,
          "position": true,
          "roles": true
        }
      }
    },
    "cachedRequired": {},

    // ... (생략)

    "getters": {},
    "inserting": true,
    "pathsToScopes": {
      "roles": "[Circular reference found] Truncated by IDE"
    },
    "session": null,
    "strictMode": true,
    "validating": null,
    "wasPopulated": false
  },
  "$locals": {},
  "$op": null,
  "_doc": {
    "__v": 0,
    "_id": "[Circular reference found] Truncated by IDE",
    "name": "hodoopapa",
    "position": "개발자",
    "roles": [
      "ADMIN"
    ]
  },
  "isNew": false
}

Mongoose Document

mongoose Query를 통해서 조회된 데이터는 단순한 Plain Old JavaScript Object(POJO)가 아닌 Mongoose Document형태이기 때문이다.

Mongoose Document는 아래와 같은 것들을 포함하고 있다.

  • Changing tracking
  • Casting and validation
  • Getters and Setters
  • Virtual
  • save()

추가 정보와 메서드들을 포함하고 있기 때문에 Query 결과 값을 가지고 수정한 후 save()메서드를 통해서 수정된 내용을 DB에 반영할 수 있는 것이다.

const findAndUpdateName = async (oldName, newName) => {
  const user = await User.findOne({ name: oldName });
  user.name = newName;
  const savedUser = await user.save();
  
 return savedUser;

Plain Old JavaScript Object(POJO)

다른 정보나 메서드를 사용하지 않는다면 굳이 Mongoose Document를 사용할 필요가 없다. 그래서 보통 toObject()메서드를 사용해 POJO로 변환해 사용하곤 한다.
이보다 조금 더 효율적인 메서드가 있는데 그것은 lean()메서드이다.

toObject()메서드를 이용하는 경우 Query 결과를 Mongoose Document로 만들기 위한 과정을 거쳤다가 다시 POJO로 변환되는 반면, lean() 메서드를 이용할 경우 중간 과정 없이 바로 POJO를 반환한다.

toObject() 메서드 이용

const findbyName = async (name) => {
  const user = await User.findOne({ name });
  	return user.toObject();
};

lean() 메서드 이용

const findByName = async (name) => {
  const user = await User.findOne({ name }).lean();
	return user;
};

lean() 메서드의 사용

lean()메서를 이용해서 얻은 데이터는 Mongoose Document가 아니기 때문에 추가정보나 save()와 같은 메서드들은 사용이 불가능하다. 그래서 아래와 같은 경우 사용을 권장한다.

  • Express response와 같이 어떠한 수정없이 Query결과를 바로 전송하는 경우
  • Query 결과를 수정하지 않고 custom getter를 사용하지 않는 경우

참고

profile
안녕하세요 주니어 프론트엔드 개발자 양윤성입니다.

0개의 댓글