-
Node.js 프로젝트 리팩토링(1)BackEnd/Node.js 2022. 2. 27. 00:02
------------------------------------------------------------ 사담 ----------------------------------------------------------------
최근에 Node.js 스터디를 했고, 인턴십 면접도 보면서 기존에 했었던 프로젝트를 리팩토링 해야겠다고 생각했다. 인턴십 사담을 좀 해보자면, 노드 쓰는곳 2군데 스프링 한군데 넣었고 노드는,, 서류는 다 붙었는데 면접 탈했다 ^_^
쨌든 기존 프로젝트를 좀 더 다듬어서 다음학기에도 또 지원해보고자 ... 리팩토링 과정을 좀 블로그에 기록해두고자 한다.
-----------------------------------------------------------------------------------------------------------------------------------
1. 프로젝트 구조 : MVC 패턴을 적용해보자
$ npm install express-generator -g
위 명령어를 vscode 터미널에 치면 express의 기본적인 구조를 자동으로 형성해준다. 그 뒤에 npm install 명령어로 필요한 모듈 설치를 해주면 된다.
그럼 위와 같은 구조가 만들어지는데, 여기서 아래처럼 바꿨다.
내 코드의 기존 문제점이라고 해야하나? 노드의 모듈화를 잘 적용하지 못한 것 같다. 처음 노드를 공부할 때에는 스치듯 지나간 다른 사람들의 코드를 보면서 왜 찾아보기 복잡하게 저렇게 해놨지? 라는 생각을 했었다. 처음엔 조금 이해하기 어려웠지만 모듈화 시키는 쪽이 좀 더 개발하기 편리할 것 같다.
✅ MVC 패턴
- Model : 데이터와 비즈니스 로직 관리
- 어플리케이션의 정보, 데이터를 나타냄
- 뷰나 컨트롤러에 대한 정보를 몰라야 함
- View : 클라이언트와 상호작용이 일어나는 부분, 레이아웃과 화면 처리
- 변경이 일어날 시 모델에게 변경 내용 전달
- Controller : 유저의 요청을 처리해서 응답하는 부분. 모델과 뷰 부분으로 라우팅
- 모델과 뷰 사이를 이어주는 브릿지 역할
- 모델이나 뷰의 변경을 모니터링, 변경 사항을 각 구성요소에 통지해야 함
2. Modules
- db와 연결하는 부분, 상태 코드, 메시지 등을 담아두는 폴더이다.
- message, status는 기존 프로젝트에서도 있었는데 달라진 부분은 connectionPool, mysql부분이다.
- mysql.js (db정보는 각자 다 다를테니 맞춰서 작성)
📌 database와의 연결을 생성하는 모듈
const mysql = require('mysql2/promise'); const database = { host: 'host 정보' user: 'username 정보', database: 'database정보', password: 'database비밀번호' } module.exports = mysql.createPool(database);
- connectionPool.js
const poolPromise = require('./mysql'); module.exports = { queryParam : async (sql) => { return new Promise (async (resolve, reject) => { try { const pool = await poolPromise; // pool생성 const connection = await pool.getConnection(); try { const result = await connection.query(sql); //sql 쿼리 수행 connection.release(); resolve(result); //프로미스 이행 } catch (err) { connection.release(); reject(err); // 프로미스 실패 } } catch (err) { reject(err); } }) } }
- database에 쿼리 날리는 방식을 async-await으로 구현
- database에 미리 연결된 connection을 생성해서 pool에 저장, 필요 시 pool의 connection 가져다 쓰고, 사용이 끝나면 반환(connection.release())
📌 queryParam : sql문을 매개변수로 받아서 데이터베이스로부터 쿼리 결과를 받아오는 비동기 함수
3. Models
- user.js : 사용자 관련 작업들 담아둠. 로그인, 닉네임 중복확인 등의 작업들을 정의해두었다.
const pool = require('../modules/connectionPool'); const bcrypt = require('bcrypt'); module.exports = { login : async (email) => { const sql = `SELECT * FROM User WHERE email="${email}"`; try { const result = await pool.queryParam(sql); return result; } catch (err) { throw err; } }, /* ..... */ }
4. Controllers
- 요청에 맞춰서 models/user.js 의 작업들을 수행시킨다.
- 예를 들어 위의 로그인 작업을 수행하는 userController 내부 코드는 아래 코드와 같다.
login : async (req, res) => { const { email, pw } = req.body; if (!email || !pw) { return res.status(statusCode.BAD_REQUEST).send(messageCode.MISS_DATA) } // 필요한 데이터 누락 const user = await User.login(email); //models/user.js의 작업 기다림 if (user.length === 0) { // email 에러 return res.status(statusCode.MATCH_ERR).send(messageCode.INVALID_USER); } else { const match = bcrypt.compare(pw, user[0][0].pw); if (!match) { return res.status(statusCode.MATCH_ERR).send(messageCode.INVALID_PW); } } return res.status(statusCode.SUCCESS).json({ code: statusCode.SUCCESS, message: messageCode.SIGN_IN_SUCCESS, userIdx : user[0][0].id }); },
- 로그인이 실패했을 경우에 각각의 에러코드와 메시지를 전달한다. 성공했을 경우에는 우선 userIdx를 성공 응답과 함께 보내주는 것으로 짜둠.
- 아직 JWT 토큰을 안 달아놨는데 그건 다음편에 쓸 예정...
5. Routes
- 클라이언트로부터 들어오는 api요청을 라우팅. 적절한 controller로 보내준다.
- 현재는 index.js, user.js 2개
- REST API구조에 맞춰 주소를 미리 정의해뒀다. userController 쪽으로 넘길거면 주소 형태가 /user/로 시작한다.
📌 index.js
const express = require('express'); const router = express.Router(); router.use('/user', require('./user')); module.exports = router;
- /user 로 시작하는 경우 ./user(같은 routes폴더에 있는 user.js)에 넘겨준다.
- 추후에 /post, /list 뭐 이런 라우터가 있으면 그에 맞는 router로 넘겨주게끔 위 코드 형태로 작성하면 된다.
📌 user.js
const express = require('express'); const router = express.Router(); const userController = require('../controllers/userController'); router.post('/login', userController.login); router.post('/join', userController.join); module.exports = router;
- user/login 주소로 POST 요청이 오면 userController의 login 처리
- user/join 주소로 POST 요청이 오면 userController의 join처리
이러한 방식으로 흘러간다.
일단 간단하게 프로젝트 구조를 좀 개선해봤다. 지금은 아직 로그인/회원가입 정도만 대강 구현해놨다. 다음 포스팅에는 다른 기능들이랑 JWT토큰 발급도 공부해서 써야겠다.
🔽 참고한 블로그들
'BackEnd > Node.js' 카테고리의 다른 글
Node.js 스터디 6주차 (0) 2022.02.22 Node.js 스터디 5주차 (0) 2022.02.15 Node.js 스터디 4주차 (0) 2022.02.07 Node.js 스터디 3주차 (0) 2022.02.05 Node.js 스터디 2주차 (0) 2022.01.25