프로젝트를 하기 위해 프로젝트 서버에 Sequelize를 연결했는데 계속 findAll is not a function, Cannot read properties of undefined (reading 'findAll') 이런 오류가 났다.
검색해보니 문법을 잘못 사용하면 이런 오류가 날 수 있다고 해서 Sequelize 공식 문서도 찾아보면서 문법이 잘못된 건 없는지 계속 체크했는데 별 문제가 없었다.
기본으로 생성해주는 models / index.js 코드가 문제가 있는 듯 했다.
알아보니 대부분의 경우 기본 셋팅된 models / index.js 파일을 사용할 경우 에러가 많아 수정을 해서 사용하는 듯 하다.
나같은 경우 도움을 받아 아래와 같이 index.js 파일을 사용하고
// models / index.js
'use strict';
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const process = require('process');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
}
fs.readdirSync(__dirname)
.filter(
(file) =>
file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js'
)
.forEach((file) => {
console.log('model file:', file);
// eslint-disable-next-line global-require,import/no-dynamic-require
const model = require(path.join(__dirname, file))(
sequelize,
Sequelize.DataTypes
);
db[model.name] = model; // db.User(키) = User(모델 객체)
});
Object.keys(db).forEach((modelName) => {
if (db[modelName].associate) {
db[modelName].associate(db);
}
});
db.sequelize = sequelize;
db.Sequelize = Sequelize;
module.exports = db;
// routes / users.js
const express = require('express');
const db = require('../models');
const User = db.User;
const { Op } = require('sequelize');
const router = express.Router();
이런식으로 불러와 사용했더니 잘 작동하였다. 작동 원리는 아직 잘 이해가 안되서 조금 더 알아보고 또 포스팅 해야겠다.
추가적으로 더 검색해서 알아보니까
//models/index.js
const path = require('path');
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require(path.join(__dirname, '..', 'config', 'config.json'))[
env
];
const db = {};
const sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.User = require('./user')(sequelize, Sequelize); // 생성한 User 모델 index에 연결
module.exports = db;
// routes / users.js
const express = require('express');
const router = express.Router();
const { Op } = require('sequelize');
const { User } = require('../models/index');
router.post('/users', async (req, res) => {
const { email, nickname, password, confirmPassword } = req.body;
if (password !== confirmPassword) {
res.status(400).send({
errorMessage: '패스워드가 패스워드 확인란과 다릅니다.',
});
return;
}
// email or nickname이 동일한게 이미 있는지 확인하기 위해 가져온다.
const existsUsers = await User.findAll({
where: {
[Op.or]: [{ email }, { nickname }],
},
});
if (existsUsers.length) {
res.status(400).send({
errorMessage: '이메일 또는 닉네임이 이미 사용중입니다.',
});
return;
}
await User.create({ email, nickname, password });
res.status(201).send({});
});
module.exports = router;
// app.js
const sequelize = require('./models').sequelize;
// db연결
sequelize
.sync({ force: false })
.then(() => {
console.log('데이터베이스 연결 성공');
})
.catch((err) => {
console.error(err);
});
이렇게 셋팅하는것도 잘 작동했다. 포인트는 models/index.js 에서
db.User = require('./user')(sequelize, Sequelize); // 생성한 User 모델 index에 연결
생성한 모델 파일들을 추가해 다른 js 파일에서 models/index.js 를 require 할 때 인식할 수 있게 해주는 것이다.
결국 위에 1번 방법도 이와 비슷한 원리었다.
참고한 블로그 링크
https://honey-kikiki.tistory.com/m/45