[TIL_2023.11.10] Sequelize 연결, findAll is not a function 오류

김효진·2023년 11월 10일
0
post-custom-banner

프로젝트를 하기 위해 프로젝트 서버에 Sequelize를 연결했는데 계속 findAll is not a function, Cannot read properties of undefined (reading 'findAll') 이런 오류가 났다.

검색해보니 문법을 잘못 사용하면 이런 오류가 날 수 있다고 해서 Sequelize 공식 문서도 찾아보면서 문법이 잘못된 건 없는지 계속 체크했는데 별 문제가 없었다.

기본으로 생성해주는 models / index.js 코드가 문제가 있는 듯 했다.
알아보니 대부분의 경우 기본 셋팅된 models / index.js 파일을 사용할 경우 에러가 많아 수정을 해서 사용하는 듯 하다.

1번 방법

나같은 경우 도움을 받아 아래와 같이 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();

이런식으로 불러와 사용했더니 잘 작동하였다. 작동 원리는 아직 잘 이해가 안되서 조금 더 알아보고 또 포스팅 해야겠다.

2번 방법

추가적으로 더 검색해서 알아보니까

//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

profile
더 많은 사람들이 더 좋은 정보와 서비스를 누릴 수 있게!!
post-custom-banner

0개의 댓글