[ 절차 ]
1)
.gitignore
작성
:/config
는 git에 올라가면 안됨 (RDS정보 유출시 과금될 수 있음)2)
/config/database.js
작성
: RDS에 접근하기 위한 인스턴스 정보가 존재3)
/modules/pool.js
작성
: 실제 RDS에 접근하기 위한 Connection 생성 및 query 하기 위한 파일4)
/models/[---.js]
: 원하는 모델에서 실제/modules/pool.js
를 가져와서 DB에 접근!
1)
.gitignore
작성
- git이 추적하지 않게 도와주는 파일
- 프로젝트 최상단에 작성 ->
/.gitignore
- https://www.toptal.com/developers/gitignore 에서 생성
- 추가로 우리가 직접 작성한
/config
추가!# Created by https://www.toptal.com/developers/gitignore/api/macos,vscode,node # Edit at https://www.toptal.com/developers/gitignore?templates=macos,vscode,node ### macOS ### # General .DS_Store .AppleDouble .LSOverride ... /* 우리 프로젝트에 노출되면 안되는 정보가 있는 폴더 */ config/
2)
/config/database.js
작성
- promise-mysql 모듈 설치
:npm install promise-mysql --save
yarn --dev add promise-mysql
- 코드 작성
const mysql = require('promise-mysql'); const dbConfig = { host : 'db-our-sopt.eerqtqedfd.ap-northeast-2.rds.amazonaws.com', port : 3306, user : 'cheeze', password : 'RDS password', database : 'posting', // schema dataString : 'date' } module.exports = mysql.createPool(dbConfig);
3)
/modules/pool.js
작성
- 3개의 메소드는 용도가 다름
- 사용하는 함수의 원리
(출처 : 경선이 블로그 - https://gngsn.tistory.com)
- queryParam
: 단순 query만 처리하기 위한 용도 (별도의 데이터가 필요 없음)const poolPromise = require('../config/database'); ... queryParam: async (query) => { return new Promise ( async (resolve, reject) => { try { /* Connection Pool을 생성! */ const pool = await poolPromise; /* Connection을 생성! */ const connection = await pool.getConnection(); try { /* 전달받은 query를 실행 */ const result = await connection.query(query); /* Connection 할당 해제 */ pool.releaseConnection(connection); /* 결과 반환 */ resolve(result); } catch (err) { pool.releaseConnection(connection); reject(err); } } catch (err) { reject(err); } }); }
- 실제 사용 코드
signin : async (id, password)=>{ const query = `SELECT * FROM user WHERE id="${id}"`; try{ const result = await pool.queryParam(query); var hashed = await encrypt(result[0].salt, password); if(result[0].password === hashed) { return true; } else { return false; } }catch(err){ throw err; } },
- queryParamArr
: 쿼리에 필요한 값들을 따로 전송받아 처리하는 방식
(사실 쿼리를 완성 시키고 queryParam으로 써도 무방함)const poolPromise = require('../config/database'); ... queryParamArr: async (query, value) => { return new Promise(async (resolve, reject) => { try { const pool = await poolPromise; const connection = await pool.getConnection(); try { /* query와 필요한 value를 함께 전달 - 차이점 */ const result = await connection.query(query, value); pool.releaseConnection(connection); resolve(result); } catch (err) { pool.releaseConnection(connection); reject(err); } } catch (err) { reject(err); } }); },
- 실제 사용 코드
signup : async (id, name, password, salt, email)=>{ const fields = 'id, name, password, salt, email'; const questions = '?, ?, ?, ?, ?'; var hashed = await encrypt(salt, password); var values = [id, name, hashed, salt, email]; const query = `INSERT INTO ${table}(${fields}) VALUES (${questions})`; try{ const result = await pool.queryParamArr(query,values); const insertId = result.insertId; return insertId; }catch(err){ if(err.errno == 1062){ console.log('signup ERROR : ', err.errno, err.code); return -1; } console.log('signup ERROR : ', err); throw err; } },
- Transaction
const poolPromise = require('../config/database'); ... Transaction: async (...args) => { return new Promise(async (resolve, reject) => { try { const pool = await poolPromise; const connection = await pool.getConnection(); try { await connection.beginTransaction(); args.forEach(async (it) => await it(connection)); await connection.commit(); pool.releaseConnection(connection); resolve(result); } catch (err) { await connection.rollback() pool.releaseConnection(connection); reject(err); } } catch (err) { reject(err); } }); }
- Transaction 관련 설명
(출처 : 경선이 블로그 - https://gngsn.tistory.com)
4) 위 실제 사용 코드로 대체