본문 바로가기

카테고리 없음

[nestjs] typeorm 페이지네이션 만들기 (take, skip이용)

typeorm의 take과 skip은 limit과 offset과 비슷하게 사용되며 페이징할때 더 효율적이다.

복잡한 쿼리문이 들어갈 경우 (가장 단편적인 예를 들어 페이지네이션같은 작업의 경우)에는 limit, offset이 제대로 작동하지 않을 수 있다. 따라서 database의 조인문이나 쿼리문을 제대로 읽지 못할 수 있기 때문에 이를 대신하여 take,skip을 많이 사용한다.

 

하단 설명 및 코드는 javascript의 slice기능을 사용해서 작업해보았던 초기 작업 코드와, typeorm을 활용한 (take,skip) 간단한 구현코드이다. 혹시 나와 같은 초보 nestjs 사용자가 참고해보면 좋을 듯하여 부끄럽지만 비교 코드를 남긴다.

 

**typeorm take skip 개념**

skiip(n)의 경우 단독으로 사용하게 되면  getRepository의 n번째열까지 건너뛰고 가져오게 된다.

take(m)의 경우 skip된 열부터 m번째 열까지 slicing한 데이터를 가져온다.

 

 //1.초기: javascript slice 사용하여 페이징 => 매번 totalQList를 불러와야함
 if (req.category === '작성자') {
        let totalQList = !(
          req.userId === '' ||
          req.userId === null ||
          req.userId === undefined
        )
          ? await this.customenrCenterQ.find({
              userId: req.userId,
            })
          : await this.customenrCenterQ.find();
        result.QList = totalQList;
        
        // let totalPageCount = Math.ceil(totalQList.length / slicePage);
        // result.totalPage = totalPageCount;
        // result.totalSearchCount = totalQList.length;
        // result.QList = totalQList.slice(
        //   (clickPage - 1) * slicePage,
        //   clickPage * slicePage,
        // );
      }
//2.typeorm의 find에 where, take, skip 으로 검색 기능 완성 가능
//=> CustomerCenterQ 에서 req.userId 값으로 들어오는 검색어를 찾고, take로 페이징 단위 설정, skip으로 페이지 시작점부터 끝지점 설정
//findAndCount로 searching한 리스트와 갯수한꺼번에 불러오기 
 if (req.category === '작성자') {
        let [searchQlist, searchQlistCount] = await getRepository(
          CustomerCenterQ,
        ).findAndCount({
          where: {
            userId: Like('%' + req.userId + '%'),
          },
          order: {
            createdAt: 'DESC',
          },
          take: slicePage,
          skip: (clickPage - 1) * slicePage,
        });

        result.QList = searchQlist;
        result.totalSearchCount = searchQlistCount;
      }

그리고 추가적으로 queryBuilder로 take,skip 설정하는 방법과 typeorm의 find로 take,skip 설정하는 방법은 유사하다. 

필자는 비교적 사용방법이 간단하고, mysql에서 사용하는 쿼리문에 익숙하지 않아 잘 사용하진 않지만, 간혹 가다가 join 문 등을 사용할 경우가 있고 그 조건식에 추가로 페이징을 더할 경우가 생겨 하단에 참고해 놓았다.

차이점이라고 하면 repository에서 바로 가져올 경우에는 where조건식에 함께 기입하며, queryBuilder를 사용할 경우 하단 처럼 내장되어있는 함수로 호출한다. 

//3.queryBuilder 안에서의 take, skip
const ABC = await data
    .getRepository(DATA)
    .createQueryBuilder("data")
    .leftJoinAndSelect("data.photos", "photo")
    .skip(5)
    .take(10)
    .getMany()

예시가 다양하진 않지만, 혹여라도 기능이 헷갈리거나 참고가 부족하다면 typeorm의 official docs를 참고해보면 도움이 많이 될것 같다.