이번에 시작할 프로젝트에서는 MongoDB를 써보려고 mongoDB 공식 문서를 비롯해 폭풍 구글링 중이다.
기존에 MySql(관계형 데이터베이스)를 썼을 때는 불편한 점이 꽤나 많았다.
테이블을 다 따로 만들어야 하며 일대다(oen to many) 관계를 표현하기 위해 '다(many)'에 해당하는 테이블에서 '일(one)'에 해당하는 테이블을 참조하는 id가 필요했다. mysql workbench를 사용해서 ER diagram을 만들었었는데 익숙하지 않아서인지 가끔 데이터베이스 동기화가 안 되거나 기존에 어렵게 만들어놓은 테이블이 날아가는 일도 있었다.
애초에 sequelize를 사용해서 코드로 모델링 해놓으면 이런 일은 발생하지 않았을 테지만 실제 쇼핑몰이라고 생각하고 데이터베이스를 짰을 때 그 테이블은 꽤나 얽혀있고 칼럼이 많아서 직접 코드로 작성하기에는 가독성도 떨어지고 별로였다. 그래서 ER diagram에 그림으로 그려놓고 sequelize-auto를 사용해서 데이터베이스 모델링 코드를 만드는 방식으로 진행했었다.
지금 하고 있는 건 솔직히 테이블 구조가 간단한 것도 많다. 그래서 mongoDb가 더 편하게 느껴질 수도 있다. 하지만 분명한 건 sub document는 편하다는 것이다. sub document란 document(데이터베이스에서 row를 의미) 안에 document를 넣을 수 있다는 것이다. 이게 의미하는 바는 하나의 컬렉션에서 중첩된 구조를 가질 수 있다는 것이다.
mongoDB는 자료형으로 배열도 지원하기 때문에 A 컬렉션(table 개념)에서 B 컬렉션의 ObjectId들을 담은 배열을 row로 사용할 수 있다. 예를 들면 떡볶이 메뉴 데이터베이스에 추가 가능한 토핑 데이터베이스들이 배열로 들어갈 수 있다.
관계형 데이터베이스에서는 Foreign key로 구현이 됐을 것이다. 이게 mongoDB를 상당히 직관적이게 만들어준다.
그렇다고 해서 기존 방식을 못 쓰는 것도 아니다. 배열이 너무 커질 염려가 있거나 배열이 너무 자주 변경되는 경우 기존처럼 Foreign key 방식으로 ObjectId를 설정하는 것도 가능하다. 관계를 나타내주는 키가 어느 방향에 들어있는 지에 따라 이렇게 달라지는 걸 보면 디자인패턴이 중요하게 느껴진다.
mongoDB에서 주의할 점은 하나의 document의 최대 크기가 16MB라는 것이다.
https://docs.mongodb.com/manual/reference/limits/#bson-documents
ObjectId 배열을 사용한다면 16MB는 큰 수이므로 크게 걱정할 필요는 없다. 십만개는 족히 들어갈 듯 하다.
단점
꽤나 큰 단점이 있었다. 프로젝트를 mongoDB로 만들던 중 깨달았다.
mongoDB는 CASCADE가 불가능하다. 자동으로 이루어지지 않으니 수동으로 일일이 찾아서 바꿔줘야 된다.
열혈 유저가 포스트도 많이 올리고 댓글도 많이 썼다 가정하자.
이 유저가 프로필 사진 혹은 닉네임을 변경한다면???
그 사람이 쓴 포스트랑 댓글 전부에서 변경 사항이 적용되어야 할 것이다. 하지만 mongoDB에는 CASCADE가 없다.
결국 ObjectId를 활용하자고 타협할 것이고 join이 필수적이다. 하지만 mongoDB에서 join은 관계형 데이터베이스에서처럼 데이터베이스 상에서 이루어지는 게 아니라 자바스크립트로 이루어지기 때문에 느리다. NoSql의 장점을 잃는다.
유저가 탈퇴한다면??
보안상 그 사람의 자취가 남은 데이터는 모두 삭제해야 한다. 여기저기 document에 탈퇴한 유저의 objectId가 들어있다. 이걸 어떻게 다 지워!!!!!
mongoose의 pre 함수를 통해 특정 쿼리를 수행하기 전에 관련 데이터들을 삭제해 줄 수 있다. 이 부분에 대해서 코드를 짜야 한다는 건 번거로운 일이다.
마무리
Nosql이 나온 이후에 RDS가 더 많이 쓰이는 이유는 분명 있는거 같다. Nosql은 아무래도 로그 수집이나 빅데이터를 위한 데이터 수집처럼 자주 변경되지 않는 정보들만 저장하는 게 정신 건강에 이로울 거 같다.
Nosql을 프로젝트에 쓰고자 한다면 이 점을 고려할 필요가 있겠다.