문제의 API
MongoDB를 사용하던 중
조회하는 Document의 갯수가 많아졌을 때 유난히 느려지는 API를 발견하였습니다. 거의 사용을 못할 지경에 이르렀는데요

조회를 한번에 많이 할수록 느려지는건 맞지만 너무 과하게 느려져서 살펴보게 되었습니다.
문제 찾아보기
1. Api 백엔드 로직에서 많은 요소를 조회시 느려지게 할만한 로직이 있었나?
백엔드 로직을 살펴 보았을 때 별도의 로직은 없었고 조건에 맞게 조회해서 return만 해주는 역할을 하는 API였습니다.
2. DB에 인덱스가 제대로 잡혀있었나??
Mongo Compass를 이용해서 해당 쿼리 filter 조건을 explane을 돌렸을때
아래와 같이 인덱스를 잘 타고 있었고 조회시간도 6ms로 굉장히 빠르게 조회되고 있었습니다.

그러면 여기서 DB조회 성능의 문제가 아니란 것은 알수 있었습니다.
3. DB와 Server간에 네트워크 통신비용이 큰가? 전체 필드를 가져와서 문제가 생기는건가?
실제로 해당 Document Schema에는 많은 필드
(nested object까지 합치면 90개가 넘는 필드)
가 있었고 이중 특정 몇몇 필드에는 많은 양의 string 데이터가 들어있었습니다.
이 수많은 필드 모두 가져오면서 통신비용으로 많은 시간을 잡아먹는게 아닌가 싶었습니다.
그래서 테스트로 _id만 조회를 하도록 테스트를 해보았습니다. 
27초에서 10초가 줄어서 개선 되기는 했으나 여전히 db 조회시간에 비해 엄청나게 많이 걸리고 있었습니다.
따라서 DB와 Server간의 네트워크 비용이 메인문제가 아니라는 것을 알 수 있었습니다.
Mongoose Lean
이 후에 다른 개발자분께 여쭤보면서 원인을 찾게 되었는데 원인는 Mongoose Model에 있었습니다.
mongoose를 사용하게 되면 일반적으로 아래와 같이 스키마를 정의해서 사용하는데
typegoose 예시
해당 Model에서 find 조회시 Example이라는 Instance가 만들어지게 됩니다.
이 Instance안에는
save()
, get()
또는 custom으로 만든 instanceMethod가 존재하게 됩니다.
하지만 제가 원하는 API는 find한 결과물을 내보내주는 역할밖에 하지 않기 때문에 Instance화는 필요가 없습니다. 더군다나 InstanceMethod는 더더욱 사용하지 않구요.
위와같은 요구사항으로 단순 조회할때 성능을 끌어올리기 위해 나타난게 mongoose의 Lean입니다.
lean은 조회된 결과물에 대해 Instance를 생성하지 않고 받은 그대로 POJO 형태로 반환하게 합니다. 단순한 순수 Object이게 된거죠.

위와 같이 인스턴스를 생성하지 않게 되면 별도의 instanceMethod도 생성되지 않으니 성능에 큰 이점이 있습니다.
사용 법도 굉장히 간단합니다.
기존 조회 방식에 lean이라는 method를 체이닝 형태로 실행시켜주면 됩니다.
Mongoose Document 내용에 따르면 차지하는 용량만 하더라도 5배 정도의 차이가 난다고 합니다.
위는 name이라는 필드 하나만 테스트 했지만 custom instance함수나 다른 추가적인 요소들이 들어가게 된다면 차이가 더 나게 됩니다.
적용해보기
처음에 보았던 느린 API에 Lean을 적용시켜 보았는데요

30초 가까이 걸리던 쿼리의 시간이 엄청 줄어든 것을 확인 할 수 있었습니다.
이후 쿼리의 조건에서 불필요한 조건들을 더 줄이고

필요한 필드만 projection 했을때

더 큰 성능 개선을 할 수 있게 되었습니다.