관계형 데이터베이스는 스키마를 미리 정해 정합성을 지키고 조인으로 흩어진 데이터를 모읍니다. NoSQL 은 이 둘을 내려놓는 대신 수평 확장을 쉽게 얻습니다. 어느 쪽이 좋은 게 아니라 무엇을 포기할 수 있는지의 문제입니다.
무엇이 갈리나
| 항목 | 관계형 | NoSQL |
|---|
| 스키마 | 미리 정의. 어긋난 데이터는 거부된다 | 유연. 문서마다 필드가 달라도 된다 |
| 조인 | 질의에서 처리 | 대개 없음. 쓸 때 미리 합쳐 둔다 |
| 확장 | 수직(서버를 키운다)이 기본 | 수평(서버를 늘린다)이 기본 |
| 트랜잭션 | 여러 행에 걸쳐 보장 | 문서 하나 단위가 흔하다 |
| 일관성 | 즉시 | 최종 일관성인 경우가 많다 |
왜 NoSQL 이 수평 확장에 유리한가
조인을 포기했기 때문입니다. 조인이 필요하면 관련 데이터가 같은 노드에 있어야 하는데,
노드를 늘릴수록 그 보장이 어려워집니다. 조인을 버리면 데이터를 키로 잘라 아무 노드에나
흩어 놓을 수 있습니다.
그래서 NoSQL 로 옮긴다는 것은 읽는 모양대로 미리 저장한다는 뜻입니다. 화면 하나에
필요한 것을 한 문서에 모아 두는 식입니다. 대신 같은 값이 여러 곳에 중복되고, 바뀔 때
전부 고쳐야 합니다.
고르는 기준
| 상황 | 선택 |
|---|
| 돈, 재고처럼 틀리면 안 되는 값 | 관계형. 트랜잭션이 필요하다 |
| 질의 모양을 미리 다 알 수 없다 | 관계형. 조인으로 나중에 조합한다 |
| 쓰기가 매우 많고 모양이 고정적이다 | NoSQL. 키로 잘라 흩는다 |
| 필드가 자주 바뀌거나 항목마다 다르다 | NoSQL. 스키마 변경 비용이 없다 |
면접에서 자주 갈리는 지점
"NoSQL 은 빠르다"는 답은 절반입니다. 같은 조건이면 오히려 느릴 수도 있습니다. 빠른
이유는 엔진이 아니라 조인과 즉시 일관성을 포기한 설계입니다. 무엇을 포기했는지 말할 수
있어야 이유를 설명한 것이 됩니다.
관계형도 수평 확장을 합니다. 읽기는 복제로, 쓰기는 샤딩으로 나눕니다. 다만 샤딩을 하면
샤드를 넘는 조인과 트랜잭션이 어려워져 NoSQL 과 같은 고민을 하게 됩니다.
Q.RDB와 NoSQL의 차이를 설명해주세요
무엇을 보장하고 무엇을 포기했는지가 다릅니다.
| 항목 | 관계형 | NoSQL |
|---|
| 스키마 | 미리 정의한다. 어긋난 데이터는 거부된다 | 유연하다. 항목마다 필드가 달라도 된다 |
| 조인 | 질의할 때 조합한다 | 대개 없다. 쓸 때 미리 합쳐 둔다 |
| 확장 | 수직이 기본. 샤딩은 추가 설계 | 수평이 기본 |
| 트랜잭션 | 여러 행에 걸쳐 보장한다 | 문서 하나 단위가 흔하다 |
핵심은 조인을 포기한 대가로 수평 확장을 얻었다는 것입니다. 조인이 필요하면 관련
데이터가 같은 노드에 있어야 하는데, 노드를 늘릴수록 그 보장이 어려워집니다.
흔한 실수: NoSQL 이 더 빠르다고 답하는 것. 같은 조건이면 오히려 느릴 수도 있습니다.
빠른 이유는 엔진이 아니라 조인과 즉시 일관성을 포기한 설계이고, 무엇을 포기했는지
말하지 못하면 이유를 설명한 것이 아닙니다.
Q.NoSQL로 옮길 때 데이터 모델링이 어떻게 달라지나요
질의 모양을 먼저 정하고 그 모양대로 저장합니다. 관계형은 반대로 정규화해 두고 질의할 때 조합합니다.
관계형은 이렇게 둡니다.
주문, 사용자, 상품을 각각 테이블로 나눠 저장한다
주문 상세 화면에서 세 테이블을 조인해 조합한다
NoSQL 은 이렇게 둡니다.
주문 문서 하나에 사용자 이름과 상품 이름을 함께 넣어 저장한다
화면에서 문서 하나만 읽는다
읽기는 한 번으로 끝나 빨라집니다. 대가는 중복입니다. 사용자가 이름을 바꾸면 그 이름이
박혀 있는 주문 문서를 모두 찾아 고쳐야 합니다.
그래서 판단 기준은 바뀌는 빈도입니다. 주문 시점의 상품명처럼 당시 값을 남겨야 하는
것은 중복이 오히려 정확합니다. 반대로 자주 바뀌고 항상 최신이어야 하면 중복은 부담이 됩니다.
흔한 실수: 스키마가 없으니 설계가 필요 없다고 답하는 것. 스키마 정의를 데이터베이스가
강제하지 않을 뿐이고, 설계는 애플리케이션으로 옮겨온 것입니다. 강제가 없으니 실제로는
더 신중해야 합니다.
Q.결제나 재고 데이터를 NoSQL에 두면 어떤 문제가 생기나요
여러 문서에 걸친 변경을 한 번에 되돌릴 수 없습니다.
재고를 줄이고 결제를 기록하는 두 작업이 서로 다른 문서라면, 하나만 성공한 상태가 생길
수 있습니다. 관계형은 트랜잭션으로 둘을 묶어 실패 시 함께 되돌립니다.
| 문제 | 나타나는 모습 |
|---|
| 부분 성공 | 재고는 줄었는데 결제 기록이 없다 |
| 이중 차감 | 재시도가 같은 작업을 두 번 반영한다 |
| 최종 일관성 | 방금 줄인 재고를 다른 노드에서 아직 옛 값으로 읽는다 |
우회 방법은 있습니다. 한 문서에 함께 담아 단일 문서 원자성을 쓰거나, 보상 트랜잭션으로
실패를 되돌리거나, 멱등 키로 재시도를 막습니다. 다만 전부 직접 만들어야 하는 것입니다.
흔한 실수: 요즘 NoSQL 도 트랜잭션을 지원한다고 답하고 끝내는 것. 지원 범위와 성능
대가가 제품마다 다르고, 샤드를 넘는 트랜잭션은 비싸거나 제약이 붙습니다. 지원 여부보다
어디까지 보장되는지를 말해야 합니다.
Q.관계형도 확장할 수 있는데 NoSQL로 넘어가는 기준은 무엇인가요
관계형으로 못 버텨서가 아니라, 관계형의 장점을 이미 포기한 시점입니다.
관계형도 확장합니다. 읽기는 복제로 나누고 쓰기는 샤딩으로 나눕니다. 그런데 샤딩을 하면
샤드를 넘는 조인과 트랜잭션이 어려워집니다. 즉 샤딩을 시작한 순간 NoSQL 과 같은 고민을
하고 있는 것입니다.
| 이 순서로 점검한다 | 아직 넘어갈 필요 없음 |
|---|
| 인덱스와 질의 튜닝 | 대부분 여기서 해결된다 |
| 캐시 도입 | 읽기 부하가 문제일 때 |
| 읽기 복제 | 읽기가 쓰기보다 훨씬 많을 때 |
| 샤딩 | 쓰기가 한 노드 한계를 넘을 때 |
이 단계를 다 밟고도 모자라고, 질의 모양이 고정적이며 조인이 필요 없다면 그때가 기준입니다.
흔한 실수: 데이터가 많으니 NoSQL 로 간다고 답하는 것. 양보다 질의 모양과 쓰기
처리량이 기준입니다. 수억 행이어도 인덱스가 맞으면 관계형이 잘 처리합니다.
먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.
읽었으면 문제로 확인해보세요
데이터베이스 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.