싸피의 특화 프로젝트를 진행하며 뉴스 기사를 조회할 일이 생겼다.
2023년 180만 건의 뉴스 기사 데이터를 가지고 있었는데 이것을 DB에 적재하고, 필요할 때 조회하는 방식으로 사용할 계획이었다.
처음에는, 이전 프로젝트에서 사용했던 RDB인 MySQL에 뉴스 데이터를 저장하려했지만 2가지의 고민을 하게 되었다.
- "Read"만을 위한 데이터
CRUD 중 Read만 하는 데이터를 굳이 관계형 데이터베이스에 저장할 필요가 있을까?- 일관적이지 않는 형식
A 기사는 5개의 필드를 가지고, B 기사는 6개의 필드를 가지는 일관적이지 않은 형식의 데이터는 어떤 데이터베이스가 어울릴까?
이러한 고민을 바탕으로 새롭게 NoSQL인 MongoDB를 사용하기로 했다.
MongoDB를 사용한 이유는 다음과 같다.
이를 고려하여 MongoDB를 사용하였고, FastAPI에서 특정 일자의 뉴스 기사를 불러오게 하였다.
180만 건의 뉴스기사 중 딱 1년 전 데이터를 불러오는데 생각보다 시간이 오래 걸렸다.
위의 그림은 쿼리를 실행하고 FastAPI 서버까지 데이터를 가져오는데 걸리는 시간을 측정한 것이다.
7144개를 가져오는데 3.6초가 걸렸고, 1520개 정도만을 가져오는데도 2초가 걸렸다.
우리의 서비스는 첫 번째로 뉴스 기사를 조회, 두 번째로 키워드를 추출하여 화면에 뿌려줘야 하기에, 최대한 빠르게 처리해야 했다.
TF-IDF Tokenizer를 통해 키워드를 뽑는 작업을 진행하는데, 라이브러리를 가져다 쓴 것 이므로 이 작업의 시간을 줄이긴 힘들겠다고 판단하여 조회 속도의 개선에 집중하였다.
MongoDB는 index 기능이 매우 잘 되어있으므로 이를 적용해보고자 하였다.
기사 데이터는 모두 published 라는 필드를 가진다.
시간이 오래걸렸던 쿼리의 조회 기준인 published(기사 출간일)에 오름차순으로 단일 필드 인덱스를 생성했다.
단일 필드 인덱스에서는 오름차순, 내림차순 어디를 기준으로해도 똑같으므로 오름차순으로 걸었다.
식별자인 _id 외의 published_1의 이름으로 인덱스가 생성되었다.
published에 인덱스를 적용시킨 후, 다시 조회 쿼리를 실행하고 시간을 측정해 보았다.
2초가 걸렸던 쿼리 실행시간이 0.01초로 줄어든 것을 확인할 수 있었다.
성능이 너무나 향상되었는데, 어떻게 이게 가능할까?
공식문서에 따르면 MongoDB의 index는 B-tree 방식을 사용한다고 한다.
B-Tree는 루트 노드에서부터 하향식으로 탐색을 수행하게 된다.
해당 과정을 리프노드에 도달할 때까지 반복하는데, 만약 리프노드에도 k와 같은 key가 없다면 검색을 실패하게된다.
처음으로 DB의 index 기능을 사용해서 조회 성능을 향상할 수 있었다.
다음엔, NoSQL이 아닌 RDB에서도 index 기능을 사용해서 조회 속도를 개선해보자.