DB의 주체 App은 1개 이어야 한다

Bonjugi·2023년 10월 8일
0

App과 DB 관계에서 이상적인건 1:1이다.

App1 -> DB1

그다음으로 이상적인건 1:N 이다.

App1 
	-> DB1
  	-> DB2

절대 지양 해야 할것은 N:1 (또는 N:N) 이다.

APP1
APP2
	-> DB1

요약하자면, DB의 master(app)은 반드시 1개 이어야 한다.
이는 monolith던 msa던 매우 엄격하게 지켜야할 사항이라 생각한다.

modular monolith도 일반적으로 1:1이 될것으로 생각된다.
modular monolith에 대해서는 잘은 모르지만, 여러개의 모듈이 있더라도 배포 단위는 (app) 1개이다.
또한 DB도 일반적으로 1개만 두는듯 하다. 이러면 1:1이 맞다.
다만 모듈간의 느슨한 결합도를 위해 논리적으로라도 table에 prefix를 주던지 등의 방법으로 격리를 추구한다.
더욱 강하게 격리 하기 위해 모듈별로 DB를 1개씩 두는 방법도 있는듯 하다.
이렇게 되면 app 1개에 DB가 여러개처럼 보일수 있겠다.
하지만 일시적이라고 생각되며 코드베이스가 1개일뿐 bc가 각각 다르기 때문에 app도 db도 여러개라고 생각할수 있겠다.
이러면 1:1 관계라고 볼수 있겠다.
https://www.youtube.com/watch?v=Xo3rsiZYsJQ&ab_channel=MilanJovanovi%C4%87 의 후반부를 참고하자

구체적으로..

1:1, 1:N, N:1 순으로 설명을 했다.
1:1은 설명할 필요없는 가장 이상적인 구조이다.
1:N은 필요시 사용하고, N:1은 절대 지양해야 한다.

1:N 에 대해서

다음과 같은 상황에서 필요해질수 있다.
충분히 괜찮다고 본다.

  • 기술적으로 다른 영속성툴을 이용하기 위해 (geometry, full-text, log..)
  • read db 분리하기 위해

기술적으로 다른 툴을 이용하기 위한 1:N

적극적으로 사용하면 된다.
필요해서 사용하는데 누가 말리겠는가?

단, 가용성이 떨어진다는 점을 고려하자. (0.9x0.9=0.81)
고가용성을 달성하기 위해선 결국 비용이 발생한다.
매니지드 서비스라고 해도 패치하때 완전히 신경끄고 숙면할수 있는것도 아니다.
100% 가용성이더라도 어쨌든 비용이 든다는 점이다.

postgresql 의 경우 jsonb도 다루고, inverted index도 가지고 있다.
다른 전문 툴들과 비교해서도 대체로 준수한 성능이 나오는것으로 알고있다.
geometry 정보도 매우 효과적으로 처리한다.
꼭 다른 툴을 활용해야 할지는 충분히 검토해보자.

읽기 전용을 위한 1:N

읽기 전용 DB를 구축해야할까?
그냥 기존의 DB 하나로 처리하면 될텐데?
타당성은 다음과 같다

  1. read를 위한 스키마는 구조가 다름
  2. read, write가 격리. read가 write에 영향을 주지 않음
  3. 트래픽을 분산 하기 위한 목적 (write 전용, read 전용으로)

1번은 잘못된 생각이다.
그냥 같은 DB 내에서 새로운 스키마로 테이블을 짜면 된다.
논리적으로 분리되면 됐지, 꼭 물리적으로 나눌 필요가 없다.
transactionManager로 분기처리를 하든 모듈로 분기처리를 하든 해야한다.

그리고 복잡도를 낮춰줄수 있다.
appliation 내에서 join을 안하려고 하는 편이긴 하지만, 운영중엔 되는게 낫다.
2개 DB에 커넥션해서 쿼리 하는것 보다 훨씬 간편할 것이다.

2번도 잘못된 생각이다.
위에서 얘기했듯, 다른 프로세스를 활용하는 이상 0.9x0.9=0.81 법칙이 적용된다.
읽기가 죽고 쓰기만 살아있어도 되는 케이스는 없다.
둘다 99.9999% 를 목표로 해야한다.
구축된 기존의 DB에선 이미 고가용성을 위해 적어도 2대의 인스턴스로 구축했을것이고, 큰 비용을 쓰고 있을 것이다.
읽기 DB를 굳이 구축해서 고가용성 달성을 시뮬레이션 해보면 비용이 만만치 않을것이다.

3번은 타당한 편이다.
스케일업이나 인스턴스 증설로는 한계가 있기 때문이다.
투입되는 비용대비 성능향상은 갈수록 미비해진다.
하지만 이말은 반대로 초기 투자는 극적으로 향상된다.
누구나 들어봄직한 서비스가 아닌 이상, 높은 확률로 스케일업이나 인스턴스 증설로이 훨씬 싸게 먹힐 것이다.

1:N을 절대 지양 하자는게 절대 아니다.
1:N은 지극히 일반적 이고, 기능 달성을 위해 반드시 필요하다.
다만 무작정 늘려서 좋을것은 없다는것이 없으므로, 꼭 필요한것인지를 말하고 싶었다.
이러한 단점들을 인지하고 있음에도 계속 회자되는 상황이라면 오히려 반드시 도입해야 하는 상황일수도 있다.
읽기 전용을 위한 1:N 구성은 기술적 문제로 도입하는것보다는 좀더 비판적으로 얘기 했는데, 추후 이전이 비교적 쉽다고 생각해서 인데, 이는 비교적일뿐.. 사실상 둘다 매우매우 비싸다.
b2c 서비라면 처음부터 적극적으로 추천한다.

N:1 (또는 N:N) 에 대해서

많은곳에서 N:1은 안티패턴으로 소개하는 케이스다. (당연히 N:N 은 더더욱)
"똥인지 된장인지 안먹어봐도 알아야 한다" 라는 말이 적용되는 사례라, 깊게 리서치 해본 적도 없지만, DB는 거버넌스가 매우 중요하기 때문이다.

  1. 스키마 구조의 변형은 app에 지대한 영향을 주기 떄문 (너무 중요해서 flyway 등으로 관리한다. 또한 스키마가 일치하지 않으면 app은 실행조차 안되는게 안전하게 여겨질 정도)
  2. ddl, dml(cud)이 한곳을 통해서만 처리되지 않으면 락에 잘 걸리기 때문 (낙관적이든 비관적이든 s락이든 x락이든..)
  3. db 케파를 예측하기 어렵기 때문 (어떤 api가 얼마나 호출하는지, 얼마나 인덱스에 비 친화적으로 쿼리하는지 추적이 어려움)
  4. 코드 추적이 어렵다. 원래는 inbound부터 보면 될것을, db부터 추적해야 한다. 사내 모든 repo에서 테이블명을 검색해야 할지도 모른다.

결론

N:1은 절대절대 하지말자.
1:N은 필요에 따라 충분히 해도 된다. (할수밖에 없다)
혹시 1:1로 풀어낼수 있다면 1:1을 먼저 고려하자.

0개의 댓글