본문으로 바로가기

MongoDB - 어플리케이션 설계

category software engineering/backend 2023. 6. 25. 15:25
728x90

어플리케이션 설계

Trade-Off

RDBMS에 익숙한 사람은 정규화에 익숙하다. 정규화는 콜렉션 간 참조를 갖고 여러 콜렉션으로 나눠 참조를 통해 접근한다. 하지만 몽고디비는 조인을 지원하지 않아서 여러 콜렉션에서 문서를 모으려면 쿼리를 여러 번 수행해야 한다. 일반적으로 정규화는 쓰기를 빠르게 만들고 비정규화는 '여러 문서가 참조를 통하지 않고 여러 문서를 갱신' 해야 하기 때문에 여러번 써야하지만 읽기를 빠르게 만든다.

데이터 표현 예제

# 관계형 사고 - 전부 참조형식 (실제 stuentId, classes 를 얻는 쿼리를 3번 해야함)
> db.studentClasses.findOne({"studentId": id})
{
    "_id": ObjectId("..."),
    "studentId": ObjectId("..."),
    "classes": [
    	ObjectId("..."),
        ObjectId("...")
    ]
}

# 몽고형 사고 - 과목과 학생이 자주 바뀌지 않는다면 참조를 내장
{
    "_id": ObjectId("..."),
    "name": "John Doe",
    "classes": [
        ObjectId("..."),
        ObjectId("...")
    ]
}

# 읽기 최적화 - 완전 비정규화
{
    "_id": ObjectId("..."),
    "name": "John Doe",
    "classes": [{
        "class": "Trigonometry",
        "credits": 3,
        "room": "204"
    }, {
        "class": "...",
        ...
	}]
}

# 혼합형 - 자주 사용하는 정보만 내장
{
    "_id": ObjectId("..."),
    "name": "John Doe",
    "classes": [{
        "_id": ObjectId("..."),
        "class": "Trigonometry",
    }, {
        "_id": ObjectId("..."),
        "class": "...",
	}]
}

NoSQL은 무조건 내장형만 사용한다고 생각 했었는데, 적당한 정규화와 비정규화의 혼합에 대한 아이디어가 마음에 들었습니다. 하지만 읽혀지는 빈도에 비해 정보가 얼마나 자주 변경되는가를 생각하고 정기적으로 갱신되어야 한다면 '정규화' 하는것이 추천되었습니다. 내장된 문서를 사용하기로 결정하고 문서들을 갱신해야 한다면, 수행하는 갱신이 성공적으로 모든 문서로 전파되도록 보장하기 위해 (서버가 갑자기 꺼지면 문제가 되니까...) cron 작업을 설정해야 함도 제안되었습니다.

내장 방식이 좋은 경우 참조 방식이 좋은 경우
작은 하위문서 큰 하위 문서
정기적으로 변하지 않는 데이터 자주 변하는 데이터
결과적으로 일관성이 허용될 때 즉각적인 일관성이 필요 할 때
증가량이 적은 문서 증가량이 많은 문서
조회하려는 두 번째 쿼리를 수행하기 위해 자주 필요한 데이터 결과에서 자주 제외되는 데이터
빠른 읽기 빠른 쓰기

언제 내장 방식을 사용할지, 참조 방식을 사용할지는 위에 정리된 표를 통해 느낌을 잡으시면 될거 같습니다. 카디널리티(콜렉션이 다른 콜렉션에 대한 참조를 얼마나 많이 갖는가)로 판단하기 위해선 '다수'를 하위 범주 '많음'과 '적음'으로 나누면 결정에 도움이 된다. 예를 들어 저자가 몇 개의 게시글을 작성하면 (one-to-few), 많은 댓글이 달려 있는 블로그 게시물과 댓글 사이에는 (one-to-many) 관계인데 일반적으로 하위 범주가 적다면 내장, 많다면 참조하는게 바람직하다.

몽고 디비의 사용이 부적합한 경우

  • 트랜잭션을 지원하지 않기에 트랜잭션을 요구하는 시스템
  • 여러 차원에 걸쳐 다양한 유형의 데이터를 조인하려는 경우
  • SQLAlchemy, 워드프레스를 사용하는 경우

'software engineering > backend' 카테고리의 다른 글

MongoDB - 인덱싱  (0) 2023.06.24
MongoDB - 문서의 갱신/쿼리  (0) 2023.06.24
MongoDB - 집계  (0) 2023.06.18
Locking - Optimistic concurrency control (OCC)  (0) 2022.08.31
Rest? gRPC? GraphQL?  (0) 2022.08.31