1. 문제 상황
회사에서 신규 프로젝트 운영을 위해서 python으로 백오피스를 구현하고 있습니다.
리스트로 이루어진 데이터가 입력으로 오면, 이 데이터를 mongoDB에서 조회해서 가공한 후에 지도에 출력하는 프로젝트 입니다.
문제는 성능이 나오지 않았습니다.
42개의 데이터를 조회 및 처리하는 데에 5초나 걸렸습니다.
2. 원인
mongoDB가 해외에 위치해 있습니다. 그러다보니 query를 날리고 응답을 받는데에 시간이 오래 걸릴 것이라고 생각했습니다.
특히 이런 IO 작업을 싱글 쓰레드로 처리하다 보니 속도가 느려졌다고 생각했었습니다.
3. 해결
그래서 싱글 쓰레드로 동작하던 것을 멀티 쓰레드로 변경했습니다.
python의 GIL이 있지만, mongoDB에서 데이터를 가져오는 IO 작업 부분을 멀티 쓰레드로 작업하기 때문에 큰 상관은 없습니다.
약 max_worker를 20개로 설정해서 실험을 해봤습니다.
기존에 5초가 걸리던 작업이 약 2.3초까지 줄어든 것을 확인했습니다.
42개의 데이터를 가져오는 데 2.3초나 걸리는 것은 성능이 많이 느리다고 생각했습니다.
그래서 다른 해결 방안을 찾고 있었습니다.
이번에는 데이터의 개수가 약 4500개를 조회하도록 하고 max_worker를 100까지 증가시켰습니다.
무려 24초나 걸렸습니다.
이번엔 mongoDB에 index를 생성해서 조회를 해봤습니다.
24초 -> 16초까지 성능은 개선이 되었습니다. 무려 8초나 줄었기 때문에 여기서 만족하고 다른 일을 처리하러 갔습니다.
그러던 중, kafka의 partitioner가 생각이 났습니다.
kafka의 경우 produce를 할 때, partitioner의 전략(sticky, round robin)에 따라 데이터를 어느 partition에 데이터를 넣을 지 결정합니다. 그리고 이를 바로 kafka에 전송하는 것이 아니라, 설정한 batch 개수 만큼 쌓거나 일정 시간 지난 후에 한 번에 보내게 됩니다.
이렇게 한 이유가 네트워크 통신 비용을 줄이려고 그랬다는 내용이 갑자기 떠올랐습니다.
그래서 데이터 개수만큼의 쿼리를 전송하는 것이 아니라, 하나의 쿼리로 여러 데이터를 조회하도록 수정했습니다.
무려 16초에서 3.7초까지 성능이 개선 되었습니다.
특히 해외에 mongoDB가 있다보니 여러 쿼리를 날리고 응답을 받는 것이 성능에 큰 이슈가 있었던 것으로 파악이 됩니다.
결론
개선 방법 | 성능 |
멀티 쓰레드로 조회 | 24 s |
mongoDB index 생성 | 16 s |
싱글 쓰레드로 쿼리 하나로 여러 데이터 조회하도록 수정(Bulk) | 3.7s |
실제 다른 기능도 멀티 쓰레드로 구현이 되어 있었습니다. 데이터를 많이 조회하지도 않는데, 7초나 소모됩니다.
이 부분을 맡은 팀원 분에게도 해당 내용 공유를 드렸습니다.
이 기능까지 성능이 개선이 된다면, 전체 프로세스가 기존 31초에서 약 4초까지 성능이 개선될 것으로 예상이 됩니다.
4. 느낀 점
당연히 batch로 데이터를 전송하는 것이 성능이 좋다는 것은 알고 있었습니다. 하지만 이 당시에 제 코드를 작성하고 있을 때는 여러 쿼리를 날리는 것이 문제가 될 것이라고 생각하지 못했습니다. 머리로는 알고 있었지만, 응용은 하지 못했었습니다.
머리로만 알던 지식을 완전히 제 것으로 만들기 가장 쉬운 방법은 프로젝트 경험이라는 것을 느낄 수 있었습니다.
(그래서 개발 동아리가 끝난 후에도, 팀원을 구해서 사이드 프로젝트를 계속 유지보수할 생각입니다.)
성능 개선하는 것이 보람차고 즐겁네요.
성능이 중요한 일을 해보고 싶네요.
'BackEnd > 이슈 정리' 카테고리의 다른 글
[DB, REDIS] PostgreSQL 및 Redis Cluster 관련 이슈 (0) | 2025.02.25 |
---|---|
로깅 로직 수정 (1) | 2024.12.15 |
[REDIS] 레디스 조회 성능 개선 - 1 (1) | 2024.10.02 |
[Webflux] 대용량 데이터 처리 heap 사용량 이슈 (0) | 2024.08.03 |