• 카테고리

    질문 & 답변
  • 세부 분야

    풀스택

  • 해결 여부

    해결됨

마이그레이션 관련 질문입니다~

22.01.18 21:26 작성 조회수 689

0

안녕하세요~
 
배포 후에 DB변경을 위해 마이그레이션을 사용해야 할 것 같아서 질문드립니다~
 
공부해본 바로는
table 추가와 column 추가는 마이그레이션으로 진행하고
일대다, 다대다 관계 등은 직접 model폴더내 파일에서 변경해야 하는 걸로 알고 있는데 맞나 싶어서요~
 
그리고 개발모드에서 back 서버에서 마이그레이션을 진행하고
배포한 서버에서 실행하려면 ec2 서버에 접속하여 mysql root 접속 후에
마이그레이션을 별도로 실행(npx sequelize-cli db:migrate)해야 하는지 궁금함니다~
 
감사합니다~^^

답변 2

·

답변을 작성해보세요.

0

마이그레이션 진행 중 

어느순간부터 

이에러가 뜨는데 도무지 감을 잡기가 힘드네요.

 

models/index.js

const Sequelize = require('sequelize');

const user = require('./user');
const withdraw = require('./withdraw');
const education = require('./education');
const career = require('./career');
const job = require('./job');
const activity = require('./activity');
const award = require('./award');
const certification = require('./certification');
const language = require('./language');
const project = require('./project');
const social = require('./social');
const comtest = require('./comtest');
const teamreview = require('./teamreview');
// const comment = require('./comment');
const skill = require('./skill');
const userskill = require('./userskill');

const certificationpool = require('./certificationpool');
const company = require('./company');
const division = require('./division');
const university = require('./university');
const course = require('./course');
const coursepool = require('./coursepool');
const jobcomment = require('./jobcomment');


// 배포시 process.env.NODE_ENV를 prodution으로 변경
// develop모드에서 config를 가져옴
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
// sequelize로 node<-->mySQL 연결
const sequelize = new Sequelize(config.database, config.username, config.password, config);

db.User = user;
db.Job = job;
db.Skill = skill;
db.Userskill = userskill;
db.Education = education;
db.Career = career;
db.Activity = activity;
db.Award = award;
db.Certification = certification;
db.Withdraw = withdraw;
db.Language = language;
db.Project = project;
db.Social = social;
db.Comtest = comtest;
db.Teamreview = teamreview;
db.Certificationpool = certificationpool;
db.Division = division;
db.University = university;
db.Company = company;
db.Course = course;
db.Coursepool = coursepool;
db.Jobcomment = jobcomment;
// db.Post = post;


Object.keys(db).forEach(modelName => {
  db[modelName].init(sequelize);
});

// 관계형db 실행문(associate)
Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

 

 

create DB로 새로운db 생성형태

 

이건 DB파일형태

'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class Coursepool extends Model {
    /**
     * Helper method for defining associations.
     * This method is not a part of Sequelize lifecycle.
     * The `models/index` file will call this method automatically.
     */
    static associate(models) {
      models.Coursepool.hasOne(models.Course);
      models.Coursepool.belongsTo(models.User);
      models.Coursepool.belongsToMany(models.Skill, { through: 'CoursepoolSkill', foreignkey: "CoursepoolId" })
      models.Coursepool.belongsToMany(models.Certificationpool, { through: 'Certification_Course', foreignkey: "CoursepoolId" })
    }
  };
  Coursepool.init({
    name: DataTypes.STRING
  }, {
    period: DataTypes.FLOAT
  }, {
    runningtime: DataTypes.FLOAT
  }, {
    cost: DataTypes.FLOAT
  }, {
    teacher: DataTypes.STRING
  }, {
    category: DataTypes.STRING
  }, {
    image: DataTypes.STRING
  }, {
    viewcount: DataTypes.INTEGER
  }, {
    intro: DataTypes.STRING
  }, {
    url: DataTypes.STRING
  }, {
    process: DataTypes.INTEGER(2)
  }, {
    rate_inside: DataTypes.FLOAT
  }, {
    rate: DataTypes.FLOAT
  }, {
    sequelize,
    modelName: 'Coursepool',
    tableName: 'coursepools',
  });
  return Coursepool;
};

 

이건 마이그레이션 파일입니다.


'use strict';
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('Jobcomment', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      content: {
        type: Sequelize.TEXT,
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    })
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('Jobcomment');
  }
};

 

이런 식으로 디비구성하고 마이그레이션 작동은 되는데(테이블도 생성됩니다)

back에서 npm run dev로 진행할 경우 에러가 뜨네요 ㅠ

 

혹시 원인 어떤건지 알 수 있을까요?ㅠ

테이블이 정말 많은데요. require한 것과 db.모델 = 모델객체 한 개수가 일치하는지 확인하시고, 모델 module.exports 제대로 하셨는지 확인하세요. 무언가가 require는 되었는데 빈 객체가 require된 것 같습니다.

모델 파일에서 return 클래스 하셨는지도요.

다시 보니까 CoursePool부터가 이상하네요. init은 클래스의 static 메서드여야 합니다. 근데 바깥에 빠져나와 있네요.

감사합니다!

CoursePool은 

npx sequelize-cli model:generate --name Comment --attributes description: string,...

이 형태 명령어로 자동 테이블생성 마이그레이션으로 만든 형탠데

기존에 작성했던 class형태로 변경해야할까요?

 

나머지 부분은 확인해보겠습니다!

이런 방식으로 다 바꿨더니

const DataTypes = require('sequelize');
const { Model } = DataTypes;

//   // mySQL에 소문자 자동변경으로 users로 (sequelize와 mySQL간의 규칙)
module.exports = class Jobcomment extends Model {
  static init(sequelize) {
    return super.init({
      content: {
        type: DataTypes.TEXT,
      },
    }, {
      sequelize,
      modelName: 'Jobcomment',
      tableName: 'jobcomments', // 테이블명: 자동으로 소문자에 복수 붙음
    })
  }
  static associate(db) {
    db.Jobcomment.belongsTo(db.User);
    db.Jobcomment.belongsTo(db.Job);
  }
}

 

 

다 바꿔봤더니 새로운 에러가 뜨네요 ㅠ

반복문 내부라서 저중에 뭐가 문제인지는 안 보이네요.  forEach안에서 modelName 콘솔찍어보면 에러메시지 바로 위에 모델이 범인일겁니다.

db[modelName].init is not a function과

'No Sequelize instance passed' 에러의 연속이네요

처음 만든 테이블부터 model/index.js에서 연결하면 에러가 떠버립니다.ㅠ

아무래도 다시싹다 지우고 하면 될까싶어서 고민중이네요

 

혹시 마이그레이션시

테이블생성과 관계생성시에는 model폴더 안만지는건 아니겠죠?

 

마이그레이션시 새로생성한 테이블을 주석처리하고

기존 model들에서 새로 작성했던 관계생성 관련코드를 주석처리했고

단지 마이그레이션을 통한 column추가는 그대로 냅뒀는데

 

연결성공은 되서요 ㅠ

 

이후에 마이그레이션 실행시키니 이상하게 작동이 되네요

뭔가 꼬여서 이런걸까요?

 

마이그레이션을 한 후에 모델을 따로 추가하신게 맞나요? 모델 먼저 추가하고 마이그레이션하시면 안됩니다.

마이그레이션이 성공하는 걸 보고 모델을 수정하시는겁니다.

테이블만들때 마이그레이션 create로 모델파일이 바로생성되게 햇었습니다

정확히 기억은 안나는데 undo all와 재실행을 반복하다가 마이그레이션을 했는데

모델파일이 생성안되어서 만들었던것 같습니다 ㅠ 이럴경우 어찌할까요?

마이그레이션 파일을 처음부터 만들어볼까요?

model:generate같은거 쓰지마세요. 마이그레이션은 up down하는 파일만 자동생성하세요.

아넵 그럼일단 마이그레이션 undo 하고 ㅍ마이그레이션 파일다 삭제후에 다시금 만들어보겠습니다 ㅠ

다지우고 새로 시작했는데 처음 모델생성(Course)부터 에러나네요 ㅠ

 

말씀하신대로 generate 안쓰고 migration:create로 뼈대파일 생성후

 

마이그레이션 내용을 넣었습니다.

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('courses', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      name: {
        type: Sequelize.STRING
      },
      //실제 학습기간
      period: {
        type: Sequelize.FLOAT
      },
      //재생시간
      runningtime: {
        type: Sequelize.FLOAT
      },
      cost: {
        type: Sequelize.FLOAT
      },
      teacher: {
        type: Sequelize.STRING
      },
      category: {
        type: Sequelize.INTEGER
      },
      image: {
        type: Sequelize.STRING
      },
      viewcount: {
        type: Sequelize.INTEGER
      },
      // 소개(학습내용)
      intro: {
        type: Sequelize.STRING
      },
      url: {
        type: Sequelize.STRING
      },
      // 학습단계(초급/중급/고급/실습문제)
      process: {
        type: Sequelize.INTEGER(2)
      },
      rate_inside: {
        type: Sequelize.FLOAT
      },
      // 추노 평점
      rate: {
        type: Sequelize.FLOAT
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    })
  },

  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('courses');
  }
};

 

그담에 migration 실행시켰습니다.

여기까진 잘 작동하는데

 

model/course.js 파일 생성후

const DataTypes = require('sequelize');
const { Model } = DataTypes;

//   // mySQL에 소문자 자동변경으로 users로 (sequelize와 mySQL간의 규칙)
module.exports = class Course extends Model {
  static init(sequelize) {
    return super.init({
      name: {
        type: DataTypes.STRING,
      },
    }, {
      period: {
        type: DataTypes.FLOAT,
      },
    }, {
      runningtime: {
        type: DataTypes.FLOAT,
      },
    }, {
      cost: {
        type: DataTypes.FLOAT,
      },
    }, {
      teacher: {
        type: DataTypes.STRING,
      },
    }, {
      category: {
        type: DataTypes.INTEGER,
      },
    }, {
      image: {
        type: DataTypes.STRING,
      },
    }, {
      viewcount: {
        type: DataTypes.INTEGER,
      },
    }, {
      intro: {
        type: DataTypes.STRING,
      },
    }, {
      url: {
        type: DataTypes.STRING,
      },
    }, {
      process: {
        type: DataTypes.INTEGER(2),
      },
    }, {
      rate_inside: {
        type: DataTypes.FLOAT,
      },
    }, {
      rate: {
        type: DataTypes.FLOAT,
      },
    }, {
      sequelize,
      modelName: 'Course',
      tableName: 'courses', // 테이블명: 자동으로 소문자에 복수 붙음
    })
  }
  static associate(db) {
    // db.Course.belongsTo(db.Coursepool);
    // db.Course.belongsTo(db.User);
  }
}

models/index.js에서

const Sequelize = require('sequelize');

const user = require('./user');
const withdraw = require('./withdraw');
const education = require('./education');
const career = require('./career');
const job = require('./job');
const activity = require('./activity');
const award = require('./award');
const certification = require('./certification');
const language = require('./language');
const project = require('./project');
const social = require('./social');
const comtest = require('./comtest');
const teamreview = require('./teamreview');
// const comment = require('./comment');
const skill = require('./skill');
const userskill = require('./userskill');

const certificationpool = require('./certificationpool');
const company = require('./company');
const division = require('./division');
const university = require('./university');
const course = require('./course');
// const coursepool = require('./coursepool');
// const jobcomment = require('./jobcomment');


// 배포시 process.env.NODE_ENV를 prodution으로 변경
// develop모드에서 config를 가져옴
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
// sequelize로 node<-->mySQL 연결
const sequelize = new Sequelize(config.database, config.username, config.password, config);

db.User = user;
db.Job = job;
db.Skill = skill;
db.Userskill = userskill;
db.Education = education;
db.Career = career;
db.Activity = activity;
db.Award = award;
db.Certification = certification;
db.Withdraw = withdraw;
db.Language = language;
db.Project = project;
db.Social = social;
db.Comtest = comtest;
db.Teamreview = teamreview;
db.Certificationpool = certificationpool;
db.Division = division;
db.University = university;
db.Company = company;
db.Course = course;
// db.Coursepool = coursepool;
// db.Jobcomment = jobcomment;


Object.keys(db).forEach(modelName => {
  console.log(db[modelName]);
  db[modelName].init(sequelize);
});

// 관계형db 실행문(associate)
Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

 

다시금 넣어줬더니 에러가 나오네요 ㅠ

혹시 이 과정에서 실수한게 있을까요?

 

해결했습니다!

model/course.js 작성에 문제가 있었네요 ㅠㅠ

번거롭게해서 죄송합니다 감사합니다!

0

db:migrate을 해도 어차피 model은 수정해야 합니다. 다대다 관계, 일대다 관계 설정도 migration으로 추가 제거할 수 있습니다. 다만 마찬가지로 model 파일들은 직접 수정해주어야 합니다.

ec2 서버에서도 따로 마이그레이션을 수행하셔야 합니다. 개발서버 디비랑 다른 디비니까요.