Building a Server and Database with Express.js and Sequelize

This is an article about the basic procedures and settings for using Sequelize in Express.js, connecting to a database using Sequelize, creating Sequelize configuration files, and defining and connecting models.

Installing Sequelize

To use Sequelize in an Express application, first install the necessary packages.

Install Sequelize

npm install --save sequelize mysql2

Creating and Verifying Sequelize Instance

This is a basic example of Sequelize configuration.

You can write it in the app.js file.

It checks the database connection. If the connection is successful, it displays a console message, and if it fails, it shows an error.

Note: Please avoid using hardcoding. It can cause security issues.

Instead of DB_NAME, use process.env.DB_NAME, instead of 'test' use process.env.USER_ID, and instead of '1234', use process.env.USER_PASSWORD, utilizing the .env file.

Sequelize Setting

const Sequelize = require('sequelize');
const sequelize = new Sequelize('DB_NAME', 'test', '1234', {
    host: '127.0.0.1',
    dialect: 'mysql',
});

sequelize
    .authenticate()
    .then(() => {
        console.log('데이터베이스 연결에 성공했습니다.');
    })
    .catch((err) => {
        console.error('데이터베이스 연결에 실패했습니다:', err);
    });

Writing Sequelize Configuration File

Write the config/config.js file to manage database settings for various environments (development, test, production).

Below is an example. Please use your created database name, personal user ID, and personal password.

You can write configurations for three environments: development, test, and production. According to the Git Flow Logic, you can switch to the desired environment's database by simply changing the settings in models/index.js to match each environment.

As a note of caution, please avoid using hardcoding as mentioned above.

config.js

module.exports = {
  development: {
    username: 'test',
    password: '1234',
    database: 'test',
    host: '127.0.0.1',
    dialect: 'mysql',
  },
  test: {
    // 테스트 환경 설정
  },
  production: {
    // 프로덕션 환경 설정
  },
};

Writing Models and Connection File (models/index.js)

The models/index.js file initializes and manages Sequelize models. This file plays a central role in importing all models, connecting to the database, and setting up relationships.

This is the current code in use.

You can check if it's a development environment using process.env.NODE_ENV.

Database connection settings are imported from config/config.js.

For models, fs.readdirSync is used to dynamically read model files.

Relationships between models can be set in each model file. (1:1, 1:N, N:M)

model/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.js')[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) => {
    return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js' && file.indexOf('.test.js') === -1;
  })
  .forEach((file) => {
    const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
    db[model.name] = model;
  });

Object.keys(db).forEach((modelName) => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

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

module.exports = db;

Real Example for Development

For the config.js file, please enhance security by using dotenv.

Hard coding has been done for the purpose of providing an example.

models/index.jsis as per the example provided.

config/config.js

require('dotenv').config();

module.exports = {
  development: {
    username: 'test',
    password: '1234',
    database: 'test',
    host: '127.0.0.1',
    dialect: 'mysql',
  },
  test: {
    username: 'root',
    password: null,
    database: 'database_test',
    host: '127.0.0.1',
    dialect: 'mysql',
  },
  production: {
    username: 'root',
    password: null,
    database: 'database_production',
    host: '127.0.0.1',
    dialect: 'mysql',
  },
};

Enter in the order of new Sequelize(database name, user ID, user password). Alternatively, please use process.env for encryption.

const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD)

app.js

const express = require('express');
const cors = require('cors');
const app = express();
const userRoutes = require('./routes/user');
const postRoutes = require('./routes/post');
require('dotenv').config();

const PORT = 3345;
const Sequelize = require('sequelize');

app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
   host: '127.0.0.1',
   dialect: 'mysql',
 });

sequelize
  .authenticate()
  .then(() => {
    console.log('데이터베이스 연결에 성공했습니다.');
  })
  .catch((err) => {
    console.error('데이터베이스 연결에 실패했습니다:', err);
  });

app.get('/', (req, res) => {
  res.send('Food-bnb-server On!');
});

app.use(
  cors({
    origin: 'http://localhost:3000', // 허용하고 싶은 도메인
    credentials: true, // 응답 헤더에 Access-Control-Allow-Credentials 추가
  }),
);

app.use('/user', userRoutes);
app.use('/post', postRoutes);

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('문제가 생겼네요.');
});

app.listen(PORT, () => {
  console.log(`서버 포트: ${PORT}`);
});