일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Exercism
- 자바스크립트
- 장고 프로젝트 순서
- MYSQL
- 프로젝트
- MyPick31
- 독립영화플랫폼
- 예술영화추천
- 북마크만들기
- Django Blog
- 타사인증
- ART_Cinema
- 개발
- python
- Django
- Node.js
- 장고 개발 순서
- mongodb
- 파이썬 웹프로그래밍 장고
- passport.js
- 장고
- Algorithm
- 알고리즘
- 북마크앱
- Blog
- JavaScript
- Bookmark
- til
- join()
- 장고 프로젝트
- Today
- Total
Juni_Dev_log
(node.js) [Part.6] 데이터 베이스 사용하기 - 인덱스와 메소드 사용하기 본문
몽고디비는 데이터베이스이므로 빠른 검색을 위해 각각의 속성에 인덱스를 만들 수 있다.
스키마를 만들 때 각 속성의 스키마 타입에는 여러 정보가 들어갈 수 있는데, 인덱스도 그 중 하나이다.
예를 들어, 다음과 같이 사용자 스키마를 만들면서 인덱스 정보를 추가할 수 있다.
var UserSchema = new mongoose.Schema({
id : {type:String, required:true, unique:true},
password : {type:String, required:true},
name : {type:String, index: 'hashed'},
age : Number
created_at : {type:Date, index:{unique:false,expires:'1d'}},
updated_at : Date
});
id 속성 값으로 전달된 자바스크립트 객체에는 unique 속성값이 true로 되어있다. 이렇게 하면 자동으로 인덱스가 만들어진다.
name 속성 값으로 들어가는 객체는 index 속성 값이 hashed 로 되어있다. 이 속성을 사용하면 인덱스가 만들어진다.
만들어진 날짜를 의미하는 created_at 속성에도 인덱스가 설정되었으며, 인덱스가 설정되는 값의 유효기간(expires)까지 설정했다.
인덱스를 사용하면 검색 속도가 빨라지므로 조회가 필요한 속성에는 인덱스를 만들어 두는 것이 좋다.
위치 기반 서비스를 위해 저장되는 경위도 좌표에는 공간 인덱싱을 사용해야 하며, {type : [Number], index:'2d', sparse : true} 와 같은 형태로 객체를 만들어 설정할 수 있다.
mongoose에서는 스키마 객체에 메소드를 추가할 수 있다. 메소드를 추가할 때는 static() 과 method() 중 하나를 사용할 수 있는데 static()은 모델 객체에서 호출할 수 있으며 method()는 모델 인스턴스 객체에서 호출할 수 있다.
메소드 이름 | 설명 |
static(name, fn) | 모델 객체에서 사용할 수 있는 함수를 등록한다. 함수의 이름과 함수 객체를 파라미터로 전달한다. |
method(name, fn) | 모델 인스턴스 객체에서 사용할 수 있는 함수를 등록한다. 함수의 이름과 함수 객체를 파라미터로 전달한다. |
사용자 리스트 조회 기능 추가하기
app3.js 파일을 복사하여 app4.js 를 만든 후, 사용자 리스트를 조회하는 기능을 추가해보자.
users 컬렉션은 이미 만들어져있으므로 삭제하지 않도록 주의한다. 그리고 users 보다 더 많은 칼럼을 가지고 있고 인덱스도 더 많이 만들어져 있는 users2 컬렉션을 새로운 스키마로 정의할 것이며, 사용자 리스트를 조회하는 기능도 추가해보자.
먼저 앞에서 만든 스키마와 모델 객체를 다음과 같이 수정한다.
1
2
3
4
5
6
7
8
9
10
11
|
...
// 스키마 정의
UserSchema = mongoose.Schema({
id : {type:String, required: true, unique : true},
password : {type:String, required: true},
name : {type:String, index:'hashed'},
age : Number,
created_at : {type:Date, index:{unique:false, expires : '1d'}},
updated_at : Date
});
...
|
cs |
스키마에는 id, password, name 이외에 age, created_at, updated_at 속성을 더 추가한다.
각각의 속성은 스키마 타입의 정보를 갑승로 갖는다. id 속성은 required 속성을 사용해서 필수 속성으로 지정하고 unique 속성으로 고유한 값을 지정한다.
name 속성은 인덱스를 만들어 둔다.
age 속성은 기본값은 -1로 하여 값을 입력하지 않으면 -1값이 디폴트로 들어간다.
created_at 와 updated_at 속성은 Date 타입으로 만들고 현재 시간을 디폴트 값으로 지정한다.
그 다음에는 static() 메소드를 사용하여 스키마에 메소드를 추가한다.
static() 메소드의 첫 파라미터는 함수 이름, 두 번째 파라미터는 호출된 함수가 전달된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
...
// 스키마에 static 메소드 추가
UserSchema.static('findById', function(id,callback){
return this.find({id:id}, callback);
});
UserSchema.static('findAll', function(id,callback){
return this.find({}, callback);
});
console.log('UserSchema 정의함.');
// UserModel 모델 정의
UserModel = mongoose.model("users2", UserSchema);
console.log('UserModel 정의함.');
...
|
cs |
먼저 모델 객체에서 호출할 수 있도록 findById 함수를 추가한다.
이 함수는 id속성을 데이터베이스에서 검색한 후 콜백 함수 쪽으로 결과를 넘겨준다. users2 컬렉션의 모든 문서를 반환하는 findAll 함수도 추가한다.
모델 객체를 만들 때는 컬렉션의 이름을 users2 로 지정한다.
코드에서는 추가하지 않았지만, 만약 showMe 메소드를 method() 함수로 추가하면 모델 인스턴스 객체에서도 사용할 수 있다.
스키마에 사용자를 찾는 기능을 메소드로 추가한다. 따라서 authUser 함수 안에서 데이터베이스의 users2 컬렉션을 조회할 때 스키마에 새로 추가한 메소드를 사용하도록 코드를 변경한다.
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
|
...
// 사용자를 인증하는 함수 : 아이디로 먼저 찾고 비밀번호를 그 다음 비교
var authUser = function(database, id, password, callback){
console.log('authUser 호출됨 : ' + id + ', ' + password);
// 1. 아이디를 사용해서 검색
UserModel.findById(id, function(err,results){
if(err){
callback(err,null);
return;
}
console.log('아이디 [%s]로 사용자 검색 결과',id);
console.dir(results);
if(results.length > 0){
console.log('아이디와 일치하는 사용자 찾음.');
// 2. 비밀번호 확인
if(results[0]._doc.password === password){
console.log('비밀번호 일치함.');
callback(null,results);
} else{
console.log('비밀번호가 일치하지 않음.');
callback(null, null);
}
}else{
console.log('아이디와 일치하는 사용자를 찾지 못함.');
callback(null,null);
}
});
}
...
|
cs |
모델 객체의 findById() 메소드를 호출할 때는 id 값과 콜백 함수를 전달한다.
콜백 함수에서 결과 데이터를 배열로 받으면 그 배열 객체에 데이터가 있는지 확인한다. 데이터가 있는 경우에는 첫 번째 배열 요소의 _doc 속성을 참조한다.
_doc 속성은 각 문서의 객체 정보를 담고 있어 그 안에 있는 password 속성 값을 확인할 수 있다.
findById() 메소드는 사용자의 아이디만으로 조회하는 메소드이기 때문에 비밀번호는 그 다음에 확인한다.
이번에는 사용자 리스트를 조회하는 메소드를 추가한다.
클라이언트에서는 /process/listuser로 요청하므로 이 패스를 라우팅하여 처리하는 함수를 추가한다.
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
|
...
router.route('/process/listuser').post(function(req,res){
console.log('/process/listuser 호출됨.');
//데이터베이스 객체가 초기화된 경우, 모델 객체의 findAll 메소드 호출
if(database){
// 1.모든 사용자 검색
UserModel.findAll(function(err,results){
// 오류가 발생했을 때, 클라이언트로 오류 전송
if(err){
console.error('사용자 리스트 조회 중 오류 발생 : ' + err.stack );
res.writeHead('200', {'Content-Type':'text/html;charset=utf8'});
res.write('<h2>사용자 리스트 조회 중 오류 발생</h2>');
res.write('<p>' + err.stack + '</p>');
res.end();
return;
}
// 결과 객체 있으면 리스트 전송
if(results){
console.dir(results);
res.writeHead('200',{'Content-Type':'text/html;charset=utf8'});
res.write('<h2>사용자 리스트</h2>');
res.write('<div><ul>');
for(var i=0; i < results.length; i++){
var curId = results[i]._doc.id;
var curName = results[i]._doc.name;
res.write(' <li>#' + i + ' : ' + curId + ', ' + curName + '</li>');
}
res.write('</ul></div>');
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();
}
});
...
|
cs |
이 함수 안에서는 모델 객체의 findAll() 함수를 호출하고 그 결과를 응답으로 전송한다.
서버 쪽에 사용자 리스트 기능을 추가했으니, 웹 브라우저에서 조회할 웹 문서를 [public] 폴더에 만든다.
listuser.html 파일을 만든 후 다음과 같이 웹 문서를 구성하는 코드를 입력한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>사용자 리스트 테스트</title>
</head>
<body>
<h1>사용자 리스트</h1>
<br>
<form method="post" action="/process/listuser">
<table>
<tr>
<td><label>아래 [전송] 버튼을 누르세요.</label></td>
</tr>
</table>
<input type="submit" value="전송" name="">
</form>
</body>
</html>
|
cs |
간단한 안내글과 함께 전송 버튼이 화면에 표시되는 웹 문서가 만들어진다.
[전송] 버튼을 누르면 POST 방식으로 서버에 등록해둔 /process/listuser 패스를 호출한다.
이제 app4.js 파일을 실행한 후, 웹 브라우저에서 localhost:3000/public/adduser.html 사이트에 접속한 후 사용자를 등록한다.
app4.js 파일에는 users2 컬렉션에 문서 데이터를 추가하도록 되어있으므로 아이디에 test01, 비밀번호 123456, 이름에 조커를 입력하고 전송버튼을 누른다. 그러면 데이터베이스에 데이터가 저장된다.
데이터를 성공적으로 저장한 후 데이터를 조회해보면 데이터가 들어간 것을 볼 수 있다.
users 컬렉션에 추가했던 문서 객체와 달리 users2 컬렉션 속성에는 인덱스가 더 많아진 것을 볼 수 있다.
속성 값 중에서는 created_at 과 updated_at 속성 값에는 현재 시간이 들어있다.
이제 새로 추가한 사용자리스트 기능을 확인해보자. 웹 브라우저에서 localhost:3000/public/listuser.html 사이트에 접속하면 화면을 확인할 수 있다.
[전송] 버튼을 누르면 서버의 데이터베이스에 저장된 사용자 리스트가 표시된다.
한 명만 등록되어있으므로 한 명의 사용자만 확인할 수 있다.
이제 사용자를 조회하는 기능까지 동작하니 사용자 정보를 관리하는 기본 기능은 어느 정도 만들었다.
'Theorem (정리) > node.js' 카테고리의 다른 글
(node.js) [Part.6] 데이터 베이스 사용하기 - MySQL 데이터베이스 사용하기 (0) | 2020.12.27 |
---|---|
(node.js) [Part.6] 데이터 베이스 사용하기 - 비밀번호 암호화하여 저장하기 (0) | 2020.12.23 |
(node.js) [Part.6] 데이터 베이스 사용하기 - 몽구스로 데이터베이스 다루기 (0) | 2020.12.18 |
(node.js) [Part.6] 데이터 베이스 사용하기 - 익스프레스에서 몽고디비 사용하기 (0) | 2020.12.18 |
(node.js) [Part.6] 데이터 베이스 사용하기 - 몽고디비 시작하기 (0) | 2020.12.18 |