백엔드팀 기술 세미나 - Tech Talk ①
| "최소한의 인덱스로 레이턴시 줄이기"
MongoDB 운영 경험에 대해
백엔드팀 권태훈님, 노정훈님
| 들어가기에 앞서
안녕하세요, 미리캔버스 백엔드팀입니다.
저희는 미리캔버스라는 디자인 플랫폼의 기반을 설계하고, 그 위에 새로운 기능을 더하고, 더 나은 속도와 안정성을 고민하는 팀입니다.
서비스가 빠르게 성장하면서, 해결해야 할 기술 과제도 늘 많아지고 있죠.
이런 환경에서 가장 중요한 건 결국 ‘사람’과 ‘팀’이라고 생각합니다.
좋은 제품은 좋은 팀에서 나오고,좋은 팀은 각자가 조금씩이라도 성장하고 있다는 믿음 위에서 만들어진다고 믿거든요.
그래서 한 달에 한두 번, 저희는 사내에서 기술 세미나를 열고 있습니다.
발표자는 정해져 있지 않고, 주제도 자유로워요.
리팩토링 후기일 때도 있고, 운영 중에 알게 된 작은 팁이나 새로 도입해본 라이브러리에 대한 얘기가 나올 때도 있습니다.
형식보다 중요한 건 서로의 경험을 나누는 일 그 자체입니다.
누군가의 고민이 다른 팀에 작은 힌트가 되기도 하고,그런 이야기들이 쌓이면서 팀 전체가 조금씩 앞으로 나아가는 걸 느껴요.
그게 결국 더 나은 제품으로 이어질 거라고 믿고 있습니다.
| 이번 세미나는 MongoDB 운영 경험에 대해 다뤘어요
이번 세미나에서는 워크스페이스 파트에서 MongoDB를 운영하면서 겪었던 문제들과, 그걸 해결하기 위해 어떤 시도들을 했는지를 공유했습니다.
생각보다 많은 팀이 비슷한 고민을 하고 있었고, 발표가 끝난 뒤에도 Q&A와 토론이 꽤 길게 이어졌어요.
미리캔버스 백엔드는 모놀리식 구조를 MSA 구조로 전환하는 작업을 진행하고 있습니다.
워크스페이스 파트에서는 담당 도메인 데이터들을 PostgreSQL에서 MongoDB로 분리했는데요, 약 10억개의 데이터베이스 행들을 마이그레이션하여 운영 중에 있습니다.
이번 세미나에서는 MongoDB로 서비스를 운영하면서 알게 된 노하우들을 공유했습니다.
워크스페이스 파트는 미리캔버스의 인증, 인가와 디자인, 디자인 요소를 관리하는 파일 시스템을 담당하고 있습니다.
도메인 특성 상 외부 시스템의 데이터를 저장해야 하고, 다양한 조건으로 조회 요청을 받고 있습니다.
MSA 전환과 동시에, 기존의 미리캔버스 에디터를 개선한 에디터 2.0을 개발하여 전환해나가고 있는데요,
에디터 2.0에서 만들어진 디자인과 디자인 요소들은 기존 에디터의 데이터와 분리되어 조회되어야 하는 요구 사항이 생겼습니다.
관계형 데이터베이스와 다르게, MongoDB에서 필터링 조건의 추가는 성능에 큰 영향을 미치고 있었습니다.
기존에 만들어져 있던 인덱스를 잘 활용하지 못하고, scanned keys 같은 쿼리 관련 지표가 올라가고 있었습니다.
인덱스를 활용해 MongoDB의 쿼리 실행을 최적화 하려면, 인덱스 필드들을 다음과 같은 순서로 배치해야 합니다.
첫 번째로 동등 조건에 사용되는 필드들입니다.
RDB에서 Cardinality가 높은 컬럼을 인덱스 앞에 배치하듯 동등 조건을 적용하여 스캔할 Object 수를 줄입니다.
두 번째로 정렬 기준이 되는 필드들입니다.
동등 조건을 적용된 Object를 가져올 때, 인덱스에서 정렬된 채 가져올 수 있도록 하여, in memory sort 단계를 제거합니다.
세 번째로 범위 조건에 사용되는 필드들입니다.
MongoDB는 정렬된 Object들에 대하여 마지막으로 범위 조건 필터링을 적용하여 쿼리의 결과를 산출합니다. 범위 조건은 인덱스와 약하게 바인딩되어 scan 수를 불가피하게 늘리므로, 지양해야 하는 조건입니다.
워크스페이스 파트의 쿼리는 경로 외에도 타입, 서브타입, 버전 같은 조건들을 함께 사용하고 있었습니다.
이 세 가지 필드는 상황에 따라 포함되기도, 빠지기도 했기 때문에 모든 조합을 커버하려면 많은 인덱스를 만들어야 하는 구조였죠.
인덱스가 늘어날수록 쓰기 성능에 영향을 줄 수 있어, 데이터 모델 자체를 단순화하는 방향으로 접근했습니다.
우리는 타입, 서브타입, 버전 정보를 하나의 문자열로 묶어 일종의 태그처럼 저장하고, 그 필드를 기준으로 쿼리하는 방식으로 구조를 개선하고자 했습니다. 따라서 처음에는 태그를 배열 형태로 저장하고 MongoDB의 MultiKey 인덱스를 활용했지만, scanned keys 수치와 document scanned/returned 비율이 높아지는 문제를 발견하게 되었습니다.
결국 배열 대신 단일 문자열 필드로 구성된 태그 인덱스로 전환했고, 필요한 인덱스 개수를 줄이면서 쿼리 레이턴시도 안정적으로 관리할 수 있었습니다.
다만, 미리캔버스에는 다양한 타입의 디자인 요소가 존재하고 있기 때문에 여러 태그를 한 번에 조회해야 할 경우 $in 조건이 복잡해지는 이슈는 여전히 남아 있습니다. 앞으로 해결해나가야 할 과제로 보고 있습니다.
| 글을 마치며
업무 시간을 들여 세미나를 열고, 참석하는 이유는 단순합니다.
바쁜 일정 속에서도 ‘요즘 내가 어떤 걸 고민하고 있는지’, ‘다른 사람은 어떤 걸 시도해봤는지’ 편하게 이야기할 수 있는 자리가 있으면 좋겠다고 생각했어요.
발표를 준비하면서 지난 작업을 돌아보는 사람도 있고, 비슷한 기술을 쓰는 다른 팀의 이야기를 들으며 자기 팀 문제를 다시 고민해보게 됐다는 얘기도 있었어요.
“알고 있는 지식들을 다른 팀원 분들에게도 도움이 되도록 정리하는 과정에서
다시 한 번 되돌아 보고 배울 수 있는 기회가 되어서 좋았습니다.
파트 내에서 고민 중이었던 문제에 대한 해결책도 파트원들과 다시 한 번 고민해볼 수 있는 기회가 되어 더욱 유익했습니다!”
“저희 파트에서도 몽고DB를 사용하고 있는데,
이번 세미나를 통해 다른 도메인에서 몽고DB를 사용하며 겪었던 문제와 해결 방법을 공유 받을 수 있어 매우 유익했습니다!”
이런 말들이 나올 때마다,이 세미나가 좋은 방향으로 가고 있다는 생각이 듭니다.
세미나는 이제 막 시작됐고, 다루고 싶은 주제도 많습니다.
다음에는 어떤 이야기들이 이어질지, 우리도 기대하고 있어요.
앞으로 다양한 세미나 발표 내용으로 찾아뵙도록 하겠습니다!
평소에 서비스 운영에서 겪었던 문제를 팀과 함께 논의하고, 성장하는 문화를 만들어가고 싶다면 백엔드 팀에 합류해 주세요!