ODM(Mongooes)가 아닌 패키지(mongodb)를 통해 DB에 직접 접근하기

kukjunLEE·2023년 6월 12일
2

Trouble Shooting

목록 보기
2/5
post-thumbnail

본 내용은 프로젝트를 진행하면서 겪었던 TroubleShooting 경험을 담고 있습니다.
Nestjs를 사용하면서 이전에는 Mongooes를 사용했습니다, 하지만 요구사항에 따른 문제가 발생해서 이 문제를 해결하기 위해서 MongoDB를 직접 다루는 패키지를 사용한 경험과 이를 통해서 얻은 효과와 문제점, 그리고 더 나은 방식은 어떤 것이 있는가에 대해서 이야기 해 보고자 합니다.



배경


Nestjs로 프로젝트를 진행하던 도중, 하나의 요구사항이 늘어났습니다.

특정한 컬럼의 값을 가지는 모든 컬렉션의 도큐먼트를 삭제해야 한다.

해당 업무를 진행하기 위해서는 단순하게 모든 컬렉션을 돌면서 해당 컬럼의 값이 일치하는지 찾고, 그것을 지우는 작업을 하면 됩니다.

미리 프로젝트엣 설정되어 있는대로, 우리는 데이터베이스에 직접 접속하는게 아닌 ODM(Object Data Mapping)을 사용하고자 했습니다. 따라서, mongooes를 사용해서 문제를 해결하고자 했습니다.

하지만 문제점이 발생했는데, 그 문제는 모든 도메인이 한 곳에 구성되어 있지 않다는 점입니다.



만약 요구사항이 F Collection이 1인 것을 지우고, 모든 컬렉션의 F_ID 필드가 1인 경우를 지워라. 라고 한다면, 다음의 그림처럼 작성될 것입니다.



이러한 문제를 ODM(Mongooes)를 이용해서 해결하려고 한다면, 모든 컬렉션에 대한 Schema를 만들고, 데이터베이스에 저장된 Collection과 구조를 일치시켜야 합니다.


이러한 방식으로 작성하게 된다면, 기껏 분리해 놓았던 ABCD 도메인도, 다시 합쳐지게 되고, 모든 Schema를 다시 작성해야 합니다. 🥲



그래서, 다른 방법을 사용할 수는 없을까 하고 고민해보게 되었습니다.




해결 과정


문제를 해결할때 생각해야 할 점들은 다음과 같습니다.

  1. 지금 있는 구조를 해쳐서는 안된다.
  2. 빠른 시간안에 문제를 해결할 수 있어야한다.

ODM을 이용하지 않고, 직접 DB에 접근하는 방식을 사용해서 해당 기능을 구현할 수 있지 않을까?

문제를 해결하기 위해 DB에 직접 접근하도록 한다면,

  1. F Collection이 1인 것을 지운다.
  2. MongoDB의 모든 컬렉션을 찾는다.
  3. 각각 컬렉션에서 F_ID가 1인 경우를 지운다.

해당하는 작업을 통해서 요구사항을 만족시킬 수 있습니다.




분석


해당 방법이 최선인가?
요구사항을 만족했지만, 최선의 방법은 아니다.

왜냐하면 해당 작업은 명백하게 해당 도메인을 구성하는 Backend 역할을 넘어서고 있기 때문입니다.

ODM을 사용하는 이유는 데이터의 정합성과 명시하지 않은 동작은 하지 않도록 할 수 있다는 장점이 있습니다. 그렇지만 지금처럼 데이터베이스에 직접 접근하는 방식은 동작을 예상할 수 없습니다.

지금의 경우에는 MongoDB의 모든 컬렉션을 찾는 코드는 우리가 명시하지 않고 있다보니 만약 지우면 안되는 Collection인 경우에도 삭제가 이루어질 수 있다는 점과, DB구조에 대해서 Nestjs에서 알 방법이 없다는 점이 문제가 될 수 있습니다.

문제를 해결하기 위한 최선의 방법은 무엇인가?
도메인을 확실하게 분리(MS구조로 변경)하거나 합쳐야 한다.

도메인을 합치는 방법을 사용하면, 당연히 ODM에서 해당 문제를 해결하는 가장 편한 방법이 될 수 있지만, 기껏 분리해놓은 도메인을 합치는 방법은 별로 메리트가 있지는 않습니다.

도메인을 확실하게 분리한다는 것은 MS구조로 만들어서 각각의 서버가 요청, 응답을 받을 수 있는 구조로 구조화를 한다는 것입니다.

그림으로 표현하면 다음과 같습니다.

해당 구조와 같이 MSA를 도입하면, ODM만을 이용해서도 각각의 동작을 분리할 수 있다.




참고


단일 DB 인스턴스 사용 시, DB에 Trasaction을 걸 수 없는 문제가 발생

NOSQL DB가 단일 인스턴스라면, 트랜잭션 안의 동작에 의해 DB가 변경되었을때, Rollback을 할 수 있는 정보가 부족하기 때문입니다.
일반적으로 몽고디비는 트랜잭션을 구성할 수 없습니다. ACID, 즉 명령어 여러개를 하나처럼 묶여서 실행할 수 있는 능력이 없습니다.

하지만 여러개의 명령어를 트랜잭션 처럼 동작하는 기능이 필요한 경우가 있는데, Mongooes를 이용해면 해당기능을 내부적으로 구현하고 있습니다.

  • 아마 내 생각에는 Mongooes가 트랜잭션을 실행시키면 해당 명령을 한번에 모았다가 정합성을 체크하고 진행하는 게 아닌가 싶긴 합니다만, 추후 더 자세하게 하나의 내용으로 다뤄보고자 합니다.

그래서 MongoDB가 단일 인스턴스인 경우에는 직접 DB에 접근할 때, 트랜잭션을 적용할 수 없고, DB를 확장(샤딩, 레플리카셋)한 후에 Transaction을 사용할 수 있습니다.

왜 그런지에 대해서 찾아보고 블로그를 써보도록 하겠습니다. 🥹



MongoDB Instance을 확장하는 방법

MongoDB Instance를 확장하는 방법은 샤딩과 레플리카셋을 이용하는 방법이 있습니다.

샤딩은 수평적인 데이터 확장을 위해 데이터를 분할하여 여러 서버에 분산 저장하는 방식이며, 레플리카셋은 데이터의 복제를 통해 고가용성을 제공하는 방식입니다. 어떤 전략을 선택할지는 시스템의 요구사항과 용도에 따라 다르며, 일반적으로는 샤딩과 레플리카셋을 조합하여 대용량 데이터 처리와 고가용성을 동시에 제공하는 방식을 사용하기도 합니다.

해당 내용에 대해서 블로그로 업로드하도록 하겠습니다. 🥹

profile
Backend Developer

0개의 댓글