11 Database Example app js Express var express
새로운 프로젝트 폴더 만들기 11 • Database. Example 이라는 이름의 새로운 프로젝트 폴더 생성 • 브라켓에서 폴더 열기 메뉴를 이용해 프로젝트 폴더 지정하고 app. js 파일 생성 // Express 기본 모듈 불러오기 var express = require('express') , http = require('http') , path = require('path'); // Express의 미들웨어 불러오기 var body. Parser = require('body-parser') , cookie. Parser = require('cookie-parser') , static = require('serve-static') , error. Handler = require('errorhandler'); // 오류 핸들러 모듈 사용 var express. Error. Handler = require('express-error-handler'); // Session 미들웨어 불러오기 var express. Session = require('express-session'); // 익스프레스 객체 생성 var app = express(); ……. Do it! Node. js 프로그래밍
이전 장에서 입력했던 코드 실행 확인 12 • app. js 파일이 동작하도록 코드 입력 • package. json 파일 생성 및 외장 모듈 설치 후 실행하여 문제없는지 확인 % npm install express --save % npm install http --save % npm install path --save % npm install body-parser --save % npm install cookie-parser --save % npm install serve-static --save % npm install errorhandler --save % npm install express-error-handler --save % npm install express-session --save % npm install mongodb --save Do it! Node. js 프로그래밍
mongodb 모듈 사용하기 13 • mongodb 모듈을 사용하면 몽고디비 데이터베이스에 연결한 후 데이터 추가, 조회 등 가능 • 로그인 기능 만들어보기 위해 public 폴더 안에 login. html 파일 생성 <form method="post" action="/process/login"> <table> <tr> <td><label>아이디</label></td> <td><input type="text" name="id" /></td> </tr> <td><label>비밀번호</label></td> <td><input type="password" name="password" /></td> </tr> </table> <input type="submit" value="전송" name="" /> </form> Do it! Node. js 프로그래밍
데이터베이스에 데이터 추가 14 • 서버 실행 node app. js • insert 명령어를 이용해 데이터 추가 % cls % use local % db. users. remove({"name": /소녀/}) % db. users. find(). pretty() % db. users. insert({"id" : "test 01" , "name" : "소녀시대", "password" : "123456"}) % db. users. find(). pretty() Do it! Node. js 프로그래밍
mongodb 모듈 설치하고 데이터베이스 연결 15 • mongodb 모듈을 설치하고 이 모듈을 이용해 데이터베이스 연결 // 몽고디비 모듈 사용 % npm install mongodb —save var Mongo. Client = require('mongodb'). Mongo. Client; var database; function connect. DB() { // 데이터베이스 연결 정보 var database. Url = 'mongodb: //localhost: 27017/shopping'; // 데이터베이스 연결 Mongo. Client. connect(database. Url, function(err, db) { if(err) throw err; console. log('데이터베이스에 연결되었습니다. : ' + database. Url); // database 변수에 할당 database = db; }); } Do it! Node. js 프로그래밍
아이디, 비밀번호 조회 함수 추가 17 • auth. User라는 이름의 함수를 만들고 데이터베이스에서 조회하도록 코드 작성 var auth. User = function(database, id, password, callback) { console. log('auth. User 호출됨. '); var users = database. collection('users'); users. find({"id" : id, "password" : password}). to. Array(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(null, null); } Do it! Node. js 프로그래밍
라우팅 함수 추가 18 • 클라이언트가 보내온 파라미터를 데이터베이스에서 조회한 값과 비교 // 라우터 객체 참조 var router = express. Router(); ……. router. route('/process/login'). post(function(req, res) { console. log('/process/login 호출됨. '); var param. Id = req. body. id || req. query. id; var param. Password = req. body. password || req. query. password; if(database) { auth. User(database, param. Id, param. Password, function(err, docs) { if(err) {throw err; } if(docs) { console. dir(docs); ……. // 라우터 객체 등록 app. use('/', router); ……. Do it! Node. js 프로그래밍
사용자 추가 기능 만들기 21 • 사용자 인증 기능을 만드는 과정과 동일한 순서로 만들 수 있음 • app. js 파일 복사하여 app 2. js 파일 만들고 add. User 함수 추가 var add. User = function(database, id, password, name, callback) { console. log('add. User 호출됨. '); var users = database. collection('users'); // id, password, username을 사용해 사용자 추가 users. insert. Many([{"id": id, "password": password, "name": name}], function(err, result) { if (err) { // 오류가 발생했을 때 콜백 함수를 호출하면서 오류 객체 전달 callback(err, null); return; } if (result. inserted. Count > 0) { console. log("사용자 레코드 추가됨 : " + result. inserted. Count); } else { console. log("추가된 레코드가 없음. "); } callback(null, result); Do it! Node. js 프로그래밍
라우팅 함수 추가 22 • 사용자를 추가하기 위한 라우팅 함수추가 router. route('/process/adduser'). post(function(req, res) { console. log('/process/adduser 호출됨. '); var param. Id = req. body. id || req. query. id; var param. Password = req. body. password || req. query. password; var param. Name = req. body. name || req. query. name; if(database) { add. User(database, param. Id, param. Password, param. Name, function(err, result) { if(err) {throw err; } // 결과 객체 확인하여 추가된 데이터 있으면 성공 응답 전송 if (result && result. inserted. Count > 0) { console. dir(result); res. write. Head('200', {'Content-Type': 'text/html; charset=utf 8'}); res. write('<h 2>사용자 추가 성공</h 2>'); res. end(); Do it! Node. js 프로그래밍
웹페이지 작성 23 • public 폴더 안에 adduser. html 파일 작성 <form method="post" action="/process/adduser"> <table> <tr> <td><label>아이디</label></td> <td><input type="text" name="id" ></td> </tr> <td><label>비밀번호</label></td> <td><input type="password" name="password" ></td> </tr> <td><label>사용자명</label></td> <td><input type="text" name="name" ></td> </tr> </table> <input type="submit" value="전송" name="" > </form> Do it! Node. js 프로그래밍
몽구스를 이용한 데이터베이스 연결 28 • mongoose 모듈을 이용해 먼저 데이터베이스에 연결 • connect() 메소드로 연결하고 on() 메소드를 이용해 연결되었는지 여부 확인 var database; var User. Schema; var User. Model; function connect. DB() { var database. Url = 'mongodb: //localhost: 27017/local'; // 데이터베이스 연결 console. log('데이터베이스 연결을 시도합니다. '); mongoose. Promise = global. Promise; mongoose. connect(database. Url); database = mongoose. connection; database. on('error', console. error. bind(console, 'mongoose connection error. ')); database. on('open', function () { console. log('데이터베이스에 연결되었습니다. : ' + database. Url); … Do it! Node. js 프로그래밍
데이터베이스 연결 후 스키마와 모델 정의 29 • Schema() 메소드로 스키마를 정의하고 model() 메소드로 모델 정의 database. on('open', function() { console. log('데이터베이스에 연결되었습니다. : ' + database. Url); // 스키마 정의 User. Schema = mongoose. Schema({ id: String, name: String, password: String }); console. log('User. Schema 정의함. '); // User 모델 정의 User. Model = mongoose. model("users", User. Schema); console. log('users 정의함. '); }); Do it! Node. js 프로그래밍
스키마 정의 31 • Schema() 메소드를 이용해 스키마 정의하고 User. Schema 라는 이름의 변수에 할당 var User. Schema = new mongoose. Schema({ id: {type: String, required: true, unique: true}, password: {type: String, required: true}, name: String, age: Number, created_at: Date, updated_at: Date }); 속성 이름 설명 - type 자료형을 지정합니다. - required 값이 true이면 반드시 들어가야 하는 속성이 됩니다. - unique 값이 true이면 이 속성에 고유한 값이 들어가야 합니다. Do it! Node. js 프로그래밍
사용자 인증 함수 추가 34 • 모델 객체의 find() 메소드를 이용해 데이터 조회 var auth. User = function(database, id, password, callback) { console. log('auth. User 호출됨. '); User. Model. find({"id" : id, "password" : password}, function(err, results) { if(err) { callback(err, null); return; } console. log('아이디 [%s], 비밀번호 [%s]로 사용자 검색결과', id, password); console. dir(results); if(results. length > 0) { console. log('일치하는 사용자 찾음. ', id, password); callback(null, results); } else { console. log("일치하는 사용자를 찾지 못함. "); callback(null, null); } }); }; Do it! Node. js 프로그래밍
사용자 추가 함수 추가 35 • 새로운 모델 인스턴스 객체를 만들고 save() 메소드를 이용해 저장 var add. User = function(database, id, password, name, callback) { console. log('add. User 호출됨. '); // User. Model의 인스턴스 생성 var user = new User. Model({"id" : id, "password" : password, "name" : name}); // save()로 저장 user. save(function(err) { if(err) { callback(err, null); return; } console. log("사용자 데이터 추가함. "); callback(null, user); }; Do it! Node. js 프로그래밍
사용자 리스트 조회 기능 추가 39 • 스키마 수정 User. Schema = mongoose. Schema({ id: {type : String, required : true, unique: true}, password : {type : String, required: true}, name: {type : String, index : 'hashed'}, age: {type : Number, 'default' : -1}, created_at : {type : Date, index : {unique : false}, 'default' : Date. now}, updated_at : {type : Date, index : {unique : false}, 'default' : Date. now} }); Do it! Node. js 프로그래밍
스키마에 메소드 추가 40 • static() 메소드를 사용하여 스키마에 메소드 추가 // 스키마에 static 메소드 추가 User. Schema. static('find. By. Id', function(id, callback) { return this. find({id : id}, callback); }); User. Schema. static('find. All', function(callback) { return this. find({ }, callback); }); console. log('User. Schema 정의함. '); // User. Model 모델 정의 User. Model = mongoose. model("users 2", User. Schema); console. log('User. Model 정의함. '); Do it! Node. js 프로그래밍
auth. User() 메소드 안에서 새로 추가한 메소드 사용 42 • auth. User() 메소드 안에서 find. By. Id() 메소드를 사용하도록 수정 var auth. User = function(database, id, password, callback) { console. log('auth. User 호출됨. '); // 1. 아이디를 사용해 검색 User. Model. find. By. Id(id, function(err, results) { if(err) { callback(err, null); return; } console. log('아이디 [%s]로 사용자 검색 결과', id); console. dir(results); if(results. length > 0) { console. log('아이디와 일치하는 사용자 찾음. '); Do it! Node. js 프로그래밍
사용자 리스트 조회를 위한 라우팅 함수 추가 44 • /process/listuser 요청 패스에 대해서는 모델 객체의 find. All() 메소드 직접 사용 router. route('/process/listuser’). post(function(req, res) { console. log(‘/process/listuser 호출됨. '); if(database) { // 1. 모든 사용자 검색 User. Model. find. All(function(err, results) { if (err) { console. error('사용자 리스트 조회 중 오류 발생 : ' + err. stack); res. write. Head('200', {'Content-Type': 'text/html; charset=utf 8'}); res. write('<h 2>사용자 리스트 조회 중 오류 발생</h 2>'); res. write('<p>' + err. stack + '</p>'); res. end(); return; } Do it! Node. js 프로그래밍
사용자 리스트 조회를 위한 라우팅 함수 추가 45 • /process/listuser 요청 패스에 대해서는 모델 객체의 find. All() 메소드 직접 사용 if (results) { // 결과 객체 있으면 리스트 전송 console. dir(results); res. write. Head('200', {'Content-Type': 'text/html; charset=utf 8'}); res. write('<h 2>사용자 리스트</h 2>'); res. write('<div><ul>'); for (var i = 0; i < results. length; i++) { var cur. Id = results[i]. _doc. id; var cur. Name = results[i]. _doc. name; res. write(' <li>#' + i + ' : ' + cur. Id + ', ' + cur. Name + '</li>'); } res. write('</ul></div>'); res. end(); } else { // 결과 객체가 없으면 실패 응답 전송 Do it! Node. js 프로그래밍
사용자 리스트 조회를 위한 웹 페이지 작성 46 • public 폴더 안에 listuser. html 페이지 작성 <!DOCTYPE html> <head> <meta charset="UTF-8"> <title>사용자 리스트 테스트</title> </head> <body> <h 1>사용자 리스트</h 1> <form method="post" action="/process/listuser"> <table> <tr> <td><label>아래 [전송] 버튼을 누르세요. </label></td> </tr> </table> <input type="submit" value="전송" name="" /> </form> </body> </html> Do it! Node. js 프로그래밍
스키마 생성 부분 수정 51 • 스키마 생성 후 virtual() 메소드 호출하여 가상 속성 추가 • 공백으로 구분된 id, password 값을 분리하여 저장하고 조회할 때는 붙여서 조회하도록 함 function create. User. Schema() { // 스키마 정의 … // info를 virtual 메소드로 정의 User. Schema. virtual('info'). set(function(info) { var splitted = info. split(' '); this. id = splitted[0]; this. name = splitted[1]; console. log('virtual info 설정함 : %s, %s', this. id, this. name); }). get(function() {return this. id + ' ' + this. name}); console. log('User. Schema 정의함. '); Do it! Node. js 프로그래밍
테스트 함수 추가 53 • find. All() 함수 안에서 id, name 속성 조회 function find. All() { User. Model. find({}, function(err, results) { if(err) {throw err; } if(results) { console. log('조회된 user 문서 객체 #0 -> id : %s, name : %s', results[0]. _doc. id, results[0]. _doc. name); } }); } Do it! Node. js 프로그래밍
비밀번호 암호화하여 저장하는 코드 적용 55 • crypto 모듈을 이용해 암호화한 후 hashed_password 속성에 저장 var crypto = require('crypto'); % npm install crypto -- save … User. Schema = mongoose. Schema({ id : {type : String, required : true, unique : true, 'default' : ' '}, hashed_password : {type : String, required : true, 'default' : ' '}, salt : {type : String, required : true}, name : {type : String, index : 'hashed', 'default' : ' '}, age : {type : Number, 'default' : -1}, created_at : {type : Date, index : {unique : false}, 'default' : Date. now}, updated_at : {type : Date, index : {unique : false}, 'default' : Date. now} }); Do it! Node. js 프로그래밍
암호화를 위한 virtual 함수 추가 56 • password 속성을 virtual 함수로 추가 User. Schema. virtual('password'). set(function(password) { this. _password = password; this. salt = this. make. Salt(); this. hashed_password = this. encrypt. Password(password); console. log('virtual password 호출됨 : ' + this. hashed_password); }). get(function() {return this. _password}); Do it! Node. js 프로그래밍
스키마에 메소드 추가 57 • 모델 인스턴스 객체에서 사용할 수 있도록 method() 메소드를 호출하여 추가 User. Schema. method('encrypt. Password', function(plain. Text, in. Salt) { if(in. Salt) { return crypto. create. Hmac('sha 1', in. Salt). update(plain. Text). digest('hex'); } else { return crypto. create. Hmac('sha 1', this. salt). update(plain. Text). digest('hex'); } }); // salt 값 만들기 메소드 User. Schema. method('make. Salt', function() { return Math. round((new Date(). value. Of() * Math. random())) + ''; }); Do it! Node. js 프로그래밍
스키마에 메소드 추가 58 • 모델 인스턴스 객체에서 사용할 수 있도록 method() 메소드를 호출하여 추가 // 인증 메소드 - 입력된 비밀번호와 비교 (true/false 리턴) User. Schema. method('authenticate', function(plain. Text, in. Salt, hashed_password) { if(in. Salt) { console. log('authenticate 호출됨 : %s -> %s : %s', plain. Text, this. encrypt. Password(plain. Text, in. Salt), hashed_password); return this. encrypt. Password(plain. Text, in. Salt) === hashed_password; } else { console. log('authenticate 호출됨 : %s -> %s : %s', plain. Text, this. encrypt. Password(plain. Text), this. hashed_password); return this. encrypt. Password(plain. Text) === this. hashed_password; } }); Do it! Node. js 프로그래밍
사용자 추가 함수 작성 60 • add. User 메소드 안에서 사용자 데이터 추가 // 사용자를 등록하는 함수 var add. User = function(database, id, password, name, callback) { console. log('add. User 호출됨. '); // User. Model 인스턴스 생성 var user = new User. Model({"id" : id, "password" : password, "name" : name}); // save()로 저장 user. save(function(err) { if(err) { callback(err, null); return; } console. log("사용자 데이터 추가함. "); callback(null, user); } Do it! Node. js 프로그래밍
사용자 인증 함수 작성 61 • auth. User 함수 안에서 모델 인스턴스 객체의 authenticate() 메소드 사용 var auth. User = function(database, id, password, callback) { console. log('auth. User 호출됨. '); User. Model. find. By. Id(id, function(err, results) { ……. if(results. length > 0) { console. log('아이디와 일치하는 사용자 찾음. '); var user = new User. Model({id : id}); var authenticated = user. authenticate(password, results[0]. _doc. salt, results[0]. _doc. hashed_password); if(authenticated) { console. log('비밀번호 일치함'); callback(null, results); } else { console. log('비밀번호 일치하지 않음'); callback(null, null); } Do it! Node. js 프로그래밍
mysql 모듈을 이용해 데이터베이스 연결 70 • 노드에서는 mysql 모듈을 설치하고 Pool을 이용해 데이터베이스 연결 //===== My. SQL 데이터베이스를 사용할 수 있는 mysql 모듈 불러오기 =====// var mysql = require('mysql'); % npm install mysql --save //===== My. SQL 데이터베이스 연결 설정 =====// var pool = mysql. create. Pool({ connection. Limit : 10, host : 'localhost', user : 'root', password : 'OOOOO', database : 'test', debug : false }); Do it! Node. js 프로그래밍
사용자 추가 함수 작성 72 • get. Connection() 메소드로 연결 객체를 참조한 후 query() 메소드로 SQL 실행 var add. User = function(id, name, age, password, callback) { console. log('add. User 호출됨. '); insert into users set id=’test 01‘, name=’김준수‘, age=20, password=’ 123456’ // 커넥션 풀에서 연결 객체를 가져옵니다. pool. get. Connection(function(err, conn) { if (err) { if (conn) { conn. release(); // 반드시 해제해야 합니다. } callback(err, null); return; } console. log('데이터베이스 연결 스레드 아이디 : ' + conn. thread. Id); Do it! Node. js 프로그래밍
사용자 추가 함수 작성 73 • get. Connection() 메소드로 연결 객체를 참조한 후 query() 메소드로 SQL 실행 …… var data = {id: id, name: name, age: age, password: password}; // SQL문을 실행합니다. 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); }); ……. Do it! Node. js 프로그래밍
라우팅 함수 추가 74 • 사용자를 추가하기 위한 라우팅 함수추가 router. route('/process/adduser'). post(function(req, res) { console. log('/process/adduser 호출됨. '); var var param. Id = req. body. id || req. query. id; param. Password = req. body. password || req. query. password; param. Name = req. body. name || req. query. name; param. Age = req. body. age || req. query. age; if(pool) { add. User(param. Id, param. Name, param. Age, param. Password, function(err, added. User) { // 동일한 id로 추가할 때 오류 발생 - 클라이언트로 오류 전송 if (err) { console. error('사용자 추가 중 오류 발생 : ' + err. stack); Do it! Node. js 프로그래밍
라우팅 함수 추가 75 • 사용자를 추가하기 위한 라우팅 함수추가 res. write. Head('200', {'Content-Type': 'text/html; charset=utf 8'}); res. write('<h 2>사용자 추가 중 오류 발생</h 2>'); res. write('<p>' + err. stack + '</p>'); res. end(); return; } if (added. User) { console. dir(added. User); console. log('inserted ' + result. affected. Rows + ' rows'); var insert. Id = result. insert. Id; console. log('추가한 레코드의 아이디 : ' + insert. Id); res. write. Head('200', {'Content-Type': 'text/html; charset=utf 8'}); res. write('<h 2>사용자 추가 성공</h 2>'); res. end(); Do it! Node. js 프로그래밍
웹페이지 작성 76 • adduser 2. html 페이지 작성 <form method="post" action="/process/adduser"> <table> <tr> <td><label>아이디</label></td> <td><input type="text" name="id" ></td> </tr> <td><label>사용자명</label></td> <td><input type="text" name="name" ></td> </tr> <td><label>나이</label></td> <td><input type="text" name="age" ></td> </tr> <td><label>비밀번호</label></td> <td><input type="password" name="password" ></td> </tr> </table> <input type="submit" value="전송" > </form> Do it! Node. js 프로그래밍
로그인 기능을 위한 함수 추가 78 • 로그인 기능을 테스트하기 위해 auth. User 함수 추가 var auth. User = function(id, password, callback) { console. log('auth. User 호출됨. '); // 커넥션 풀에서 연결 객체를 가져옵니다. pool. get. Connection(function(err, conn) { if (err) { if (conn) { conn. release(); // 반드시 해제해야 합니다. } callback(err, null); return; } console. log('데이터베이스 연결 스레드 아이디 : ' + conn. thread. Id); Do it! Node. js 프로그래밍
로그인 기능을 위한 함수 추가 79 • 로그인 기능을 테스트하기 위해 auth. User 함수 추가 var columns = ['id', 'name', 'age']; var tablename = 'users'; // SQL문을 실행합니다. var exec = conn. query("select ? ? from ? ? where id = ? and password = ? ", [columns, tablename, id, password], function(err, rows) { conn. release(); // 반드시 해제해야 합니다. console. log('실행 대상 SQL : ' + exec. sql); if(rows. length > 0) { console. log('아이디 [%s], 패스워드 [%s] 가 일치하는 사용자 찾음. ', id, password); callback(null, rows); } else { console. log("일치하는 사용자를 찾지 못함. "); callback(null, null); } }); select id, name, age from users where id = ‘test 01’ and password = ‘ 123456’ Do it! Node. js 프로그래밍
라우팅 함수 추가 80 • 사용자 로그인을 위한 라우팅 함수추가 router. route('/process/login'). post(function(req, res) { console. log('/process/login 호출됨. '); var param. Id = req. body. id || req. query. id; var param. Password = req. body. password || req. query. password; if(pool) { auth. User(param. Id, param. Password, function(err, rows) { if(err) …. if(rows) { console. dir(rows); var username = rows[0]. name; res. write. Head('200', {'Content-Type': 'text/html; charset=utf 8'}); res. write('<h 1>로그인 성공</h 1>'); res. write('<div><p>사용자 아이디 : ' + param. Id + '</p></div>'); res. write('<div><p>사용자 이름 : ' + username + '</p></div>'); res. write(" <a href='/public/login 2. html'>다시 로그인하기</a>"); res. end(); Do it! Node. js 프로그래밍
실행 확인 81 • 웹페이지에서 접속하여 확인 ▶ http: //localhost: 3000/public/login 2. html Do it! Node. js 프로그래밍
- Slides: 82