Home 로그인 페이지 만들기 - 04
Post
X

로그인 페이지 만들기 - 04

mysql2/promise 모듈을 활용해 로그인 페이지를 완성해보자.


mysql2/promise 모듈 (+ promise)

이전 포스트에서 정리한 mysql2 모듈의 createPool 메서드를 활용해 AWS RDS와 연동해보겠습니다. (AWS RDS는 이전에 만들어둔 것 활용하겠습니다.)

  • 설치
    1
    
    npm i mysql2
    

Pool 생성

Model 폴더에 새로운 model_user.js 파일을 생성합니다.

mysql2/promise 패키지를 import한 후 createPool 메서드를 사용해 Pool을 생성합니다.

getConnection 메서드로 Connection을 가져와 쿼리 작업을 한 후 반환합니다.

1
2
3
4
5
6
7
8
9
10
11
12
import mysql from "mysql2/promise";

const pool = await mysql.createPool({
  host: "db-instance.czm29ewy6sqk.ap-northeast-2.rds.amazonaws.com", //실제로 연결할 데이터베이스의 위치
  user: "psmin",
  password: "java1994",
  database: "user", //데이터베이스 이름
  port: 3306,
  connectionLimit: 30,
});

const conn = await pool.getConnection(async (conn) => conn);

로그인 기능 구현

Controller로 부터 사용자의 id를 받아 연동된 AWS RDS에 저장된 사용자 정보를 조회합니다.

해당 데이터가 존재하면 객체로 반환하고 존재하지 않으면 에러를 반환합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
... // Pool 생성

class UserStorage {
  static async getUserInfo(id) {
    try {
      const sql = "SELECT id, password FROM users WHERE id = ?";

      await conn.beginTransaction();
      const [rows] = await conn.query(sql, [id]);
      await conn.commit();

      return rows[0];
    } catch (err) {
      await conn.rollback();

      throw err;
    } finally {
      conn.release();
    }
  }
}

export default UserStorage;

회원가입 기능 구현

Controller로 부터 사용자가 보낸 id, password, name을 객체로 받아 연동된 AWS RDS에 사용자 정보를 추가합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
... // Pool 생성

class UserStorage {
  static async getUserInfo(id) {
    ... // 로그인 기능
  }

  static async createUser(userInfo) {
    try {
      const sql = "INSERT INTO users(id, password, nickname) VALUES(?, ?, ?);";

      await conn.beginTransaction();
      await conn.query(sql, [userInfo.id, userInfo.password, userInfo.name]);
      await conn.commit();

      return { success: true }; // 쿼리 성공 시 반환
    } catch (err) {
      await conn.rollback();

      throw err;
    } finally {
      conn.release();
    }
  }
}

export default UserStorage;

Controller 수정

사용자가 로그인 요청 시 아이디가 틀렸을 경우 Error가 발생하므로 try-catch문 으로 처리해줍니다.

사용자가 회원가입 요청 시 req.body (id, password, name 이 담긴 객체)를 인수로 넘깁니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import UserStorage from "../models/model_user.js";

const output = {
  login: (req, res) => {
    res.render("user/login");
  },

  register: async (req, res) => {
    res.render("user/register");
  },
};

const process = {
  login: async (req, res) => {
    var response = {};

    try {
      const user = await UserStorage.getUserInfo(req.body.id);

      if (user) {
        if (password === req.body.password) {
          return (response = { success: true });
        } else {
          return (response = { success: false, msg: "비밀번호가 틀렸습니다." });
        }
      }

      response = { success: false, msg: "존재하지 않는 아이디입니다." };
    } catch (err) {
      response = {
        success: false,
        msg: "로그인을 할 수 없습니다.\n잠시 후 다시 시도해주세요.",
      };
    } finally {
      res.json(response);
    }
  },

  register: async (req, res) => {
    try {
      const user = await UserStorage.getUserInfo(req.body.id);

      let response = {};

      if (user) {
        return (response = { success: false, msg: "아이디가 존재합니다." });
      }

      response = await UserStorage.createUser(req.body);

      res.json(response);
    } catch (err) {
      // 간단한 에러 처리문 작성
      const response = {
        success: false,
        msg: "회원가입을 할 수 없습니다.\n 잠시 후 다시 시도해주세요.",
      };
    } finally {
      res.json(response);
    }
  },
};

export default { output, process };

Pool & Connection 생성 모둘화

Model_user.js에서 createPool, getConnection 부분을 config 폴더에 따로 담아두고 필요할 때 꺼내서 사용해 코드의 가독성을 높혀보겠습니다.

config폴더에 db_pool.js 파일에 Pool을 생성하고 Connection을 받아 export합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import mysql from "mysql2/promise";

const pool = await mysql.createPool({
  host: process.env.DB_HOST, //실제로 연결할 데이터베이스의 위치
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_DATABASE, //데이터베이스 이름
  port: process.env.DB_PORT,
  connectionLimit: process.env.DB_CONN_LIMIT,
});

const conn = await pool.getConnection(async (conn) => conn);

export default conn;

model 파일에 db_pool.js 파일을 import하고 필요할 때 사용하고 쿼리 작업 완료 후 반환합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import conn from "../config/db_pool.js";

class UserStorage {
  static async getUserInfo(id) {
    try {
      const sql = "SELECT id, password FROM users WHERE id = ?";

      await conn.beginTransaction(); // 커넥션을 받아 트랜잭션 시작
      const [rows] = await conn.query(sql, [id]);
      await conn.commit(); // 쿼리문 완료시 커밋

      return rows[0];
    } catch (err) {
      await conn.rollback(); // 에러 발생 시 롤백

      throw err;
    } finally {
      conn.release(); // 쿼리 작업 완료 후 반환
    }
  }

  static async createUser(userInfo) {
    ...
  }
}

export default UserStorage;

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.