ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Node.js & MySQL] main.js 정리 - DB접속 정보/쿼리 분리
    생활코딩/WEBn 2021. 1. 12. 02:08

    main.js에 실제 실행 부분의 코드가 포함되어 있으면 복잡해져서 전체맥락을 파악하기 쉽지 않다.

    main.js는 index, 목차처럼 사용하는 것이 바람직하고, 그렇게 하기 위해서는 구체적인 정보들의 분리가 필요하다.

     

    먼저 DB접속 정보를 분리했다.

     

    data/lib/db.js 파일 생성 후 접속 정보를 가져온다.

    var mysql = require('mysql');
    
    var db = mysql.createConnection({
    	  host     : 'localhost',
    	  user     : 'root',
    	  password : 'password',
    	  database : 'data'
    	})
    db.connect();
    module.exports = db;   // 외부에서 임포트할 모듈이 하나라면 이렇게 하면 된다

     

    main.js에서는 해당 부분을 삭제하고, main.js에서는 mysql 모듈을 다룰 일이 없으니 require 부분을 삭제해서

    해당 스크립트 내에서 쓰이는 모듈만 임포트되도록 한다. (임포트한 모듈에서 다시 임포트한 모듈은 거기서만 임포트하면 된다.)

     

    *실제로 아이디/패스워드 같은 데이터는 소스코드에서 아예 분리해서 관리하는 편이 좋다.

    아래처럼 탬플릿 파일을 만들어두고, 위의 db.js는 버전관리에서 제외하면 된다.

     

    data/lib/db.template.js

    var mysql = require('mysql');
    
    var db = mysql.createConnection({
    	  host     : '',
    	  user     : '',
    	  password : '',
    	  database : ''
    	})
    db.connect();
    module.exports = db;

     

     

    DB접속 정보를 분리했으니 이제 쿼리문을 다루는 부분을 분리한다.

     

    기존 페이지는 유저가 특정 데이터 페이지를 요청하면 해당 데이터가 데이터베이스에 있는지 여부를 확인하고,

    있는 페이지면 상세페이지를 출력해주는 구조였다.

    여부확인에 1번, 상세페이지 출력에 1번 해서 쿼리문이 총 2번 사용되어서 쿼리1(callback{ 쿼리2 }) 형태로 구성했었다.

     

    그대로 옮기자니 한 덩어리도 커지고 가독성이 떨어져서 dataMenu라는 함수로 분리하고,

    데이터 존재 여부를 파악해야 하는 경우, 해당 함수 내에서 dataMenu를 불러와서 처리했다.

    콜백구조인 것은 똑같지만 가독성은 약간 개선된 듯하다!

     

    // 데이터 목록 조회용
    var dataMenu = function(topicId, request, response, callback){
    	db.query('SELECT id, title FROM topic', function(err, result){
          var dataList = [];
    	  var dataNameList = [];
    	  for (var data of result){
    		  if (data.id !== 0){
    		      dataList.push(String(data.id));
    		      dataNameList.push(data.title);  
    		  };
    	  };
    	  callback(dataList, dataNameList);
    	});
    }
    
    
    exports.page = function(topicId, request, response){
    	dataMenu(topicId, request, response, function(dataList, dataNameList){
    		  if(dataList.includes(topicId) || topicId === undefined){  // 홈or데이터 있는 페이지인지
    			  if(topicId === undefined){  // 홈이면 아이디 0 부여
    				  topicId = 0;
    			  }
    		    db.query('SELECT * FROM topic WHERE id = ', [topicId], function(err, result){
    		      var template = templates.get(topicId, result[0], dataList, dataNameList);
    		      response.writeHead(200);
    		      response.end(template);
    		    });
    		  } else {
    	          response_fmt.notFound(response);
    		      return 0;
    		  }
    	});
    }

     

    main.js의 원래 해당 코드 자리에는 topic.page(topicId, request, response)를 넣어주면 된다.

    이런 식으로 대부분의 코드를 전부 옮기고 나니, main.js 파일의 if 부분들이 훨씬 심플해졌다.

    이 구성에서 필요하지 않은 모듈은 임포트하지 않고, 필요하면 topic에서 따로 불러다가 쓰면 된다.

    var http = require('http');
    var url = require('url');
    var path = require('path');
    var topic = require('./data/lib/topic');
    
    
    var app = http.createServer(function(request, response){
        var _url = request.url;
        var topicId = url.parse(_url, true).query.id;
        if (topicId !== undefined){
          topicId = path.parse(topicId).base;
        };
        var pathname = url.parse(_url, true).pathname;
        var ext = '';
        if(pathname.indexOf('.') > -1){
          ext = pathname.split('.').splice(-1)[0];
        };
    
        if(ext){    // 확장자가 있으면: html이 아니면
            if(0 <= ['css', 'js'].indexOf(ext)){
                topic.response_fmt.sendContent(response, ext, pathname);
            } else {  // 확인불가
                topic.response_fmt.notFound(response);
            }
        } else {    // html이면
            if (pathname === "/"){  // 홈 요청이면
    		    topic.page(topicId, request, response);  // id 조회 가능하면 해당 페이지, 아니면 404
            } else if (pathname === "/create"){
    			topic.create(topicId, request, response);
    		} else if (pathname === "/update"){  // 편집페이지면
    			topic.update(topicId, request, response);
            } else if (pathname === "/process_create"){ // 처리과정이면
    			topic.process_create(topicId, request, response);
    		} else if (pathname === "/process_update"){
    			topic.process_update(topicId, request, response);
    		} else if (pathname === "/process_delete") {
    			topic.process_delete(topicId, request, response);
    		} else if (pathname === "/process_undo") {
    			topic.process_undo(topicId, request, response);
    		} else {
                topic.response_fmt.notFound(response);
            }
          }
    });
    app.listen(3000);
    

     

    *탬플릿이나 css 같은 경우도 main.js 기준으로 구성되어 있어서, 기능을 담당하는 코드들을 topic으로 옮기게 되면

    파일 경로를 지정하는 부분도 마찬가지로 수정해주어야 한다.

     

    댓글

Designed by Tistory.