본문 바로가기

JS/NodeJS

Node JS로 단순 간단한 즐겨찾기 사이트 만들기 + MongoDB + 모듈화

app.js 파일에 DB 연동을 위한 스키마, 모델 그리고 라우터 등이 한꺼번에 있어서 모듈화를 한다.


사실 아직 익숙해지지 않아서 모듈화한 부분들이 어떤 흐름을 가지고 실행되는지 정확히는 모른다... 계속 공부해야함..


database----bookmark_schema.js //DB 스키마 설정

           |----database_loader.js //config.js에 있는 값들을 바탕으로 몽고DB 연결, 스키마, 모델 생성

public-------404.html //에러 페이지

        |------bookmark.html //메인 페이지,,,

routes-------bookmark.js //라우팅 경로에 맞는 함수 호출되게 함수 작성

        |------route_loader.js //config.js에 있는 라우터 설정 정보로 라우터 초기화

app.js //메인 파일

config.js //설정 파일

.... 



bookmark_schema.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var Schema={};
Schema.createSchema=function(mongoose){
    console.log('createSchema 호출됨');
    
    var BookmarkSchema=mongoose.Schema({
        bmurl:{type:String,required:true},
        bmname:{type:String},
        bmimage:{type:String}
    });
    console.log('bookmark schema 정의함');
    
    return BookmarkSchema;
}
 
module.exports=Schema;
cs


database_loader.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
var mongoose=require('mongoose');
var database={};
 
database.init=function(app,config){
    console.log('init 호출됨');
    connect(app,config);
};
 
function connect(app,config){
    console.log('connect 호출됨');
    
    mongoose.Promise=global.Promise;
    mongoose.connect(config.db_url,{useNewUrlParser:true});
    database.db=mongoose.connection;
    
    database.db.on('error',console.error.bind(console,'mongoose connection error'));
    database.db.on('open',function(){
        console.log('db에 연결됨:'+config.db_url);
        createSchema(app,config);
    });
    database.db.on('disconnected',function(){
        console.log('연결이 끊어짐 5초후 재 연결');
        setInterval(connectDB,5000);
    });
    
    //app.set('database',database);
}
 
function createSchema(app,config){
    var confLen=config.db_schemas.length;
    console.log('설정의 DB 스키마 수:'+confLen);
    for(var i=0;i<confLen;i++){
        var curItem=config.db_schemas[i];
        var curSchema=require(curItem.file).createSchema(mongoose);
        console.log('%s 모듈을 이용해 스키마 생성함.',curItem.file);
        var curModel=mongoose.model(curItem.collection,curSchema);
        console.log('%s 컬렉션을 위해 모델 정의함.',curItem.collection);
        
        database[curItem.schemaName]=curSchema;
        database[curItem.modelName]=curModel;
        console.log('스키마 [%s], 모델 [%s] 생성됨',curItem.schemaName, curItem.modelName);
    }
    app.set('database',database);//모듈 불러서 init하면 app 안에 database가 들어감
}
 
module.exports=database;
cs


bookmark.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
var path=require('path');
 
var addBookmark=function(database,bmurl,bmname,bmimage,callback){
    console.log('addBookmark 호출됨: '+bmurl+', '+bmname+', '+bmimage);
    var bm=new database.BookmarkModel({"bmurl":bmurl,"bmname":bmname,"bmimage":bmimage});
    bm.save(function(err){
        if(err){
            callback(err,null);
            return;
        }
        console.log('사이트 추가함');
        callback(null,bm);
    });
};
 
var siteViewer=function(database,callback){
    console.log('siteViewer 호출됨');
    database.BookmarkModel.find({},function(err,results){
        if(err){
            callback(err,null);
            return;
        }
        //console.log('즐겨찾기 검색 결과: ');
        //console.dir(results);
        if(results.length>0){
            console.log('즐겨찾기 찾음');
            callback(null,results);
        }else{
            console.log('즐겨찾기 못찾음');
            callback(null,null);
        }
    });
};
 
var images=function(req, res) {
    console.log('/process/bookmark 호출됨.'); //config.js의 설정과 route_loader에 의해 실행됨
    var database=req.app.get('database');
    try{
        var paramUrl=req.body.bookmarkUrl; //html 파일에서 입력된 input 값들
        var paramName=req.body.bookmarkName;
        var file=req.files; //요청된 파일
        var imgpath=file[0].path; //업로드할 이미지 경로
        console.log('file정보: ');
        console.log(file);
        console.log(imgpath);
        //console.dir('파일 정보: '+req.file[0]);
        console.log('요청 파라미터들:'+paramUrl+', '+paramName);
 
        
        if(database){
            addBookmark(database,paramUrl,paramName,imgpath,function(err,result){
                if(err) throw err;
                if(result){
                    console.dir(result);
                    res.writeHead('200',{'Content-Type':'text/html;charset=utf8'});
                    res.write('<h2>사이트 추가 성공</h2>');
                    res.write('<a href="/public/bookmark.html">즐겨찾기 추가 페이지로 돌아가기</a>');
                    res.end();
                }else{
                    res.writeHead('200',{'Content-Type':'text/html;charset=utf8'});
                    res.write('<h2>사이트 추가 실패</h2>');
                    console.dir(result);
                    res.end();
                }
            });
        }else{
            res.writeHead('200',{'Content-Type':'text/html;charset=utf8'});
            res.write('<h2>db 연결 실패</h2>');
            res.end();
        }
    }catch(err) {
        console.dir(err.stack);
    }            
};
 
var viewer=function(req,res){
    var database=req.app.get('database');
    console.log('즐겨찾기 보기, siteViewer() 호출');
    if(database){
        siteViewer(database,function(err,results){//즐겨찾기 찾으면 callback으로 results받아옴
            res.writeHead('200',{'Content-Type':'text/html;charset=utf8'});
            res.write('<h1>나의 즐겨찾기 보기</h1>');
            res.write('<table border=1><tr><th>즐겨찾기</th><th>이미지</th></tr>');
            
            for(var i=0;i<results.length;i++){
                res.write('<tr>');
                res.write('<td><a href="'+results[i].bmurl+'">'+results[i].bmname+'</a></td>'+
                          '<td><img width="80" height="80" src="../'+results[i].bmimage+'"/></td>');
                res.write('</tr>');
                console.log('이미지: ',results[i].bmimage);
            }
            res.write('</table>');
            res.end();
        });
    }
};
 
module.exports.images=images;
module.exports.viewer=viewer;
cs


route_loader.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
var route_loader={}; //route_loader 객체 생성
var config=require('../config'); //config 모듈 참조
// 파일 업로드용 미들웨어
var multer = require('multer'); //multipart/form-data를 다루기 위한 미들웨어, 주로 파일 업로딩에 쓰임, 다른 양식은 처리 안함
var fs = require('fs');
var static=require('serve-static');
var path=require('path');
 
//multer 미들웨어 사용 : 미들웨어 사용 순서 중요  body-parser -> multer -> router
// 파일 제한 : 10개, 1G
var storage = multer.diskStorage({ //storage 엔진은 파일을 디스크에 저장하는 걸 제어함
    destination: function (req, file, callback) {
        callback(null'uploads'//목적지:uploads 폴더에 파일 생김
    },
    filename: function (req, file, callback) {
        callback(null, file.originalname) //파일명
    }
});
 
var upload = multer({ //옵션들
    storage: storage, //파일이 저장될 장소
    limits: { //업로드될 데이터의 제한
        files: 10//파일 수?
        fileSize: 1024 * 1024 * 1024 //파일 용량 1GB
    }
});
 
route_loader.init=function(app,router){ //router_loader 초기화 함수, 메인에서 app객체와 router객체 넘겨줌
    console.log('route_loader.init 호출됨');
    initRoutes(app,router);
    app.use('/uploads', static(path.join(__dirname, 'uploads'))); //정적 파일 제공, 디렉토리 uploads에 있는 파일 제공, localhost://uploads/...
}
 
function initRoutes(app,router){ //사용자가 요청한 라우터 경로에 따라 함수 호출
    console.log('initRoutes 호출됨');
    var routeLen=config.route_info.length//라우터 정보의 개수
    for(var i=0;i<routeLen;i++){
        var curItem=config.route_info[i]; //i번째 라우터 정보
        var curModule=require(curItem.file); //i번째 라우터 정보의 파일 정보
        if(curItem.type=='get'){ //i번째 라우터 정보의 타입이 get이면
            router.route(curItem.path).get(curModule[curItem.method]); //라우팅 경로와 해당 경로로 요청이 왔을 때의 함수 이름 지정
        }else if(curItem.type=='post'){
            if(curItem.method=='images'){ //이미지 저장하는 함수인 경우
                router.route(curItem.path).post(upload.array('bookmarkImg',1),curModule[curItem.method]);
            }else{
                router.route(curItem.path).post(curModule[curItem.method]);
            }
        }else{
            console.error('라우팅 함수 타입 알 수 없음'+curItem.type);
        }
    }
    app.use('/',router); // 루트에 router 마운트
}
module.exports=route_loader;
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
/*
기능 추가 : routes폴더에 파일 생성 후 함수 추가 -> config.js의 route_info에 객체 추가
*/
 
// 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');
 
//클라이언트에서 ajax로 요청 시 CORS(다중 서버 접속) 지원
var cors = require('cors');
 
// 익스프레스 객체 생성
var app = express();
 
var config=require('./config');
console.log('config.server_port->'+config.server_port);
 
var database_loader=require('./database/database_loader');
var route_loader=require('./routes/route_loader');
 
// 기본 속성 설정
app.set('port', config.server_port);
 
// body-parser를 이용해 application/x-www-form-urlencoded 파싱
app.use(bodyParser.urlencoded({ extended: false }))
 
// body-parser를 이용해 application/json 파싱
app.use(bodyParser.json())
 
// public 폴더와 uploads 폴더 오픈
app.use('/public', static(path.join(__dirname, 'public')));
app.use('/uploads', static(path.join(__dirname, 'uploads')));
 
// cookie-parser 설정
app.use(cookieParser());
 
// 세션 설정
app.use(expressSession({
    secret:'my key',
    resave:true,
    saveUninitialized:true
}));
 
//클라이언트에서 ajax로 요청 시 CORS(다중 서버 접속) 지원
app.use(cors());
 
route_loader.init(app,express.Router()); //app, 라우터 모듈 전달
 
// 404 에러 페이지 처리
var errorHandler = expressErrorHandler({
    static: {
      '404''./public/404.html'
    }
});
 
app.use( expressErrorHandler.httpError(404) );
app.use( errorHandler );
 
// Express 서버 시작
http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
    database_loader.init(app,config);//database_loader파일에서 한번에 로딩, 스키마는 config 파일에
});
cs


config.js

1
2
3
4
5
6
7
8
9
10
11
module.exports={
    server_port:3000,
    db_url:'mongodb://localhost:27017/local',
    db_schemas:[
        {file:'./bookmark_schema',collection:'bookmark0',schemaName:'BookmarkSchema',modelName:'BookmarkModel'}
    ],
    route_info:[
        {file:'./bookmark',path:'/process/bookmark',method:'images',type:'post'},
        {file:'./bookmark',path:'/process/siteview',method:'viewer',type:'post'}
    ]
};
cs



출처 Do it Node.js + 직접 수정