6챕터-데이터베이스 사용하기
웹 서버가 사용자 요청을 받으면 데이터베이스에 있는 데이터를 조회하여 응답하거나 또는 사용자가 보낸 데이터를 데이터베이스에 저장한다. 데이터베이스 유형은 데이터를 메모리에 저장하는 형태부터 오라클이나 MySQL 같은 관계형 데이터베이스, 몽고디비와 같은 NoSQL에 이르기까지 다양하다. 특히 몽고디비는 자비스크립트 객체를 그대로 저장할 수 있어서 자바스크립트 언어를 사용하는 노드에서 데이터를 저장하기 좋은 데이터베이스이다. 책에선 몽고디비로 데이터를 저장하고 조회하는 방법을 소개하고 있다.
몽고디비 시작하기
실무에서는 오라클이나 MySQL과 같은 관계형 데이터베이스를 많이 사용한다. 그러나 최근 비관계형 데이터베이스를 적용하는 곳이 늘고 이쓰며, 이런 시스템을 NoSQL 또는 Not Only SQL 이라고 한다.
관계형 데이터베이스는 시스템의 신뢰도를 높이는데 필요한 장치를 많이 가지고 있다. 또 SQL문을 읽어 들이고 실행하는 데 많은 리소스를 사용하며 이 떄문에 성능이 떨어지는 경우가 많다. 이에 반해 NoSQL 데이터베이스는 성능을 최우선으로 생각하기 때문에 실시간으로 처리해야 하는 경우나 대용량 트래픽을 감당할 수 있는 메시징 시스템 등에 활용된다. 특히 클라우드 서비스로 서버를 구성하는 경우가 많아지면서 많은 사용자를 수용하거나 시스템 자원을 적게 소모하는 NoSQL 데이터베이스에 점점 더 관심을 갖게 되었다고 한다.
몽고디비는 NoSQL이기 때문에 관계형데이터베이스의 테이블의 개념이 없다. 그 대신 몽고디비는 여러 데이터가 모인 하나의 단위를 컬렉션(Collection)이라고 부른다. 테이블과 달리 데이터를 정해 놓은 칼럼의 형태대로 컬렉션에 넣어야 한다는 제약이 없다.
설치 후 시스템 환경 변수 추가를 한다.
익스프레스에서 몽고디비 사용하기
앞서 사용한 코드들을 이용하여 Databaseexample 폴더에 app.js 파일을 생성한다.
폴더에 npm init 을 통해 package.json 파일을 생성한 후 필요한 모듈들을 설치한다.
(npm install express --save 등등)
package.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
{
"name": "package",
"version": "1.0.0",
"description": "",
"main": "app.js",
"dependencies": {
"body-parser": "^1.18.2",
"cookie-parser": "^1.4.3",
"errorhandler": "^1.5.0",
"express": "^4.16.2",
"express-error-handler": "^1.1.0",
"express-session": "^1.15.6",
"http": "0.0.0",
"mongodb": "^2.2.33",
"path": "^0.12.7",
"serve-static": "^1.13.1"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
| cs |
이 파일의 dependencies 정보는 새로운 프로젝트를 생성할때 그대로 사용 가능하다. 새 프로젝트를 만들었을때 이 파일과함께 npm install 명령을 해주면 이 정보대로 설치가 된다.
<mongodb를 이용한 간단한 아이디 체크,추가>
login.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<!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="전송" />
</form>
</body>
</html>
| cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>사용자추가 테스트</title>
</head>
<body>
<h1>사용자추가</h1>
<br>
<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>
</table>
<input type="submit" value="전송" name="" />
</form>
</body>
</html>
| cs |
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
|
/**
* 데이터베이스 사용하기
*
* 몽고디비에 사용자 추가하기
* 웹브라우저에서 아래 주소의 페이지를 열고 웹페이지에서 요청
* http://localhost:3000/public/adduser.html
*
* @date 2016-11-10
* @author Mike
*/
// Express 기본 모듈 불러오기
var express = require('express')
, http = require('http')
, path = require('path');
// Express의 미들웨어 불러오기
var bodyParser = require('body-parser')
, cookieParser = require('cookie-parser')
, static = require('serve-static')
, errorHandler = require('errorhandler');
// 에러 핸들러 모듈 사용
var expressErrorHandler = require('express-error-handler');
// Session 미들웨어 불러오기
var expressSession = require('express-session');
// 몽고디비 모듈 사용
var MongoClient = require('mongodb').MongoClient;
// 익스프레스 객체 생성
var app = express();
// 기본 속성 설정
app.set('port', process.env.PORT || 3000);
// body-parser를 이용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({ extended: false }))
// body-parser를 이용해 application/json 파싱
app.use(bodyParser.json())
// public 폴더를 static으로 오픈
app.use('/public', static(path.join(__dirname, 'public')));
// cookie-parser 설정
app.use(cookieParser());
// 세션 설정
app.use(expressSession({
secret:'my key',
resave:true,
saveUninitialized:true
}));
//===== 데이터베이스 연결 =====//
// 데이터베이스 객체를 위한 변수 선언
var database;
//데이터베이스에 연결
function connectDB() {
// 데이터베이스 연결 정보
var databaseUrl = 'mongodb://localhost:27017/local';
// 데이터베이스 연결
MongoClient.connect(databaseUrl, function(err, db) {
if (err) throw err;
console.log('데이터베이스에 연결되었습니다. : ' + databaseUrl);
// database 변수에 할당
database = db;
});
}
//===== 라우팅 함수 등록 =====//
// 라우터 객체 참조
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 + ', ' + paramPassword);
// 데이터베이스 객체가 초기화된 경우, authUser 함수 호출하여 사용자 인증
if (database) {
authUser(database, paramId, paramPassword, function(err, docs) {
if (err) {throw err;}
// 조회된 레코드가 있으면 성공 응답 전송
if (docs) {
console.dir(docs);
// 조회 결과에서 사용자 이름 확인
var username = docs[0].name;
res.writeHead('200', {'Content-Type':'text/html;charset=utf8'});
res.write('<h1>로그인 성공</h1>');
res.write('<div><p>사용자 아이디 : ' + paramId + '</p></div>');
res.write('<div><p>사용자 이름 : ' + username + '</p></div>');
res.write("<br><br><a href='/public/login.html'>다시 로그인하기</a>");
res.end();
} else { // 조회된 레코드가 없는 경우 실패 응답 전송
res.writeHead('200', {'Content-Type':'text/html;charset=utf8'});
res.write('<h1>로그인 실패</h1>');
res.write('<div><p>아이디와 패스워드를 다시 확인하십시오.</p></div>');
res.write("<br><br><a href='/public/login.html'>다시 로그인하기</a>");
res.end();
}
});
} else { // 데이터베이스 객체가 초기화되지 않은 경우 실패 응답 전송
res.writeHead('200', {'Content-Type':'text/html;charset=utf8'});
res.write('<h2>데이터베이스 연결 실패</h2>');
res.write('<div><p>데이터베이스에 연결하지 못했습니다.</p></div>');
res.end();
}
});
// 사용자 추가 라우팅 함수 - 클라이언트에서 보내오는 데이터를 이용해 데이터베이스에 추가
router.route('/process/adduser').post(function(req, res) {
console.log('/process/adduser 호출됨.');
var paramId = req.body.id || req.query.id;
var paramPassword = req.body.password || req.query.password;
var paramName = req.body.name || req.query.name;
console.log('요청 파라미터 : ' + paramId + ', ' + paramPassword + ', ' + paramName);
// 데이터베이스 객체가 초기화된 경우, addUser 함수 호출하여 사용자 추가
if (database) {
addUser(database, paramId, paramPassword, paramName, function(err, result) {
if (err) {throw err;}
// 결과 객체 확인하여 추가된 데이터 있으면 성공 응답 전송
if (result && result.insertedCount > 0) {
console.dir(result);
res.writeHead('200', {'Content-Type':'text/html;charset=utf8'});
res.write('<h2>사용자 추가 성공</h2>');
res.end();
} else { // 결과 객체가 없으면 실패 응답 전송
res.writeHead('200', {'Content-Type':'text/html;charset=utf8'});
res.write('<h2>사용자 추가 실패</h2>');
res.end();
}
});
} else { // 데이터베이스 객체가 초기화되지 않은 경우 실패 응답 전송
res.writeHead('200', {'Content-Type':'text/html;charset=utf8'});
res.write('<h2>데이터베이스 연결 실패</h2>');
res.end();
}
});
// 라우터 객체 등록
app.use('/', router);
// 사용자를 인증하는 함수
var authUser = function(database, id, password, callback) {
console.log('authUser 호출됨 : ' + id + ', ' + password);
// users 컬렉션 참조
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 { // 조회한 레코드가 없는 경우 콜백 함수를 호출하면서 null, null 전달
console.log("일치하는 사용자를 찾지 못함.");
callback(null, null);
}
});
}
//사용자를 추가하는 함수
var addUser = function(database, id, password, name, callback) {
console.log('addUser 호출됨 : ' + id + ', ' + password + ', ' + name);
// users 컬렉션 참조
var users = database.collection('users');
// id, password, username을 이용해 사용자 추가
users.insertMany([{"id":id, "password":password, "name":name}], function(err, result) {
if (err) { // 에러 발생 시 콜백 함수를 호출하면서 에러 객체 전달
callback(err, null);
return;
}
// 에러 아닌 경우, 콜백 함수를 호출하면서 결과 객체 전달
if (result.insertedCount > 0) {
console.log("사용자 레코드 추가됨 : " + result.insertedCount);
} else {
console.log("추가된 레코드가 없음.");
}
callback(null, result);
});
}
// 404 에러 페이지 처리
var errorHandler = expressErrorHandler({
static: {
'404': './public/404.html'
}
});
app.use( expressErrorHandler.httpError(404) );
app.use( errorHandler );
//===== 서버 시작 =====//
// 프로세스 종료 시에 데이터베이스 연결 해제
process.on('SIGTERM', function () {
console.log("프로세스가 종료됩니다.");
app.close();
});
app.on('close', function () {
console.log("Express 서버 객체가 종료됩니다.");
if (database) {
database.close();
}
});
// Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
console.log('서버가 시작되었습니다. 포트 : ' + app.get('port'));
// 데이터베이스 연결을 위한 함수 호출
connectDB();
});
| cs |
예제를 홈페이지에서 받았는데 책과 다르다 ;;;; 위는 완성된 예제
댓글 없음:
댓글 쓰기