이번에 사이드 프로젝트를 하며 검색 기능을 구현하게 되었는데 이때 Mongoose 의 aggregate 메소드를 사용했다. 

 

검색 기능 구현을 위해 Atlas Search 를 이용했는데, 이를 이용하려면 데이터 조회 시 find 대신 aggregate를 사용해야 했다. ($search)

 

구현을 위해 알아본 aggregate 에 대한 정보를 find 와 비교하여 정리했다. 

 

1. aggregate 란

aggregate 는 모으다, 집합, 집계 등의 의미를 가지고 있는 단어이다. Mongoose 에서는 find 와 같이 데이터를 조회할 때 사용하는 메소드이지만 find 보다 더 복잡한 처리를 지원하는 파이프라인 메소드라고 이해하면 된다. 

 

복잡한 계산, 변형, 조인, 통계 분석에 최적화되어있다. 

 

2. aggregate 매개변수

aggregate() 는 매개변수로 배열을 받는다. 배열 안에는 다양한 연산자가 올 수 있는데 aggregate 는 이 연산자들을 순차적으로 처리한다. 

 

아래 코드는 Model 에서 이름이 'Junseo' 인($match) Document 에서 name, age, _id 필드를 가져오고($project) age 를 내림차순으로 정렬($sort)한 다음 최대 10개까지 반환($limit)하는 로직이다. 

Model.aggregate([
  { $match: { name: 'Junseo' } },
  { $project: { name: 1, age: 1, _id: 0 } },
  { $sort: { age: -1 } },
  { $limit: 10 }
]);

 

3. find 와 차이점 / 장점

단순 조회인 find 에 비해 aggregate는 더욱 확장된 연산을 지원한다. 대표적으로는 Join, Grouping 이 있다. 

 

3-1. Join 

먼저 흔히 알려져있는 find() 의 populate는 Join이 아니다. Join 처럼 보이지만 내부적으로 어플리케이션 레이어에서 두번의 로직을 실행하는 것이다.

 

하지만 아래 코드와 같이 aggregate 을 사용하면 MongoDB 단에서 한번의 조회를 통해 Join 을 구현할 수 있다.

Order.aggregate([
  {
    $lookup: {
      from: 'users',
      localField: 'userId',
      foreignField: '_id',
      as: 'userInfo'
    }
  },
  { $unwind: '$userInfo' },
  { $project: { orderNumber: 1, userName: '$userInfo.name' } }
]);

 

3-2. Grouping

아래 코드와 같이 MongoDB에서 grouping 을 할 수 있다. find 로는 구현이 불가하다. 

User.aggregate([
  { $group: { _id: '$age', count: { $sum: 1 } } },
  { $sort: { count: -1 } }
]);

 

 

또한 Atlas Search 의 기능을 aggregate을 통해 구현할 수 있다. 

아래 코드는 이번에 검색 기능을 구현한 코드의 일부분이다. $search 연산자가 Atlas Search 를 이용하는 연산자이다.  

searchPipeline.push(
      {
        $search: {
          index: 'geo',
          compound: {
            should: keywordScoreQuery,
            minimumShouldMatch: 1,
            ...(geoFilterQuery ? { filter: geoFilterQuery } : {}),
          },
        },
      },
      ... 중략

 

4. 단점과 보완 방법

완벽해보이는 메소드지만 단점도 있다.

 

1. find 에 비해 속도가 느림

여러 연산을 처리하도록 설계되어 있다보니 당연히 find에 비해 절대적인 성능은 좋지않다. 

 

따라서 aggregate를 사용할 땐 Index를 잘 활용하여 성능을 뒷받침해주어야 한다. 

(여담으로, Atlas Search 를 사용할 땐 무조건 Search Index 라는 것을 설정해야 한다.) 

 

2. 코드 복잡성 증가

위에 올린 코드들만 봐도 find 에 비해 가독성이 확 떨어진다. 연산자 이름도 직관적이지않다보니 더욱 부각되는 것 같은데, 주석을 잘 활용해야 할 것 같다. 

'Backend > Mongoose' 카테고리의 다른 글

Mongoose Geo-Query / Geo-JSON 사용법  (0) 2025.06.19