본문 바로가기
Back-end/기초부터 따라하는 nest.js

시즌 2 #3. 기초부터 따라하는 Nest.js 2 : Express 배우기(2)

by hsloth 2024. 5. 15.

 

지난 시간에는 간단하게 express 서버 구축, router, query, param, body, middleware에 대해서 배웠습니다.

https://suloth.tistory.com/197

 

시즌 2 #2. 기초부터 따라하는 Nest.js 2 : Express 배우기(1)

지난 시간에는 HTTP Method에 대해서 배웠습니다.https://suloth.tistory.com/196 시즌 2 #1. 기초부터 따라하는 Nest.js 2 : HTTP 메소드이전 시간에는 간단하게 서버와 클라이언트에 대해서 다뤄봤습니다.https:/

suloth.tistory.com

 

이번 시간에는 Express와 MySQL을 연동하는 방법에 대해서 배워보려고 합니다.

 


과제 정답


다음은 지난번 과제입니다.

 

과제1

post.router.js 파일에 Router를 정의하고, /post 경로로 요청을 보내면 해당 Router를 탈 수 있도록 설정하기

 

과제2

/post 경로로 GET 요청을 하면, title과 content를 얻을 수 있도록 함수를 작성해주세요. 이때, title과 content는 query로 전달하는 방법과 param으로 전달하는 방법 두 가지를 모두 구현해주세요.

 

 

간단합니다...! 정답은 다음과 같습니다.

// routers/post.router.js
const router = require("express").Router();

router.get("/", (req, res) => {
  const title = req.query.title;
  const content = req.query.content;

  res.json({
    title: title,
    content: `query ${content}`,
  });
});

router.get("/title/:title/content/:content", (req, res) => {
  const title = req.params.title;
  const content = req.params.content;

  res.json({
    title: title,
    content: `param ${content}`,
  });
});

module.exports = router;

router.get("/title/:title/content/:content") 함수의 경우, 꼭 이런식으로 설정하지 않아도 됩니다. 저는 url을 입력하는 사람(사용자 혹은 클라이언트 개발자) 입장에서 명확하게 param의 용도를 구분하기 쉽게 하기 위해서 이런식으로 만들어 줬습니다.

router.get("/:title/:content") 이런식으로 해줘도 상관없습니다. 모든 것은 약속이니까요.

 

 

app.js에 다음 코드를 추가해줍니다.

// app.js
const postRouter = require("./routers/post.router");

app.use("/post", postRouter);

 

 

 

전체 코드

// app.js
const express = require("express");
const app = express();
const port = 3000;
const userRouter = require("./routers/user.router");
const postRouter = require("./routers/post.router");

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use("/user", userRouter);
app.use("/post", postRouter);

app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});


// post.router.js
const router = require("express").Router();

router.get("/", (req, res) => {
  const title = req.query.title;
  const content = req.query.content;

  res.json({
    title: title,
    content: `query ${content}`,
  });
});

router.get("/title/:title/content/:content", (req, res) => {
  const title = req.params.title;
  const content = req.params.content;

  res.json({
    title: title,
    content: `param ${content}`,
  });
});

module.exports = router;

 

 

이제 서버를 실행시키고

node app.js

 

해당하는 url을 브라우저에 입력하면...!

param

 

query


MySQL 테이블 설계


 

만약 데이터베이스에 대해 아무것도 모른다면... 기본적인 강의정도는 듣고와줍시다.

 

먼저, MySQL과 MySQL workbench가 설치되어있지 않다면 설치해주도록 합시다. (workbench는 꼭 필요는 없습니다)

우리는 간단하게 User과 Post 테이블을 만들어보겠습니다. 테이블을 설계하려면, MySQL Workbench 혹은 erdcloud를 이용하도록 합시다.

 

MySQL Workbench 이용

이 방법은 일단, 제가 알던 것과 많이 달려져서 패스하겠습니다.

MySQL Workbench를 이용하면 ERD 구조를 그린 것과 동일하게 SQL 쿼리문을 자동으로 작성해준다는 장점이 있다는 것만 알아두시면 될 것 같습니다.

 

erdCloud 이용

https://www.erdcloud.com 

 

ERDCloud

Draw ERD with your team members. All states are shared in real time. And it's FREE. Database modeling tool.

www.erdcloud.com

위의 사이트에서 테이블 관계를 그려줄 수 있습니다.

사용자와 게시글만 만들어 주었고, 사용자 한명이 여러 게시글을 적을 수 있으니 1:N 관계를 걸어주었습니다.

사용자가 1, 게시글이 N입니다.

 

DB 구조에 대한 부분은 일단 넘어가겠습니다. 추후에, Nest.js 프로젝트를 진행할 때 자세한 설명과 함께 진행할 예정입니다.


MySQL 설치 및 명령어


먼저, MySQL을 컴퓨터에 설치해주세요

주의사항 : username이랑 비밀번호 꼭 기억해두세요. 만약, 잊어버리셨다면 구글링으로 둘다 찾아보시기 바랍니다!

본 포스팅에서는 DB는 MySQL(혹은 MariaDB) 기준으로 진행할 예정입니다.

준비물 : 본인 컴퓨터에 MySQL 설치(구글링해서 본인 운영체제에 맞게 설치해주시면 됩니다 / macOS같은 경우는 homebrew이용해서 mysql 다운받는 방법 찾아보세요)

 

macOS의 경우

homebrew로 설치하고 나서,

brew services start mysql 명령어를 통해 시작을 해주어야 합니다.

 

mysql 접속

터미널에서 mysql 명령어를 치시면 데이터베이스에 들어갈 수 있습니다. (mac이나 리눅스의 경우 sudo를 입력해야할 수도 있습니다. ex/ sudo mysql )

보통 mysql -u 유저네임 -p 비밀번호 를 입력해서 접속합니다. (보통은 mysql -u root -p 까지 입력 후, 비밀번호 없이(비밀번호 입력 창이 나오면 그냥 엔터치면) 들어가집니다)

sudo는 함부로 쓰지마세요

그 후, show databases; 명령을 통해 database 목록을 볼 수 있습니다.

 

흰색으로 가려진 부분은 database 목록입니다.

우리 프로젝트에 사용할 database를 생성합니다.

create database db이름;

우리는 db이름을 study로 해서 지어봅시다.

create database study;

그 후, DB가 생성되었는지 show databases; 명령으로 확인합니다.

 

study 가 생성된 것을 확인할 수 있습니다.

 

그리고 해당 DB를 사용하기 위해서는 use 구문을 이용하면 됩니다.

use study;

 

 

테이블 생성하기

erdcloud에서 테이블을 그렸었죠? 그러면 그려진대로 DB에 테이블을 만들어봅시다.

 

사용자 테이블

먼저, 사용자입니다. 사용자는 외래키가 따로 없기 때문에 사용자 테이블 먼저 만들어줍시다. (외래키가 있으면, 외래키에서 참조하는 테이블이 존재해야 테이블을 만들 수 있습니다)

더보기

MySQL에 대해 잘 모른다면?

기초적인 MySQL 문법을 공부하고 와주세요.

특히, 기본 문법인 Create Table, Insert, Update, Delete, Select, Join, 정규화는 꼭 공부해와주세요.

그 밖의 키워드는 제약조건, PK, 외래키, Soft Delete, Hard Delete, MySQL 관계(1:1, 1:N, N:1, N:M)

 

-- create User Table --
CREATE TABLE User (
	id INT NOT NULL AUTO_INCREMENT,
    email VARCHAR(100) NOT NULL UNIQUE,
    password VARCHAR(100) NOT NULL,
    nickname VARCHAR(10) NOT NULL UNIQUE,
    PRIMARY KEY (id)
);

 

 

이제 desc 명령을 사용해서 테이블 구조를 볼 수 있습니다.

 

게시글 테이블

게시글 테이블은 User 테이블을 참조하는 외래키가 있기 때문에 User 테이블보다 후에 만들어주어야 합니다.

-- Create Post Table --
Create Table Post (
	id INT NOT NULL AUTO_INCREMENT,
    title VARCHAR(30) NOT NULL,
    content VARCHAR(255) NOT NULL,
    userId INT NOT NULL,
    PRIMARY KEY (id),
    FOREIGN KEY (userId) REFERENCES User(id)
);

 

 

Post 테이블도 마찬가지로 desc 명령을 써서 테이블 구조를 볼 수 있습니다.

 

 

자, 그러면 테이블 생성이 끝났습니다. 이제 MySQL과 Express를 연동해서 서버로 Http Request가 들어오면 DB에 데이터를 삽입, 수정, 삭제, 읽기 할 수 있도록 해봅시다.

 


Express - MySQL 연동


 

먼저, 터미널로 가서 mysql2 패키지를 설치해줍시다. (항상 npm install 할때, 경로 주의해주세요. package.json이 있는 경로에서 설치해주어야 됩니다)

npm i mysql2

 

 

최상위 폴더에 config.js를 만들어주고 config.js 에서 다음과 같이 설정해줍시다.

// config.js
const mysql = require("mysql2");

const connection = mysql.createConnection({
  host: "localhost",
  port: 3306,
  user: "root",
  password: "",
  database: "study",
});

module.exports = connection;

 

그리고 app.js에서는 다음과 같이 설정해줍시다.

// app.js
const express = require("express");
const app = express();
const port = 3000;
const userRouter = require("./routers/user.router");
const postRouter = require("./routers/post.router");

// 추가된 코드
const connection = require("./config");
connection.connect();

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use("/user", userRouter);
app.use("/post", postRouter);

app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});

중간에 require("./config")와 connection.connect()가 추가되었습니다.

 

 

회원가입 로직

MySQL과 express를 연동했으니, 회원가입 로직을 작성해보도록 합시다.

원래는 비밀번호 암호화도 해야하지만, 지금은 넘어가겠습니다. 모든 내용은 Nest.js 프로젝트 진행할 때 자세하게 설명할 예정입니다.

 

원래는 router, controller, service를 나눠서 프로젝트를 진행하는게 보통입니다. 일단, 여기서는 router 파일에 모든 로직을 작성하겠습니다. 자세하게 배우고 싶으시면, 추후에 express 강의를 따로 보셔도 좋을 것 같습니다.

 

user.router.js에 다음 함수를 추가해줍시다.

// user.router.js
router.post("/sign-up", (req, res, next) => {
  // 이 문법을 모른다면, 구조분해할당을 검색해서 알아보시기 바랍니다 ㅎㅎ
  const { email, password, nickname } = req.body;
  const sql = `INSERT INTO User (email, password, nickname) VALUES ('${email}', '${password}','${nickname}' )`;
  mysql.query(sql);

  res.send("Sign up Success");
});

 

그리고 postman을 켜서 다음과 같이 설정하고 요청을 보내면...!

 

위와 같이 데이터가 입력된 것을 볼 수 있습니다. (undefined는 신경 쓰지 말아주세요 ㅎㅎ...)

 

이상으로 MySQL과 Express 연동 편을 마칩니다.

 

 

전체코드

// app.js
const express = require("express");
const app = express();
const port = 3000;
const userRouter = require("./routers/user.router");
const postRouter = require("./routers/post.router");
const connection = require("./config");
connection.connect();

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use("/user", userRouter);
app.use("/post", postRouter);

app.get("/", (req, res) => {
  res.send("Hello World!");
});

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`);
});


// config.js
const mysql = require("mysql2");

const connection = mysql.createConnection({
  host: "localhost",
  port: 3306,
  user: "root",
  password: "",
  database: "study",
});

module.exports = connection;


// user.router.js
const router = require("express").Router();
const mysql = require("../config");

router.post("/sign-up", (req, res, next) => {
  const { email, password, nickname } = req.body;
  const sql = `INSERT INTO User (email, password, nickname) VALUES ('${email}', '${password}','${nickname}' )`;
  mysql.query(sql);

  res.send("Sign up Success");
});

router.get(
  "/middleware",
  (req, res, next) => {
    req.query["nickname"] = "suloth";
    next();
  },
  (req, res) => {
    res.json({
      nickname: req.query.nickname,
    });
  }
);

router.get("/", (req, res) => {
  const nickname = req.query.nickname;

  res.json({
    userInfoForQuery: {
      nickname: nickname,
    },
  });
});

router.get("/:nickname", (req, res) => {
  const nickname = req.params.nickname;

  res.json({
    userInfoForParam: {
      nickname: nickname,
    },
  });
});

router.post("/", (req, res) => {
  const body = req.body;

  res.json(body);
});

module.exports = router;

 


과제


 

자, 저희가 Post에 대해서도 테이블을 만들었죠!

그러면 여러분들은 게시글을 생성하는 API를 한 번 만들어봅시다.

 

과제1

post.router.js에 게시글을 생성하는 API를 만들어주세요!

 

과제2

post.router.js에 생성한 게시글을 GET하는 API를 만들어주세요! 이 때, post의 id값을 url로 입력 받아서 해당하는 id를 가진 post 정보만 가져올 수 있도록 해주세요.

 

힌트를 드리자면 생성 로직은 Post 메소드를 사용하면 되고, body로 title, content, userId를 받아서 Post 테이블로 Insert 문을 날리면 됩니다.

GET 로직은 Get 메소드와 SELECT 문을 사용하면 되겠죠?!