[Node.js] MySQL - 로그인, 회원가입 구현

이전 포스팅에서 회원가입(사용자 추가) 구현을 완성했으니 로그인(사용자 인증)을 구현하고 로그인, 회원가입을 모두 완성해보자.

먼저 사용자를 인증하는 authUser 함수를 먼저 작성한다.

//사용자 조회(로그인) 함수
var authUser = function (id, password, callback) {
    console.log('authUser 호출됨');
 
    pool.getConnection(function (err, conn) {
        if (err) {
            if (conn) {
                conn.release();
            }
            callback(err, null);
            return;
        }
 
        console.log('DB 연결 스레드 아이디: ' + conn.threadId);
 
        var col = ['id''name''age']; //SELECT ?
        var tablename = 'users';
 
        var exec = conn.query('select ?? from ?? where id = ? and password = ?', [col, tablename, id, password], function (err, rows) {
            conn.release();
            console.log('실행 대상 SQL: ' + exec.sql);
 
            if (err) throw err;
            if (rows.length > 0) {
                console.log('아이디 [%s], 패스워드 [%s] 사용자 찾음', id, password);
                callback(null, rows);
            } else {
                console.log('일치 사용자 못 찾음');
                callback(nullnull);
            }
        });
    });
}
cs

이전에 작성했던 사용자 등록 함수와 SQL문 외에는 다른 것이 없다. 데이터를 조회해야 하므로 SELECT문을 사용한다. 어떤 칼럼, 어떤 테이블, 어떤 조건으로, 이 3가지 정보를 객체로 만들어 전달한다.

SQL문이 정상적으로 실행되면 연결 객체의 release 메소드를 호출하여 연결 객체를 커넥션 풀로 반환한 후 콜백 함수를 실행한다. 이렇게 하면 이 함수를 호출한 쪽에서 rows 객체를 전달받게 된다.

이제 로그인 처리를 요청하는 /process/login 패스에 라우터를 추가하자.

//사용자 조회(로그인) 라우터
router.route('/process/login').post(function (req, res) {
    console.log('/process/login 호출됨');
 
    var paramId = req.body.id || req.query.id;
    var paramPw = req.body.password || req.query.password;
    
    console.log('요청 파라미터: ' + paramId + ', ' + paramPw);
    
    if(pool){
        authUser(paramId, paramPw, function(err, rows){
            if(err){
                console.error('사용자 로그인 오류: '+err.stack);
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>로그인 중 오류 발생함</h1><hr>'+err.stack);
                res.end();
                return;
            }
            
            if(rows){
                console.dir(rows);
                
                var username = rows[0].name;
                
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>로그인 성공!</h1><hr>');
                res.write('<div><p>ID: ' + paramId + '</p></div>');
                res.write('<div><p>이름: ' + username + '</p></div>');
                res.write("<br><a href='/public/login.html'>다시 로그인</a>");
                res.end();
                return;
            } else{
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>해당 사용자 없음!</h1><hr>');
                res.write("<br><a href='/public/login.html'>다시 로그인</a>");
                res.end();
            }
        });
    } else {
        res.writeHead(200, {
            "Content-Type""text/html;charset=utf8"
        });
        res.write('<h1>DB 연결 실패</h1>');
        res.end();
    }
});
cs

사용자가 POST 방식으로 요청한 id, password 파라미터를 확인한 후 authUser() 메소드를 호출하면서 파라미터로 전달한다. 조회한 사용자 데이터는 rows 파라미터에 들어 있으므로 사용자 이름은 그 배열의 첫 번째 배열요소로 참조한다.

이제 login.html, adduser2.html을 모두 완성하자. 로그인 페이지에는 사용자 등록 태그를 추가했다.

/public/login.html
<!DOCTYPE HTML>
<html>
 
<head>
    <meta charset="UTF-8">
    <title>로그인</title>
</head>
 
<body>
    <h1>로그인</h1>
    <br>
    <form method="post" action="/process/login">
        <table>
            <tr>
                <td><label>아이디</label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>비밀번호</label></td>
                <td><input type="password" name="password"></td>
            </tr>
        </table>
        <input type="submit" value="전송" name="">
    </form>
    <a href="/public/adduser2.html">MySQL 사용자 등록</a>
</body>
 
</html>
cs

/public/adduser2.html
<!DOCTYPE HTML>
<html>
 
<head>
    <meta charset="UTF-8">
    <title>MySQL 사용자 등록</title>
</head>
 
<body>
    <h1>MySQL 사용자 등록</h1>
    <hr>
    <form method="post" action="/process/adduser">
        <table>
            <tr>
                <td><label>아이디</label></td>
                <td><input type="text" name="id"></td>
            </tr>
            <tr>
                <td><label>비밀번호</label></td>
                <td><input type="password" name="password"></td>
            </tr>
            <tr>
                <td><label>이름</label></td>
                <td><input type="text" name="name"></td>
            </tr>
            <tr>
                <td><label>나이</label></td>
                <td><input type="text" name="age"></td>
            </tr>
        </table>
        <input type="submit" value="등록하기" name="">
    </form>
</body>
 
</html>
cs

이제 app.js를 실행 후 localhost:3000/public/login.html 으로 접속하여 회원가입, 로그인을 해보자. 정상적으로 출력되었다면 MySQL 데이터베이스를 확인해보자.

-

로그인, 회원가입이 모두 구현된 app.js의 풀 코드는 다음과 같다.

app.js
var express = require('express'),
    http = require('http'),
    path = require('path'),
    bodyParser = require('body-parser'),
    cookieParser = require('cookie-parser'),
    static = require('serve-static'),
    errorHandler = require('errorhandler'),
    expressErrorHandler = require('express-error-handler'),
    expressSession = require('express-session');
 
var mysql = require('mysql');
 
var pool = mysql.createPool({
   connectionLimit: 10,
    host: 'localhost',
    user: 'root',
    password: 'wjswls1',
    database: 'test',
    debug: false
});
 
var app = express();
 
app.set('port', process.env.PORT || 3000);
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use('/public', express.static(__dirname + '/public'));
app.use(cookieParser());
app.use(expressSession({
    secret: 'my key',
    resave: true,
    saveUninitialized: true
}));
 
var router = express.Router();
 
//사용자 등록 라우터
router.route('/process/adduser').post(function(req, res){
    console.log('/process/adduser 호출됨');
    
    var paramId = req.body.id || req.query.id;
    var paramPw = req.body.password || req.query.password;
    var paramName = req.body.name || req.query.name;
    var paramAge = req.body.age || req.query.age;
    
    console.log('요청 파라미터: ' + paramId + ', ' + paramPw + ', ' + paramName + ', ' + paramAge);
    
    if(pool){
        addUser(paramId, paramName, paramAge, paramPw,
               function(err, addedUser){
            if(err){
                console.error('사용자 추가 중 오류: '+err.stack);
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>에러발생</h1>');
                res.end();
                return;
            }
            
            if(addedUser){
                console.dir(addedUser);
                console.log('inserted ' + addedUser.affectedRows + ' rows');
                
                var insertId = addedUser.insertId;
                console.log('추가한 레코드 ID: ' + insertId);
                
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>사용자 추가 성공</h1>');
                res.write("<br><a href='/public/login.html'>로그인</a>");
                res.end();
                return;
            } else{
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>사용자 추가 중 오류</h1>');
                res.write("<br><a href='/public/adduser.html'>되돌아가기</a>");
                res.end();
            }
        });
    } else{
        res.writeHead(200, {
            "Content-Type""text/html;charset=utf8"
        });
        res.write('<h1>DB 연결 실패</h1>');
        res.end();
    }
});
 
//사용자 조회(로그인) 라우터
router.route('/process/login').post(function (req, res) {
    console.log('/process/login 호출됨');
 
    var paramId = req.body.id || req.query.id;
    var paramPw = req.body.password || req.query.password;
    
    console.log('요청 파라미터: ' + paramId + ', ' + paramPw);
    
    if(pool){
        authUser(paramId, paramPw, function(err, rows){
            if(err){
                console.error('사용자 로그인 오류: '+err.stack);
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>로그인 중 오류 발생함</h1><hr>'+err.stack);
                res.end();
                return;
            }
            
            if(rows){
                console.dir(rows);
                
                var username = rows[0].name;
                
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>로그인 성공!</h1><hr>');
                res.write('<div><p>ID: ' + paramId + '</p></div>');
                res.write('<div><p>이름: ' + username + '</p></div>');
                res.write("<br><a href='/public/login.html'>다시 로그인</a>");
                res.end();
                return;
            } else{
                res.writeHead(200, {
                    "Content-Type""text/html;charset=utf8"
                });
                res.write('<h1>해당 사용자 없음!</h1><hr>');
                res.write("<br><a href='/public/login.html'>다시 로그인</a>");
                res.end();
            }
        });
    } else {
        res.writeHead(200, {
            "Content-Type""text/html;charset=utf8"
        });
        res.write('<h1>DB 연결 실패</h1>');
        res.end();
    }
});
 
app.use('/', router);
 
//사용자 등록 함수
var addUser = function(id, name, age, password, callback){
    console.log('addUser 호출됨');
    
    pool.getConnection(function(err, conn){
        if(err){
            if(conn){
                conn.release();
            }
            callback(err, null);
            return;
        }
        
        console.log('DB 연결 스레드 아이디: ' + conn.threadId);
        
        var data = {id:id, name:name, age:age, password:password};
        
        var exec = conn.query('insert into users set ?', data, function(err, result){
            conn.release();
            console.log('실행 대상 SQL: ' + exec.sql);
            
            if(err){
                console.log('SQL 실행 오류 발생');
                console.dir(err);
                callback(err, null);
                return;
            }
            
            callback(null, result);
        });
    });
}
 
//사용자 조회(로그인) 함수
var authUser = function (id, password, callback) {
    console.log('authUser 호출됨');
 
    pool.getConnection(function (err, conn) {
        if (err) {
            if (conn) {
                conn.release();
            }
            callback(err, null);
            return;
        }
 
        console.log('DB 연결 스레드 아이디: ' + conn.threadId);
 
        var col = ['id''name''age']; //SELECT ?
        var tablename = 'users';
 
        var exec = conn.query('select ?? from ?? where id = ? and password = ?', [col, tablename, id, password], function (err, rows) {
            conn.release();
            console.log('실행 대상 SQL: ' + exec.sql);
 
            if (err) throw err;
            if (rows.length > 0) {
                console.log('아이디 [%s], 패스워드 [%s] 사용자 찾음', id, password);
                callback(null, rows);
            } else {
                console.log('일치 사용자 못 찾음');
                callback(nullnull);
            }
        });
    });
}
 
 
// 404 에러 페이지 처리
var errorHandler = expressErrorHandler({
    static: {
        '404''./public/404.html'
    }
});
 
app.use(expressErrorHandler.httpError(404));
app.use(errorHandler);
 
//웹서버 생성
var appServer = http.createServer(app);
appServer.listen(app.get('port'),
    function () {
        console.log('express server started with port ' + app.get('port'));
    }
);
 
cs

댓글 없음:

Powered by Blogger.