다음 내용은 인프런에서 공부한 내용을 복습하는 차원에서 기록한 것입니다.
출처 : https://www.inflearn.com/course/%EB%85%B8%EB%93%9C-js-%EA%B5%90%EA%B3%BC%EC%84%9C


컬럼명 옆의 것들은 컬럼에 대한 옵션들
INT: 정수 자료형(FLOAT, DOUBLE은 실수)
VARCHAR: 문자열 자료형, 가변 길이(CHAR은 고정 길이)
TEXT: 긴 문자열은 TEXT로 별도 저장
DATETIME: 날짜 자료형 저장
TINYINT: -128에서 127까지 저장하지만 여기서는 1 또는 0만 저장해 불 값 표현
NOT NULL: 빈 값은 받지 않는다는 뜻(NULL은 빈 값 허용)
AUTO_INCREMENT: 숫자 자료형인 경우 다음 로우가 저장될 때 자동으로 1 증가
UNSIGNED: 0과 양수만 허용
ZEROFILL: 숫자의 자리 수가 고정된 경우 빈 자리에 0을 넣음
DEFAULT now(): 날짜 컬럼의 기본값을 현재 시간으로
외래키를 두어 두 테이블이 관계가 있다는 것을 표시
FOREIGN KEY (컬럼명) REFERENCES 데이터베이스.테이블명 (컬럼)
FOREIGN KEY (commenter) REFERENCES nodejs.users (id)
댓글 테이블에는 commenter 컬럼이 생기고 사용자 테이블의 id값이 저장됨
ON DELETE CASCADE, ON UPDATE CASCADE
사용자 테이블의 로우가 지워지고 수정될 때 댓글 테이블의 연관된 로우들도 같이 지워지고 수정됨
데이터를 일치시키기 위해 사용하는 옵션(CASCADE 대신 SET NULL과 NO ACTION도 있음)









const Sequelize = require('sequelize');
const User = require('./user');
const Comment = require('./comment');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.User = User;
db.Comment = Comment;
User.initiate(sequelize);
Comment.initiate(sequelize);
User.associate(db);
Comment.associate(db);
module.exports = db;
const express = require('express');
const path = require('path');
const morgan = require('morgan');
const nunjucks = require('nunjucks');
const { sequelize } = require('./models');
const indexRouter = require('./routes');
const usersRouter = require('./routes/users');
const commentsRouter = require('./routes/comments');
const app = express();
app.set('port', process.env.PORT || 3001);
app.set('view engine', 'html');
nunjucks.configure('views', {
express: app,
watch: true,
});
//데이터베이스 연결
sequelize.sync({ force: false })
.then(() => {
console.log('데이터베이스 연결 성공');
})
.catch((err) => {
console.error(err);
});
app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use('/', indexRouter);
app.use('/users', usersRouter);
app.use('/comments', commentsRouter);
app.use((req, res, next) => {
const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
error.status = 404;
next(error);
});
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
res.status(err.status || 500);
res.render('error');
});
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기 중');
});
const Sequelize = require('sequelize');
class User extends Sequelize.Model {
static initiate(sequelize) {
User.init({
name: {
type: Sequelize.STRING(20),
allowNull: false, //Not NULL
unique: true,
},
age: {
type: Sequelize.INTEGER.UNSIGNED,
allowNull: false,
},
married: {
type: Sequelize.BOOLEAN, //true false
allowNull: false,
},
comment: {
type: Sequelize.TEXT,
allowNull: true,
},
created_at: {
type: Sequelize.DATE, //DATETIME, MySQL DATE => Sequelize DateOnly
allowNull: false,
defaultValue: Sequelize.NOW,
},
}, {
sequelize,
timestamps: false, //createAt, updateAt 활성화 유무
underscored: false, //자동으로 만들어지는 객체명에 _ 넣을지 유무
modelName: 'User',
tableName: 'users',
paranoid: false,
charset: 'utf8',
collate: 'utf8_general_ci',
});
}
static associate(db) {
db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id' });
}
};
module.exports = User;
const Sequelize = require('sequelize');
class Comment extends Sequelize.Model {
static initiate(sequelize) {
Comment.init({
comment: {
type: Sequelize.STRING(100),
allowNull: false,
},
created_at: {
type: Sequelize.DATE,
allowNull: true,
defaultValue: Sequelize.NOW,
},
}, {
sequelize,
timestamps: false,
modelName: 'Comment',
tableName: 'comments',
paranoid: false,
charset: 'utf8mb4',
collate: 'utf8mb4_general_ci',
});
}
static associate(db) {
db.Comment.belongsTo(db.User, { foreignKey: 'commenter', targetKey: 'id' });
}
};
module.exports = Comment;
const Sequelize = require('sequelize');
const User = require('./user');
const Comment = require('./comment');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.User = User;
db.Comment = Comment;
User.initiate(sequelize);
Comment.initiate(sequelize);
User.associate(db);
Comment.associate(db);
module.exports = db;

static associate(db) {
// User는 다수의 Comment를 가지는데
// 외부키는 Comment의 commenter라는 컬럼을 사용하고 User의 id 컬럼을 참조한다는 의미
// foreignKey는 User나 Comment나 같은 것을 사용
// 하지만 commenter라는 컬럼은 Comment쪽에 생성됨 (belongsTo 쪽에 컬럼이 추가됨)
db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id' });
}
static associate(db) {
// Comment는 User에 속하는데
// 외부키로 commenter를 사용하고 User의 id 컬럼을 참조한다는 의미
// foreignKey는 User나 Comment나 같은 것을 사용
// 하지만 commenter라는 컬럼은 Comment쪽에 생성됨 (belongsTo 쪽에 컬럼이 추가됨)
db.Comment.belongsTo(db.User, { foreignKey: 'commenter', targetKey: 'id' });
}
User.hashOne(db.Info { foreignKey: "UserId", sourceKey: "id" });
Info.belongsTo(db.User { foreignKey: "UserId", targetKey: "id" });
db.Post.belongsToMany(db.Hashtag, { through: "PostHashTag" });
db.Hashtag.belongsToMany(db.Post, { through: "PostHashTag" });
// Id가 1, 3, 5인 user를 삭제하라는 의미
User.destroy({
where: { id: { [Op.in]: [1, 3, 5] } }
});
// Id가 5가 아닌 user들을 전부 삭제하라는 의미
User.destroy({
where: { id: { [Op.ne]: 5 } }
});
const user = await User.findOne({...});
console.log(user.nick); // 사용자 닉네임
const user = await User.findOne({
include: [{
model: Comment,
}]
});
console.log(user.Comments); // 사용자 댓글
db.sequelize.models.PostHashtag
const user = await User.findOne({ ... });
const comments = await user.getComments();
console.log(comments); // 사용자 댓글 출력
// 관계를 설정할 때 as로 등록
db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id', as: 'Answers' });
// 쿼리할 때는
const user = await User.findOne({ ... });
const comments = await user.getAnswers();
console.log(comments);
어떤 User의 댓글을 가져오는데, 전부 다 가져오지 말고 id가 1인 댓글들의 id 컬럼을 가져오라는 의미
만약 id가 1인 User의 댓글들을 가져오고 싶을 때는 include 밖에서 where을 사용해 가져와야 함
const user = await User.findOne({
include: [{
model: Comment,
attributes: ['id'],
where: {
id: 1,
},
}]
});
// 또는
const comments = await user.getComments({
where: {
id: 1,
},
attributes: ['id'],
});
const user = await User.findOne({ ... });
const comment = await Comment.create( ... );
await user.addComment(comment);
// 또는
await user.addComment(comment.id);
const user = await User.findOne({});
const comment1 = await Comment.create();
const comment2 = await Comment.create();
await user.addComment([comment1, comment2]);
const [result, metadata] = await sequelize.query('SELECT * from comments');
console.log(result);
