본문 바로가기

Database

[Mongo] find / limit query의 중요성 (feat. Array.slice())

가설 및 검증
가설

db에서 모든 데이터를 가져온 후 router에서 slice를 하는 것보다

limit을 활용해 db에서 일부만 가져오는 것이 더 빠를 것이다.

 

테스트 코드

1. 백엔드로 api 요청을 보난 후 프론트로 데이터가 넘어오는 시간을 확인함

2. 50초 동안 1초 간격으로 시간을 측정한 후 그 평균 값을 측정

3. 총 5번 반복

let timeAcc = 0
timeTest();

async function timeTest() {
  console.log("start");
  let count = 0
  let interval = setInterval(() => {
    getProductList($homeProductListNew, 'new')
    count += 1
    console.log("count:", count)
  }, 1000)
    
  setTimeout(() => {
    clearInterval(interval)
    setTimeout(() => {
      console.log("Avg: ", timeAcc/count)
    }, 1000)
  }, 50000)
}

async function getProductList(ele, getApi) {
	const start = +new Date()
    const result = await Api.get(`/api/products/list/${getApi}`);
    const end = +new Date()
    const diff = end - start
    timeAcc += diff
    console.log("time:", diff)
    console.log("timeAcc:", timeAcc);
    printProductList(ele, result)
}

 

첫번째 방법: slice in router

- 모든 데이터를 가져온 후 router에서 slice하는 방법

// router.js

// 최신 순
productRouter.get('/list/new', async (req, res, next) => {
  try {
    const allProducts = await productService.getProducts();
    const products = allProducts
      .sort((a, b) => b.createdAt - a.createdAt)
      .slice(0, 4);
    res.status(200).json(products);
  } catch (err) {
    next(err);
  }
});

//getProducts는 어떠한 파라미터도 갖지 않는 findAll 메서드에 해당하여 
//service, model에 특별한 코드가 없어 첨부하지 않음.

- 측정 결과

각 시도 별 평균 시간: [ 94, 119, 87, 80, 148 ]

시도 1
시도 2
시도 3
시도 4
시도 5

두번째 방법: limit in model(db)

- DB에서 find, sort, limit query를 이용하기

// router.js
productRouter.get('/list/new', async (req, res, next) => {
  try {
    const products = await productService.getProductsByFieldRank("createdAt", -1, 4)
    res.status(200).json(products);
  } catch (err) {
    next(err);
  }
});

// productService.js
async getProductsByFieldRank(field, sort, limit) {
    const products = await this.productModel.findByRank(field, sort, limit)
    return products;
}

// productModel.js
async findByRank(field, sort, limit) {
    const products = await Product.find().sort({[field]: sort}).limit(limit)
    return products
}

- 테스트 결과 

각 시도 별 평균 시간: [ 38, 34, 28, 38, 30 ]

시도 1
시도 2
시도 3
시도 4
시도 5

가설 검증!

 


평가
코드 리팩토링

1. router에서의 중복되는 코드를 지울 수 있음.

2. 재사용성이 높은 model 구현

 

 

 

소감

1. 테스팅 측면

interval을 활용하여 평균 값을 측정하지 않았을 때는 시간 차이가 두드러지지 않아보였는데,

평균 값을 구하고 여러번 시도를 한 결과를 보니 꽤나 유의미한 속도 차이가 두드러졌다. 

앞으로 성능을 확인하고 싶을 때 테스트 코드 또한 꼼꼼한 검증을 거칠 수 있도록 작성하면 좋겠다.

 

2. db 측면

limit query의 중요성을 체감하였다. 앞으로 db에서 데이터를 활용할 땐 최대한 qeury를 통해 값을 처리해야겠다.

 

3. 백엔드 직무 칙면

성능에 대한 고려를 꾸준히 해야겠다! 테스트한 코드는 소규모 프로젝트(documents가 50개도 안 됨)였기에 성능에 대한 생각을 미처 하지 못했는데, 앞으로는 더 꼼꼼히 따져보아야겠다.