본문으로 바로가기

🎩 requirement

MySQL, sequelize에 대한 이해

https://darrengwon.tistory.com/146?category=858366

 

sequelize ORM를 이용한 MySQL 활용

ORM는 우리가 사용하는 프로그래밍 언어를 SQL문으로 변환해준다. python의 경우 장고 ORM, node.js 에는 type ORM, 시퀄라이즈(sequelize) 등이 존재한다. SQL문을 작성하지 않고 평소 하던 JS나 python으로 DB를..

darrengwon.tistory.com

HeidiDB와 mysql 모델을 이용해서 AWS RDS와 연동하기

https://darrengwon.tistory.com/240

 

ORM 말고 SQL로 AWS RDS DB와 Express 웹 서버 연결

AWS RDS RDS(Relational Database Servide) 관계형 데이터베이스(RDBMS)를 생성하고 확장할 수 있는 서비스 DB 인스턴스를 손 쉽게 생성하고 관리하며 성능 확장도 할 수 있고 여러모로 편리하다. 장애에 대비한 F..

darrengwon.tistory.com

 

 

mongoDB, mongoose에 대한 이해

https://darrengwon.tistory.com/188

 

mongoose를 통해 express와 mongoDB 연동하기

몽고가 성공적으로 설치되었음을 확인했다면 우리가 사용하고 있는 Javascript로 사용할 수 있게 mongoDB를 연결해보자. mongoDB는 다른 언어(C++)로 구성되어 있어 javascript와의 adapter를 통한 연결 작업이 필..

darrengwon.tistory.com

node.js의 기본 모듈과 express-generator가 생성하는 폴더, 파일에 대한 역할 이해

https://darrengwon.tistory.com/139?category=858366

 

★ express의 app.js 살펴보기

바닐라 node에 대한 지식이 전무했을 때 적은 express 관련 글이다. 한 번 훑고 express를 공부해보자. Express에서 간단한 server 만들기 var express = require("express"); var app = express(); PORT = 4000;..

darrengwon.tistory.com

 

express에서 router 이용

https://darrengwon.tistory.com/46?category=858366

 

★ express에서 router 사용법

습관적으로 Router는 다음을 세팅해 놓고 사용합시다. import express from "express" const router = express.Router(); export default router // app.js app.use(routes.users, userRouter); //userRouter.js i..

darrengwon.tistory.com

ES6 JS 문법과 이를 실행하기 위한 babel 설치

https://darrengwon.tistory.com/29?category=858365

 

ES6+ 문법 (1)

- Arrow Functions const sayHello = name => { return "Hello " + name; }; console.log(sayHello("Darren")); 재미있는 점은 중괄호 {}를 쓰지 않고 한 줄로 작성하거나 ()를 쓰면 return을 하지 않아도 된다는..

darrengwon.tistory.com

https://darrengwon.tistory.com/12

 

★ Node.js 기본 세팅 - babel, .babelrc, nodemon

Babel var http = require("http"); (과거) import http from ‘http’; (ES6) 대개의 개발자들이 ES6를 선호하지만 종종 컴퓨터가 못 알아듣는 경우가 많아서 syntax error가 날 경우가 많다. 특히 nod..

darrengwon.tistory.com

 

dotenv 활용

https://darrengwon.tistory.com/171

 

[dotenv] 환경 변수 .env를 활용하자

환경 변수를 저장하기 위해 dotenv를 설치한다. 주로 중요한 정보기 때문에 .gitignore에 은닉한다. 따라서, .gitignore에 .env를 추가하는 걸 잊지 말자 npm install dotenv .env 파일에는 사용할 변수나 상수를..

darrengwon.tistory.com

세션, 쿠키에 대한 이해

https://darrengwon.tistory.com/185?category=858372

 

[Cookie] Cookie

vanilla node.js로 간단한 cookie를 만들어보자. set-Cookie를 통해 cookie를 세팅할 수 있다. 우선 쿠키가 서버측에서 클라이언트에게 부여하는 것임을 알아두자. 그래서 res를 통해 쿠키를 설정해야 한다. cooki..

darrengwon.tistory.com

https://darrengwon.tistory.com/186?category=858366

 

express-session을 통해 세션 사용하기

Middleware Quick npm i pug morgan helmet cookie-parser express-session connect-flash ejs npm i @babel/node @babel/preset-env @babel/core npm i -D nodemon 미들웨어는 req와 최종 res 사이에 존재하는 중..

darrengwon.tistory.com

 


express를 활용한 웹 백엔드 설계 순서

 

🎩 설치 및 DB 세팅

🎩 DB 만들기

🎩 app.js에서 사용할 미들 웨어 설치 후 app.js 코딩

🎩 router와 view 세팅

🎩 필요한 DB 테이블 정의 및 생성

🎩 passport.js로 로그인 기능 구현 (+ federated id)

🎩 코드 배포용으로 전환하기

🎩 배포

 


 

🎩 설치 및 DB 세팅

 

npm init
npm i nodemon babel @babel/core @babel/preset-env @babel/node
npm i sequelize mysql2
npm i -g sequelize-cli
npm i express dotenv

 

sequelize init

 

MySQL을 사용하기 위한 폴더가 자동 생성 됩니다.

 

 

🎩 DB 만들기


config.json에서 DB pw, 이름(database) 등 설정

{
  "development": {
    "username": "root",
    "password": "1111",
    "database": "twitter",
    "host": "xxx.xxx.xxx.xxx",
    "dialect": "mysql",
    "operatorsAliases": false
  },

 

sequelize db:create

 

 

이후 명령창에서 mysql -h [접속할 주소] u[사용자아이디] -p[비밀번호]로 접속 가능합니다.

 

 

🎩 app.js에서 사용할 미들 웨어 설치 후 app.js 코딩

 

 

Middleware

Quick npm i pug morgan helmet cookie-parser express-session connect-flash ejs npm i @babel/node @babel/preset-env @babel/core npm i -D nodemon 미들웨어는 req와 최종 res 사이에 존재하는 중간 단계로..

darrengwon.tistory.com

npm i cookie-parser express-session morgan connect-flash helmet pug

 

다음은 app.js의 전반적인 모습입니다.

import express from "express";
import cookieParser from "cookie-parser";
import morgan from "morgan";
import path from "path";
import session from "express-session";
import flash from "connect-flash";
import dotenv from "dotenv";
import connect from "./db"; // mongoDB를 사용하면 연결해둡시다.
import webSocket from "./socket"; // socket.IO 쓸거면 연결해둡시다.
import router from "./routes/index";

// using dotenv
dotenv.config();

const app = express();

// mongoDB 연결
connect();

//view engine
app.set("views", path.join(__dirname, "views")); //views 폴더 생성해야 함
app.set("view engine", "pug");

//middleware
app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public"))); //static 정보처리. public 폴더 생성해야 함
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(
  session({
    secret: process.env.COOKIE_SECRET,
    resave: false,
    saveUninitialized: true,
    cookie: {
      httpOny: true,
      secure: false
    }
  })
);
app.use(flash());

//router
app.use("/", router);

// 404 handling
app.use((req, res, next) => {
  const err = new Error("Not Found");
  err.status = 404;
  next(err);
});

// Error handling
app.use((req, res, err) => {
  res.locals.message = err.message;
  res.locals.error = req.app.get("env") === "development" ? err : {};
  res.status(err.status || 500);
  res.render("error");
});

// listen
const server = app.listen(process.env.PORT, () => {
  return console.log(`success on : http://localhost:${process.env.PORT}`);
});

// 소켓을 쓸거면 server와 연동
webSocket(server);

 

app.js에서 입력한대로 views와 public 폴더를 생성합니다.

 

 

🎩 router와 view 세팅

 

app.js에서 app.get("/", (req, res) => "yeah") 로 계속 라우터 처리를 할수는 없습니다. 라우터 폴더를 따로 만든 후에 처리하도록 합시다. 아직 controller 단으로 구별하지는 않았습니다. 또, 렌더하는 함수에 각종 변수를 전달할수도 있음을 기억합시다

 

import express from "express";
import db from "./models";
import cookieParser from "cookie-parser";
import morgan from "morgan";
import path from "path";
import session from "express-session";
import flash from "connect-flash";
import dotenv from "dotenv";
import router from "./routes/index";

// using dotenv
dotenv.config();

//mysql 연동
db.sequelize.sync();

const app = express();

//view engine
app.set("views", path.join(__dirname, "views")); //views 폴더 생성해야 함
app.set("view engine", "pug");

//middleware
app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public"))); //public 폴더 생성해야 함
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(
  session({
    secret: process.env.COOKIE_SECRET,
    resave: false,
    saveUninitialized: true,
    cookie: {
      httpOny: true,
      secure: false
    }
  })
);
app.use(flash());

//router
app.use("/", router);

// 404 handling
app.use((req, res, next) => {
  const err = new Error("Not Found");
  err.status = 404;
  next(err);
});

// Error handling
app.use((req, res, err) => {
  res.locals.message = err.message;
  res.locals.error = req.app.get("env") === "development" ? err : {};
  res.status(err.status || 500);
  res.render("error");
});

// listen
app.listen(process.env.PORT, () => {
  return console.log(`success on : http://localhost:${process.env.PORT}`);
});

 

app.js와 연결해줍니다

import router from "./routes/index";

... 중략

//router
app.use("/", router);

 

🎩 필요한 DB 테이블 정의 및 생성

 

앞서 sequelize로 생성된 여러 폴더와 파일중 models 폴더에 테이블로 사용할 js 파일들을 생성하고, 이를 models/index.js에 연결합니다. 물론 이 index 는 app.js에 연결해야 합니다.

 

1️⃣ 테이블 작성

export default (sequelize, DataTypes) => {
  return sequelize.define(
    "user",
    {
      email: {
        type: DataTypes.STRING(40),
        allowNull: false,
        Unique: true
      },
      nick: {
        type: DataTypes.STRING(15),
        allowNull: false
      },
      password: {
        type: DataTypes.STRING(100),
        // social login시 비밀 번호가 없기 때문에 null을 허용해야 합니다
        allowNull: true
      },
      provider: {
        type: DataTypes.STRING(10),
        allowNull: false,
        defaultValue: "local"
      },
      snsId: {
        type: DataTypes.STRING(30),
        allowNull: true
      }
    },
    //timestamps는 생성일과 수정일, paranoid는 삭제일(복구용)입니다
    // charset과 collate를 다음과 같이 해야 한글이 깨지지 않습니다.
    { timestamps: true, paranoid: true, charset: 'utf8', collate: 'utf8_general_ci' }
  );
};

 

2️⃣ models/index.js 에 삽입

//index.js
import path from "path";
import Sequelize from "sequelize";
import user from "./user";
import post from "./post";
import hashtag from "./hashtag";

const env = process.env.NODE_ENV || "development"; //실제 출시할 때 production로 변경.
const config = require("../config/config.json")[env]; //config.json 객체에서 [env] 선택

const sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  config
);

const db = {}; //db라는 객체를 만들고 모듈로 활용

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

const User = user(sequelize, Sequelize);
const Post = post(sequelize, Sequelize);
const Hashtag = hashtag(sequelize, Sequelize);

// 1개의 User는 여러 개의 Post를 가지고 있는 1:N 관계
User.hasMany(Post);
Post.belongsTo(User);

// Post와 HashTag는 다대다 관계입니다.
// through에는 새로 생기는 모델(매칭 테이블)의 이름을 지정합니다.
Post.belongsToMany(Hashtag, { through: "PostHashTag" });
Hashtag.belongsToMany(Post, { through: "PostHashTag" });

// User 간 팔로우는 같은 테이블간 다대다입니다.
// as는 Join 작업시 사용하는 이름이며 foreignKey는 참고하는 외래키입니다.
// 팔로워는 팔로잉의 id를 참고하고 팔로잉은 팔로워의 id를 참고합니다.
User.belongsToMany(User, {
  through: "Follow",
  as: "Followers",
  foreignKey: "followingId"
});
User.belongsToMany(User, {
  through: "Follow",
  as: "Following",
  foreignKey: "followerId"
});

// User가 Like하는 Post는 다대다 관계입니다
User.belongsToMany(Post, { through: "Like" });
Post.belongsToMany(User, { through: "Like" });

export default db;

 

3️⃣ app.js에 연결

import db from "./models";

//mysql 연동
db.sequelize.sync();

 

연결을 완료하면 다음과 같이 config/config.json에서 등록한 DB의 이름 아래 테이블이 생성되어 있음을 확인할 수 있습니다.

 

 

 

MySQL이 아닌 mongoDB를 사용하고 싶으면 다음 게시물을 참고합시다.

https://darrengwon.tistory.com/188

 

mongoose를 통해 express와 mongoDB 연동하기

몽고가 성공적으로 설치되었음을 확인했다면 우리가 사용하고 있는 Javascript로 사용할 수 있게 mongoDB를 연결해보자. mongoDB는 다른 언어(C++)로 구성되어 있어 javascript와의 adapter를 통한 연결 작업이 필..

darrengwon.tistory.com

 

또, Sequelize와 같은 ORM이 아니라 SQL로 작성하고 싶다면(또, AWS RDS를 이용할 것이라면) 아래 포스트를 참고합시다. 저는 이 방법이 더 맞다고 생각하는 편입니다.

https://darrengwon.tistory.com/240

 

ORM 말고 SQL로 AWS RDS DB와 Express 웹 서버 연결

AWS RDS RDS(Relational Database Servide) 관계형 데이터베이스(RDBMS)를 생성하고 확장할 수 있는 서비스 DB 인스턴스를 손 쉽게 생성하고 관리하며 성능 확장도 할 수 있고 여러모로 편리하다. 장애에 대비한 F..

darrengwon.tistory.com

 

 

 

🎩 passport.js로 로그인 기능 구현 (+ federated id)

 

https://darrengwon.tistory.com/195

 

passport : (2) 회원가입과 local 로그인

passport 사용의 흐름은 대략 이렇습니다. - 설치 - import - 미들웨어 : passport.initialize(), passport.session() - passport.use() : 아이디가 db에 있는지, 비밀번호는 일치는지 등 확인 - serialize, deser..

darrengwon.tistory.com

https://darrengwon.tistory.com/211?category=858366

 

passport.js : (3) kakao 로그인

passport.js : (2) 회원가입과 local 로그인 MySQL Sequelize를 설치했다고 가정하고 진행되었습니다. 그러나 무슨 SQL을 사용하던 흐름이나 코드는 동일합니다. * passport를 import함으로써 req.login, req.logo..

darrengwon.tistory.com

 

🎩 코드 배포용으로 전환하기

 

 

Express 백엔드 배포용 전환

🎩 코드 배포용으로 전환하기 개발용으로 세팅해놓았던 미들웨어를 배포용으로 전환하기 .env에 NODE_ENV="development"를 "production"으로 변환하면 작동할 수 있게끔 만들자. - morgan 수정 if (process.env.NO..

darrengwon.tistory.com

 

🎩 배포

 

  AWS나 GCP와 같은 클라우드 플랫폼을 통해 배포하는 것을 선호한다. AWS를 기준으로 이야기하자면, EC2를 하나 만든 후 node.js 등 이용한 것들을 설치한 후 git clone을 통해 작성한 코드를 불러온 다음 dependencies를 설치하고 DB를 시작한 후 배포하면 된다.

  처음 EC2를 시작하면 아무 것도 들지 않은 깡통을 받는 것이기 때문에 node 부터 설치해서 구동에 필요한 것들을 일일히 설치해야 한다.

 

https://github.com/nodesource/distributions

 

nodesource/distributions

NodeSource Node.js Binary Distributions. Contribute to nodesource/distributions development by creating an account on GitHub.

github.com

 

* ubuntu 환경에서 설치

 

sudo apt-get update

sudo apt-get install build-essential

sudo apt-get curl

curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -  // 위 사이트에 가서 원하는 버전으로 설치합니다 최근 이 코드가 말을 안 듣는 경우가 많아졌으니 설치가 안되면 위 사이트를 참고합시다.

sudo apt-get install -y nodejs // 노드가 설치됩니다. node -v와 npm -v를 확인해보세요

 

sudo npm i -g npm // npm update

 

mysql을 사용하시면 아래 코드를 입력합시다.

sudo apt-get install -y mysql-server // 설치 직후 mysql 비밀번호 등록이 나옵니다. 소스 코드에 적은 대로 적읍시다.

mysql_secure_installation // mysql 설치 완료. mysql -h localhost -u root -p로 접속해봅시다

 

* git clone을 통해 불러온 소스코드가 있는 경로로 이동한 후

 

npm i //dependencies 설치
sudo npm i -g pm2 cross-env sequelize-cli // global하게 사용한 패키지들 설치
sequelize db:create --env production


* git에 올리지 않은 dotenv는 어떻게 하나요? => vim을 통해 직접 .env를 복붙합시다

 

npm start // 실행 완료 (혹, package.json의 script를 다른 걸로 작성했다면 그걸로 실행합니다)

 

 

* 같은 EC2에 DB 서버와 웹 서버가 동시에 있는 형국은 좋지 않다. 둘을 분리하는 것이 좋다. 서버 하나에 문제가 생겼을 때 다른 서버에 영향을 미치는 것을 막아야 하기 때문이다. RDS를 사용사던지 다른 EC2를 열어 따로 DB 서버를 운영하자.

 

darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체