# Express.js와 MySql기반 서버 구축(SignUp 구축)

## 개요

Next.js와 Express.js를 연계하여 도서 대여 서비스를 구축하고자 한다. 로그인 서비스를 구축하고 있으며 오늘은 서버 구축 과정에 대해 이야기해보고자 한다.

## Server.js

```javascript
const express = require('express');
const bodyParser = require('body-parser');

const cors = require('cors');

const loginRouter = require('./routes/auth/login');
const signUpRouter = require('./routes/auth/signup');
const authRouter = require('./routes/auth/auth');
const secretGenerator = require('./secret');

const app = express();
const port = 3001;

secretGenerator.updateSecretKey();

// 주기적으로 실행 (예: 24시간마다)
const interval = 2 * 60 * 60 * 1000; // 24시간
setInterval(secretGenerator.updateSecretKey, interval);

app.use(cors());

app.use(express.urlencoded({ extended: true }));
app.use(bodyParser.json());

// app.post('/auth/login', login.getUserHandler);
app.use('/auth/login', loginRouter);
app.use('/auth/signup', signUpRouter);
app.use('/auth/auth', authRouter);

app.listen(port, () => {
	console.log('Server port: ', port);
});
```

loginRouter와 signUpRouter를 분리했다.

기본적으로 app.use()로 원하는 라우터에 분리한 라우터 모듈을 분리하여 등록했다. 이중 signUpRouter에 대해 자세히 보자.

## signUpRouter

```javascript
const express = require('express');

const signUpController = require('../../controllers/userSignupController');

const router = express.Router();

router.use((req, res, next) => {
	console.log('sign up process');
	next();
});

router.post('/', signUpController.addUserHandler);

module.exports = router;
```

라우터를 살펴보면, express.Router()로 라우터를 생성하고, router.post('/', function );를 통해 '/auth/signup'에 signUpController 모듈의 addUserHandler함수를 등록하여, 이 라우터로 post 요청이 들어올 때마다, 이 함수를 실행한다.

## signUpController

signUp 과정에서 데이터를 request로 보냈을 때, 데이터를 처리하는 프로세스를 담당한다.

```javascript
const db = require('../db');
const User = require('../models/user');

exports.addUserHandler = async (req, res) => {
	const userName = req.body.user;
	const studentId = req.body.student_id;
	const password = req.body.password;

	const userData = new User(userName, studentId, password);

	function callback_onAdd(object) {
		res.set('Content-Type', 'application/json');
		if (!object.result) {
			res.send({ message: 'Database failed', result: 0 });
		} else {
			res.send({ message: 'Sign up success', result: 1 });
		}
	}

	function callback_onCheck(object) {
		res.set('Content-Type', 'application/json');
		if (object.isSuccess === 'no data') {
			userData.addUser(callback_onAdd);
		} else if (object.isSuccess === 'log in') {
			res.send({ message: 'You already have account', result: 0 });
		}
	}

	userData.checkUser(callback_onCheck);
};
```

addUserHandler 함수는 클라이언트에서 request를 보냈을 때, body에서 student\_id와 password, username을 얻어낸다. 이는 클라이언트에서 회원가입할 때, 입력하는 정보이다.

checkUser 함수는 user 모델 클래스의 메소드로

```javascript
	checkUser(cb) {
		let sql = `SELECT * FROM login_data WHERE student_id='${this.student_id}' AND password='${this.password}'`;

		db.query(sql, (err, rows) => {
			if (err) {
				console.log('Error occured during checking user data', err);
				cb({ isSuccess: 'error', id: -1, username: '' });
			} else if (rows.length >= 1) {
				console.log('You log in!');
				cb({
					isSuccess: 'log in',
					id: rows[0].id,
					username: rows[0].user_name,
				});
			} else if (rows.length === 0) {
				console.log('no data please make an account');
				cb({ isSuccess: 'no data', id: -1, username: '' });
			}
		});
	}
```

mysql 데이터베이스에 SELECT구문으로 모든 데이터를 가져온다. db.query문을 통해 쿼리 결과가 rows에 들어가 콜백함수를 실행한다.콜백 함수의 인자로 쿼리 성공 여부와 쿼리 결과로 얻은 username을 입력한다.

username: rows\[0\].user\_name 에서 rows\[0\]는 쿼리 결과로 얻는 데이터 중 첫 번째 데이터이므로, 여기서 user\_name을 얻을 수 있다.

콜백함수로 실행하는 callback\_onCheck(object)

```javascript
	function callback_onCheck(object) {
		res.set('Content-Type', 'application/json');
		if (object.isSuccess === 'no data') {
			userData.addUser(callback_onAdd);
		} else if (object.isSuccess === 'log in') {
			res.send({ message: 'You already have account', result: 0 });
		}
	} 
```

쿼리결과로 얻는 isSuccess 값에 따라 no data일 때, addUser()를하고, log in일 때, 이미 계정이 있음을 res.send()로 전달한다. addUser()는

```javascript
	addUser(cb) {
		let sql = `INSERT INTO login_data (user_name, student_id, password) VALUES (?, ?, ?)`;

		db.query(
			sql,
			[this.username, this.student_id, this.password],
			(err, results) => {
				if (err) {
					cb({
						message: 'Error occured during adding user data',
						result: 0,
					});
				} else {
					cb({ message: 'Adding account success', result: 1 });
				}
			}
		);
	}
```

```javascript
	function callback_onAdd(object) {
		res.set('Content-Type', 'application/json');
		if (!object.result) {
			res.send({ message: 'Database failed', result: 0 });
		} else {
			res.send({ message: 'Sign up success', result: 1 });
		}
	}
```

addUser는 Insert 구문을 통해 입력한 username, student\_id, password로 sql구문을 통해 데이터베이스에 유저데이터를 넣는다. 그리고, 해당 쿼리문 결과에 따라 callback 함수로 callback\_onAdd()함수를 실행하여 insert쿼리에 성공했으면, res.send()로 클라이언트에 회원가입을 성공했음을 result에 담아서 보낸다.
