MySQL에서 MongoDB로 옮기기


처음 블로그를 만들어야지 생각했을 때부터 데이터베이스는 MongoDB를 사용하려 했습니다. 하지만 최대한 빨리 블로그를 배포하기 위해 처음에는 이미 알고있던 My SQL을 사용해 개발했습니다. 개발이 완료되고도 귀찮아서 미루고 있다가 이번에 데이터베이스를 바꾸기로 했습니다. 또한 이번에는 MongoDB 드라이버를 직접 쓰지 않고 Node.js와 MongoDB의 ODM인 Mongoose를 사용했습니다.

스키마 정의

SQL에서는 데이터를 테이블에 저장했지만 MongoDB는 다큐먼트에 저장하기 때문에 이에 맞는 스키마를 정의해줘야 합니다.

우선 포스트 컬렉션을 보면 기존에는 댓글이 작성된 포스트의 id를 가리키는 구조였습니다. 하지만 Mongo에서는 Post스키마 안에 Reply스키마의 배열을 만들어줬습니다. 추가로 지금까지는 포스트에 GET요청을 하면 데이터베이스에서 마크다운 데이터를 컴파일해서 응답해주는 방식이었는데 formattedBody필드를 추가해 글 작성시 한 번만 컴파일을 해 해당 필드에 저장하는 구조로 변경했습니다. 아래는 현재 사용하고 있는 Post의 스키마입니다.

const postSchema = new mongoose.Schema({
    title: {
        type: String,
        required: true
    },
    url: {
        type: String,
        unique: true,
        default: this.title
    },
    category: {
        type: String,
        required: true
    },
    body: {
        type: String,
        required: true
    },
    formattedBody: {
        type: String,
        required: true
    },
    tags: [String],
    writtenTime: {
        type: Date,
        default: DateTime.now().toString()
    },
    views: {
        type: Number,
        default: 0
    },
    replies: {
        type: [replySchema],
        default: []
    },
    repliesNum: {
        type: Number,
        default: 0
    }
});

Reply는 댓글이 대댓글을 무한히 가질 수 있도록 recursive하게 스키마를 정의했습니다. 스키마를 재귀적으로 정의 하려면 생성자로는 안되고 Schema.add()함수를 이용해 스키마를 정의해줘야 합니다. 아래는 현재 사용중인 Reply의 스키마를 정의한 코드입니다.

const replySchema = new mongoose.Schema();

replySchema.add({
    nickname: String,
    body: String,
    password: String,
    writtenTime: {
        type: Date,
        default: DateTime.now().toString()
    },
    reReplies: [replySchema]
});

데이터 이동

제일 귀찮은 부분이 바로 MySQL 데이터베이스 서버에 있는 데이터를 MongoDB로 이동시키는 것이었습니다. 데이터 저장 방식 자체가 달라졌기 때문에 간단한 방법으로 바로 옮기는 것은 불가능했습니다. 다행히 아직 블로그에 데이터가 많지 않은 상태여서 My SQL Workbench와 MongoDB Compass를 이용해수동으로 데이터를 변환시켜 줬습니다(...). 하지만 만약 옮겨야 하는 데이터 양이 많았다면 데이터 변환을 위한 별도의 코드를 작성했어야 됐을 것입니다.

MongoDB 서버

기존 My SQL 서버는 Heroku에서 제공하는 ClearDB라는 애드온을 사용해 쉽게 사용할 수 있었습니다. 하지만 MongoDB 애드온은 서비스가 종료되어 다른 서버를 찾아야 했습니다. 제일 먼저 시도한 것은 MongoDB에서 직접 지원하고 있는 MongoDB Atlas였습니다. 하지만 데이터 센터의 위치가 멀어서인지 아니면 싼 옵션을 사용해서인지는 몰라도 데이터를 읽는 속도가 너무 느려졌습니다. 이 속도로는 쓸 수 없다는 생각이 들어 결국 Heroku를 버리고 Digital Ocean이라는 클라우드 호스팅 서비스를 이용하기로 했습니다. 이 과정은 다음 글에서 쓰도록 하겠습니다.