NoSQL 데이터 모델링 (NoSQL Data Modeling)
목차
- NoSQL 데이터 모델링이란
- 왜 접근 패턴이 먼저인가
- 문서 경계와 Aggregate
- Embed vs Reference
- 중복 저장과 동기화 비용
- 문서 크기, 배열 성장, Hot Partition
- MongoDB 모델링 예시
- Firestore 모델링 예시
- RDBMS 모델링과의 차이
- 면접 포인트
- 참고 자료
NoSQL 데이터 모델링이란
NoSQL 데이터 모델링(NoSQL Data Modeling) 은
테이블 정규화보다 조회 패턴과 쓰기 패턴에 맞춰 데이터 경계를 설계하는 작업에 가깝습니다.
이 문서는 데이터베이스 구현·운영 관점에서 NoSQL 저장소에 데이터를 어떻게 배치할지를 다룹니다.
왜 RDBMS 대신 NoSQL을 선택하는지 같은 저장소 선택 판단은 NoSQL 데이터베이스, 데이터베이스 설계 문서와 함께 보면 경계가 더 분명합니다.
백엔드 면접에서 NoSQL 모델링은 보통 다음 질문으로 이어집니다.
- 어떤 데이터를 한 문서에 같이 넣을 것인가
- 어떤 관계는 중복 저장하고 어떤 관계는 참조로 둘 것인가
- 조인이 없거나 비싼 환경에서 조회를 어떻게 풀 것인가
- 문서가 커지거나 특정 파티션에 트래픽이 몰리면 어떻게 할 것인가
즉, 핵심은 “스키마가 자유롭다”가 아니라
접근 패턴을 보고 데이터 경계를 의도적으로 설계할 수 있는가입니다.
RDBMS 관점의 스키마 설계는 데이터 모델링 (Data Modeling) 문서가 더 직접적입니다.
왜 접근 패턴이 먼저인가
RDBMS 모델링은 보통 엔티티, 관계, 정규화를 먼저 생각합니다.
반면 NoSQL 모델링은 가장 자주 하는 조회와 쓰기 흐름이 무엇인지부터 확인하는 편이 자연스럽습니다.
예를 들어 다음 질문이 먼저 나옵니다.
- 주문 상세 화면에서 한 번에 무엇을 읽어야 하는가
- 사용자 프로필을 읽을 때 권한, 설정, 최근 활동을 같이 읽는가
- 타임라인은 최신순 조회가 핵심인가
- 특정 사용자나 리전에 쓰기가 집중되는가
이 질문이 중요한 이유는 다음과 같습니다.
- 조인이 없거나 제한적일 수 있음
- 문서 단위 원자성이 모델의 기본 단위가 되기 쉬움
- 분산 저장소에서는 파티션 키와 접근 경로가 성능을 크게 좌우함
좋은 답변은 “NoSQL은 비정형 데이터에 좋다”에서 끝나지 않고,
핵심 API나 화면이 어떤 읽기 경로를 요구하는지 먼저 보고 모델을 잡는다고 설명하는 편이 좋습니다.
문서 경계와 Aggregate
NoSQL 모델링에서 중요한 질문 중 하나는
“어디까지를 한 문서 또는 한 레코드로 묶을 것인가”입니다.
이때 실무적으로는 같이 읽히고 같이 수정되는 데이터를 먼저 묶어 봅니다.
- 주문과 주문 항목을 거의 항상 같이 읽는가
- 프로필과 설정을 한 요청에서 같이 가져오는가
- 댓글 수 같은 요약 값은 원본과 같이 두는가
문서 경계를 정할 때 자주 보는 기준은 다음과 같습니다.
- 원자성 범위: 한 번에 같이 업데이트돼야 하는가
- 조회 결합도: 거의 항상 같이 조회되는가
- 크기 증가 패턴: 시간이 지나도 문서가 과하게 커지지 않는가
- 수명주기: 부모와 자식 데이터가 같은 시점에 생성/삭제되는가
예를 들어 상품 문서에 짧은 태그와 대표 가격을 같이 두는 것은 자연스러울 수 있습니다.
반면 수천 건으로 계속 늘어나는 주문 이벤트 로그를 같은 문서에 계속 쌓는 것은 위험할 수 있습니다.
NoSQL 문서 경계는 결국 데이터 의미 + 접근 패턴 + 성장 패턴을 같이 봐야 합니다.
Embed vs Reference
NoSQL 데이터 모델링에서 가장 자주 나오는 질문입니다.
| 방식 | 설명 | 장점 | 주의점 |
|---|---|---|---|
| Embed | 관련 데이터를 같은 문서 안에 중첩 저장 | 한 번에 읽기 좋고 문서 단위 원자성 활용 가능 | 문서가 커질 수 있고 부분 갱신 비용이 커질 수 있음 |
| Reference | 다른 문서의 식별자를 참조 | 중복이 줄고 독립 수명주기 관리가 쉬움 | 추가 조회가 필요하고 조인 부재를 앱이 감당해야 함 |
Embed가 잘 맞는 경우
- 항상 부모와 함께 읽는 작은 하위 데이터
- 문서 크기가 안정적으로 유지되는 경우
- 한 번에 같이 수정돼야 하는 경우
예:
- 주문 문서 안의 주문 항목 요약
- 사용자 문서 안의 작은 설정 객체
- 게시글 문서 안의 소수 태그
Reference가 잘 맞는 경우
- 자식 데이터가 계속 증가하는 경우
- 독립 조회와 독립 수정이 자주 필요한 경우
- 부모보다 수명주기가 긴 경우
예:
- 사용자와 주문 목록
- 상품과 리뷰
- 게시글과 댓글 전체 목록
면접에서는 “embed가 빠르다”보다
같이 읽고 같이 수정되는 작은 데이터는 embed, 독립 수명주기이거나 커지는 데이터는 reference라고 설명하는 편이 좋습니다.1
Reference를 과하게 쓸 때 생기는 N+1성 읽기 문제
NoSQL에서도 RDBMS에서 말하는 N+1 문제와 비슷한 read amplification 이 생길 수 있습니다.
예를 들어:
- 게시글 목록 100건을 읽고
- 각 게시글의 작성자 문서를 다시 100번 조회하거나
- Firestore에서 문서 참조를 따라 개별 문서를 반복 조회하면
결과적으로 목록 1번 조회 + 참조 문서 N번 조회 구조가 될 수 있습니다.
이 문제는 join이 없어서 사라지는 것이 아니라,
참조를 애플리케이션이 직접 따라가면서 네트워크 round trip이 늘어나는 형태로 바뀌는 것에 가깝습니다.
대표 대응은 다음과 같습니다.
- embed: 자주 같이 읽는 작은 필드는 문서에 포함
- 중복 저장:
authorName,thumbnailUrl같은 조회용 필드 일부를 함께 저장 - batch read: 가능하면 여러 키를 한 번에 읽도록 묶기
- 모델 재조정: 문서 경계를 다시 나눠 조회 횟수 자체를 줄이기
좋은 답변은 “NoSQL에는 N+1이 없다”가 아니라
조인 대신 다건 참조 조회로 같은 문제가 다시 나타날 수 있다고 설명하는 편이 더 정확합니다.
중복 저장과 동기화 비용
NoSQL에서는 읽기 성능과 단순한 조회를 위해 중복 저장(denormalization) 을 더 적극적으로 허용하는 경우가 많습니다.
예를 들어:
posts컬렉션에 작성자 이름과 프로필 이미지 일부를 같이 저장user_feed문서에 게시글 요약을 중복 저장orders문서에 배송지 스냅샷을 함께 저장
이 방식의 장점은 분명합니다.
- 조회가 단순해짐
- 추가 조회나 조인 비용이 줄어듦
- 읽기 경로 latency를 줄이기 쉬움
하지만 대가도 있습니다.
- 같은 값이 여러 군데 퍼짐
- 값 변경 시 여러 문서를 같이 갱신해야 할 수 있음
- 비동기 보정이나 재동기화 작업이 필요할 수 있음
즉, NoSQL 모델링은 “중복을 허용할 수 있는가”보다
그 중복을 나중에 어떻게 동기화하고 운영할 것인가까지 같이 봐야 합니다.
좋은 답변은 “NoSQL이라 중복 저장합니다”가 아니라
조회 성능을 위해 중복 저장하되, 원본 소스와 갱신 경로를 분명히 둔다고 설명하는 쪽입니다.
문서 크기, 배열 성장, Hot Partition
NoSQL 모델링은 처음엔 단순해 보여도, 운영 단계에서 다음 문제가 자주 나옵니다.
문서 크기 증가
- 작은 설정 객체를 넣는 것은 괜찮지만
- 무한히 늘어나는 이벤트나 댓글을 계속 같은 문서에 누적하면 문제가 됩니다
문서가 커질수록 다음 위험이 있습니다.
- 읽기/쓰기 비용 증가
- 전송 크기 증가
- 부분 갱신이 어려워짐
배열 성장
배열은 문서형 DB에서 자주 쓰이지만, “계속 늘어나는 리스트”를 한 문서에 몰아넣는 것은 조심해야 합니다.
- 최근 3개 태그: 자연스러움
- 수천 개 댓글 ID: 위험할 수 있음
- 수만 개 좋아요 사용자 ID: 더 위험함
Hot Partition / Hot Document
분산 저장소에서는 특정 키나 문서에 읽기/쓰기가 몰리면 병목이 생길 수 있습니다.
- 인기 게시글 하나에 좋아요 쓰기가 집중
- 타임스탬프 기반 키만 써서 특정 파티션으로 몰림
- 카운터 하나를 모든 요청이 동시에 갱신
이 문제를 줄이기 위해 다음 전략을 검토합니다.
- 파티션 키 분산
- 카운터 샤딩
- 읽기 전용 요약 문서 분리
- append-only 이벤트와 집계 문서 분리
NoSQL 모델링은 결국 데이터 구조뿐 아니라 트래픽 분포까지 설계 대상입니다.2
MongoDB 모델링 예시
MongoDB에서는 문서 중심 모델링이 핵심입니다.
예를 들어 주문 모델을 다음처럼 생각할 수 있습니다.
{
"_id": "order_123",
"user_id": "user_10",
"status": "PAID",
"shipping_address": {
"city": "Seoul",
"zip_code": "06236"
},
"items": [
{ "product_id": "p1", "name": "Keyboard", "quantity": 1, "price": 100000 },
{ "product_id": "p2", "name": "Mouse", "quantity": 2, "price": 30000 }
],
"created_at": "2025-04-05T10:00:00Z"
}
이 구조가 잘 맞는 이유는 다음과 같습니다.
- 주문 상세를 볼 때 주문 항목과 배송지 스냅샷을 함께 읽고 싶음
- 주문 생성 시 한 문서 단위 원자성이 유용함
- 주문 항목 수가 제한적이라 문서 크기 관리가 가능함
반대로 다음은 분리 후보입니다.
- 주문 상태 변경 이력 수천 건
- 별도 조회가 많은 결제 이벤트 로그
- 계속 커지는 배송 추적 이벤트
즉, MongoDB 모델링은 문서 하나로 끝낼 수 있는 경계는 최대한 활용하되, 계속 커지는 데이터는 분리하는 쪽이 자연스럽습니다.3
관련 제품 특성과 분산 운영은 MongoDB 문서와 같이 보면 좋습니다.
Firestore 모델링 예시
Firestore는 컬렉션/문서/서브컬렉션 구조를 기준으로 모델링하는 경우가 많습니다.
예를 들어 게시글과 댓글을 다음처럼 풀 수 있습니다.
posts/{postId}posts/{postId}/comments/{commentId}
또는 조회 패턴에 따라:
- 전역
posts컬렉션 - 사용자별
users/{userId}/posts/{postId}보조 경로
Firestore에서 자주 보는 설계 기준은 다음과 같습니다.
- 한 문서에 너무 많은 리스트를 누적하지 않기
- 자주 같이 읽는 작은 값은 문서에 포함하기
- 쿼리에 필요한 필드는 인덱스와 함께 설계하기
- 특정 문서 하나에 쓰기가 몰리지 않게 하기
예를 들어 게시글 문서에 다음 정도는 자연스러울 수 있습니다.
{
"title": "NoSQL modeling",
"authorId": "user_10",
"authorName": "zeikar",
"commentCount": 12,
"createdAt": "2025-04-05T10:00:00Z"
}
여기서 authorName 을 중복 저장한 이유는 조회를 단순하게 만들기 위해서입니다.
대신 이름 변경 전파 비용이 생기므로, 이런 중복은 의도적으로 선택해야 합니다.
Firestore에서는 특히 핫 문서와 인덱스 비용을 같이 봐야 합니다.
좋은 답변은 “문서를 저장한다”보다 읽기 횟수, 인덱스, write contention까지 같이 본다고 설명하는 편이 좋습니다.42
RDBMS 모델링과의 차이
| 관점 | RDBMS 모델링 | NoSQL 모델링 |
|---|---|---|
| 출발점 | 엔티티, 관계, 정규화 | 접근 패턴, 문서 경계, 파티션 키 |
| 조인 | 기본 도구 | 없거나 제한적이거나 비쌀 수 있음 |
| 중복 | 줄이는 쪽이 기본 | 읽기 최적화를 위해 더 적극 허용 |
| 무결성 | FK, UNIQUE, CHECK 등 강한 제약 | 애플리케이션/문서 단위 보장이 더 중요 |
| 핵심 질문 | 데이터를 어떻게 정규화할까 | 무엇을 한 번에 읽고 어디에 분산할까 |
좋은 면접 답변은 두 방식을 대립적으로만 말하지 않습니다.
- RDBMS는 관계와 무결성에 강함
- NoSQL은 접근 패턴과 분산 운영에 맞춘 모델이 강함
- 결국 어떤 모델이 더 좋은지가 아니라, 문제 구조에 어떤 모델이 더 맞는가가 기준입니다
즉, data-modeling.md 가 RDBMS 관점의 모델링이라면,
이 문서는 조회 경로와 문서 경계를 먼저 잡는 모델링이라고 보면 됩니다.
면접 포인트
- NoSQL 모델링의 출발점은 정규화보다 접근 패턴과 문서 경계입니다.
- 같이 읽고 같이 수정되는 작은 데이터는 embed, 독립 수명주기이거나 계속 커지는 데이터는 reference가 자연스럽습니다.
- 중복 저장은 조회 성능에 유리하지만, 동기화 비용과 정합성 관리가 따라옵니다.
- 문서 크기 증가, 배열 성장, hot partition/hot document는 운영 단계에서 자주 터지는 모델링 리스크입니다.
- MongoDB와 Firestore 예시를 설명할 때는 제품 기능보다 어떤 조회/쓰기 패턴 때문에 그런 구조를 택했는지 말하는 편이 좋습니다.