[Node.js] 몽고디비 - 익스프레스에서 사용하기 (로그인 구현)

MongoDB 익스프레스에서 시작하기

몽고디비 모듈을 사용하기 위해 cmd에서 npm i mongodb --save 입력 후 설치한다. 몽고디비 쉘에서 다음 명령을 입력한다.

> use local
switched to db local
> db.users.remove({name:/zini/})
WriteResult({ "nRemoved" : 1 })
> db.users.find()
> db.users.insert({id:'test',  name:'testuser', password:'1234'})
WriteResult({ "nInserted" : 1 })
> db.users.find().pretty()
{
        "_id" : ObjectId("5e60add815b2efd4aff61eda"),
        "id" : "test",
        "name" : "testuser",
        "password" : "1234"
}
cs

1. local 데이터베이스로 변경한다.
2. 이전 포스팅에서 추가했던 users 컬렉션에서 zini 도큐먼트를 삭제한다.
3. users 컬렉션을 조회한다. (0개라서 아무것도 표시되지 않는다)
4. 로그인 테스트를 위해 testuser 도큐먼트를 추가한다.
5. users 컬렉션을 '예쁘게' 조회한다.

tip. 몽고디비 쉘을 한번에 지우고 싶다면 cls를 입력한다.

이제 mongodb 모듈을 불러와서 사용해보자. 우선 틀만 작성한다.

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'),
    MongoClient = require('mongodb').MongoClient;
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use('/public', static(path.join(__dirname, 'public')));
app.use(cookieParser());
app.use(expressSession({
    secret: 'my key', resave: true, saveUninitialized: true
}));
var router = express.Router();
router.route('/process/login').post(function(req, res){
    console.log('/process/login 호출됨');
    
});
//DB 객체를 위한 변수선언
var database;
//DB 연결
function connectDB(){
    var databaseUrl = 'mongodb://localhost:27017/local';
    
    MongoClient.connect(databaseUrl, function(err, db){
        if (err) throw err;
        
        console.log('DB 연결됨 : ' + databaseUrl);
        //database 변수에 할당
        database = db;
    });
}
app.use('/', router);
//404 Error Handling
var errorHandler = expressErrorHandler({
    static: { '404''./public/404.html'}
});
app.use(expressErrorHandler.httpError(404));
app.use(errorHandler);
//서버 시작
http.createServer(app).listen(app.get('port'), function(){
    console.log('Server started with port ' + app.get('port'));
    connectDB(); //데이터베이스 연결
});
cs

모듈을 불러들이면서 동시에 그 객체 안의 MongoClient 속성을 참조한다. 이제부터 이 객체를 사용해 몽고디비를 사용할 수 있다.

ConnectDB 함수는 mongodb 모듈을 사용해 데이터베이스에 연결하도록 새로 만든 것이다. 데이터베이스에 연결하려면 먼저 연결 정보를 문자열로 정의해야 한다. 문자열 형식은 다음과 같다.

mongodb://%IP정보%:%포트정보%/%데이터베이스이름%
cs

localhost 환경이므로 27017 포트에서 실행되고 있는 local 데이터베이스에 연결하도록 연결 정보를 만든다.

데이터베이스에 연결하려면 mongodb 객체의 connect() 메소드를 호출한다. 첫 번째 파라미터로 연결 URL을 전달하고, 두 번째 파라미터로 콜백 함수를 전달한다. 데이터베이스가 정상적으로 연결되면 db 객체가 전달되는데 이 객체를 database 변수에 저장한다.

서버가 실행되면 connectDB 함수를 호출하여 데이터베이스에 연결한다.

사용자 아이디, 비밀번호 비교하기

사용자 아이디, 비밀번호를 보내왔을 때 데이터베이스 안에 일치하는 문서 객체가 있는지 조회하는 authUser 함수를 작성해보자.

var authUser = function(database, id, password, callback){
    console.log("authUser 호출됨");
    
    var users = database.collection('users');
    users.find({"id": id, "password": password}).toArray(function(err, docs){
        if(err) {
            callback(err, null); return;
        }
        
        if(docs.length > 0){
            console.log('아이디 [%s], 비밀번호 [%s] 일치 사용자 찾음', id, password);
            callback(null, docs);
        }
        else{
            console.log('일치 사용자 없음');
            callback(nullnull);
        }
    });
}
cs

위 코드를 작성했던 틀 코드의 connectDB 함수 밑에 입력한다. authUser 함수는 데이터베이스 객체, 아이디, 비밀번호를 파라미터로 받으며 콜백 함수도 파라미터로 전달받는다.

데이터베이스의 users 컬렉션 안에 사용자 정보가 들어 있으므로 database.collection() 메소드로 users 컬렉션 객체를 참조한다.

그 다음 find() 메소드를 호출하여 데이터를 조회한다. id, password 속성 값을 파라미터로 전달하여 조회한 후 조회 결과는 toArray() 메소드를 사용해서 배열 객체로 반환한다.

docs의 값이 0보다 크면 사용자 데이터가 조회된 것이므로 콜백 함수를 호출하면서 docs 객체를 파라미터로 전달한다. 이렇게 하면 이 함수를 호출한 쪽에서 콜백 함수를 사용해 docs 객체를 전달받을 수 있다.

로그인 처리 요청 패스에 라우팅 함수 추가하기

이제 로그인 처리를 요청하는 /process/login 패스에 라우팅 함수를 추가하고 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'),
    MongoClient = require('mongodb').MongoClient;
//DB 객체를 위한 변수선언
let database;
//DB 연결
function connectDB() {
    const databaseUrl = 'mongodb://localhost:27017';
    MongoClient.connect(databaseUrl, {useNewUrlParser: true, useUnifiedTopology: true}, function(err, client) {
        if (err) throw err;
        console.log('DB 연결됨 : ' + databaseUrl);
        //database 변수에 할당
        let db = client.db("local");
        database = db
    })
}
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/login').post(
    function (req, res) {
        console.log('process/login 호출됨');
        var paramId = req.body.id || req.query.id;
        var paramPassword = req.body.password || req.query.password;
        console.log('paramId : ' + paramId + ', paramPW : ' + paramPassword);
        if (database) {
            authUser(database, paramId, paramPassword,
                function (err, docs) {
                    if (err) {
                        console.log('Error!');
                        res.writeHead(200, {
                            "Content-Type""text/html;charset=utf8"
                        });
                        res.write('<h1>에러발생</h1>');
                        res.end();
                        return;
                    }
                    if (docs) {
                        console.dir(docs);
                        res.writeHead(200, {
                            "Content-Type""text/html;charset=utf8"
                        });
                        res.write('<h1>로그인 성공</h1>');
                        res.write('<h1> user </h1>' + docs[0].id + '  :   ' + docs[0].name);
                        res.write('<br><a href="/public/login.html">다시 로그인 </a>');
                        res.end();
                    } else {
                        console.log('Error(empty)');
                        res.writeHead(200, {
                            "Content-Type""text/html;charset=utf8"
                        });
                        res.write('<h1>사용자 없음</h1>');
                        res.write('<a href="/public/login.html">다시 로그인</a>');
                        res.end();
                    }
                });
        } else {
            console.log('DB 연결 안됨');
            res.writeHead(200, {
                "Content-Type""text/html;charset=utf8"
            });
            res.write('<h1>데이터베이스 연결 안됨</h1>');
            res.end();
        }
    }
);
app.use('/', router);
var authUser = function (db, id, password, callback) {
    console.log("authUser 호출됨");
    var users = db.collection('users');
    var result = users.find({
        "id": id,
        "password": password
    });
    result.toArray(
        function (err, docs) {
            if (err) {
                callback(err, null);
                return;
            }
            if (docs.length > 0) {
                console.log('아이디 [%s], 비밀번호 [%s] 일치 사용자 찾음', id, password);
                callback(null, docs);
            } 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'));
        connectDB(); //DB 연결
    }
);
cs

정말 우여곡절이 많았다..
책이 옛날에 출판되서 몽고디비 관련 명령어가 많이 바껴서 애를 많이 먹었다.
그리고 아무리 코드를 수정해도 브라켓 node runner에서 실행이 안되서 cmd에서 node run을 해보니 잘 되었다. (아직도 왜 그런지는 모르겠다)

아무튼 코드를 설명하자면,
authUser() 함수는 데이터베이스 객체, 아이디, 비밀번호를 파라미터로 받고 콜백 함수도 파라미터로 전달받는다. 데이터베이스 users 컬렉션 안에 사용자 정보가 있으므로 db.collection() 메소드로 users 컬렉션 객체를 참조한다. 그 다음 find() 메소드로 데이터를 조회하고, toArray() 메소드로 배열 객체로 반환한다.

댓글 없음:

Powered by Blogger.