728x90
반응형

JQuery를 1년간 개발한 결과 결국 제일 중요한 것은 Ajax와 Object인 것을 깨달았다. 이는 React에선 Axios, State(리액트 훅)으로 이어지며, JQuery를 나름 심도있게 개발하니 React도 이해하기가 쉬웠다.

기억하자 JQuery는 Object와 Ajax가 제일 중요하고 쓸모있다!

 

화면 구성

구성한 테이블의 화면이다. 주요 기능들 위주로 설명하겠다.

 

728x90
반응형
728x90
반응형

i18n은 다국어 지원을 가능하게 해주는 모듈이다. JQuery 와 React에서 쓰이는 방법이 다르며, React에서 쓰이는 방법은 

차후에 올리도록 하겠다. 

 

1. 먼저 i18n을 설치한다.

sudo npm i i18n

 

2. 최상 루트폴더 밑에 i18n.js를 만들어준다.

 

i18n.js

const i18n = require('i18n');

i18n.configure({
    locales: ['ko', 'en'],
    directory: __dirname + '/locales',
    defaultLocale: 'ko',
    cookie: 'lang',
});

module.exports = function(req, res, next) {
    i18n.init(req, res);
    res.locals.__ = res.__;
    var current_locale = i18n.getLocale();
    return next();
};

코드를 보면 /locales 파일 밑에 ko, en 파일들을 쓴다고 되어있다. 

defaultLocale인 ko(한국어)가 최초의 값으로 되어있고, 위에 사진처럼 다른언어를 클릭할 시에 페이지 내에

텍스트들이 바뀌는것을 확인 할 수 있다.

 

3.  최상 루트폴더 밑에 locales 폴더를 만들고, 하위에 ko.json, en.json파일들을 만들어 준다.

 

ko.json

{
	"" : "",
	"lang_kr": "한국어 (기본)",
	"lang_en": "영어",
}

 

en.json

{
	"" : "",
    "lang_kr": "Korean (Basic)",
	"lang_en": "English"
}

 

해당 모듈은 json형식을 완벽하게 따라해야되기 때문에 마지막 value 값 뒤 ,(콤마)를 붙이는 실수를 하면 안된다.

(나중에 큰 고생을 합니다..ㅜㅜ) 두 개의 파일의 순서도 똑같이 해줘야 한다.

 

4. app.js에 i18n을 설정해준다.

const i18n = require('./i18n');

app.use(i18n);

 

5. 클라이언트에서 버튼을 생성해준다

<div class="dropdown-menu dropdown-menu-right">
	<a href="/ko" class="dropdown-item d-flex justify-content-start align-items-center"><img class="flag" src="https://lipis.github.io/flag-icon-css/flags/4x3/kr.svg" alt="South Korea Flag">{{__('lang_kr')}}</a>
	<a href="/en" class="dropdown-item d-flex justify-content-start align-items-center"><img class="flag" src="https://lipis.github.io/flag-icon-css/flags/4x3/us.svg" alt="United States of America Flag">{{__('lang_en')}}</a>
</div>

 

6. 백엔드(node.js)라우터에서 쿠키설정을 해줍니다.

router.get('/en', function(req, res) {
  res.cookie('lang', 'en');
  res.redirect('/main');
});

router.get('/ko', function(req, res) {
  res.cookie('lang', 'ko');
  res.redirect('/main');
});

 

그럼 모든 설정을 끝이 났다. 

사용하는 방법은 아래와같다.

<button type="button">{{__('close')}}</button>

{{__('이곳')}} 에 json파일들로 설정한 이름들을 넣어주면 get메소드가 실행될 때마다 언어를 바꿔줄 수 있다.

 

노가다지만 나중에 다국어를 한다 생각해보면 필요성이 있는 모듈이었다.

728x90
반응형
728x90
반응형

전 글에서 schemas 파일까지 다루어보았다.

이번 글에선 대망의query.js를 다루어보겠다.

 

1. 전체코드 

const mongoose = require('mongoose');
const { Schema } = mongoose; 

const { WORKER, COLLECTION_NAME, QUERY } = require('../const/consts'); //consts 파일들
      
const Schemas = require('./schemas')

const { Worker } = Schemas; // 몽구스 model 파일들

exports.modelQuery = async (query,collection,doc,option) => {
    var doc = doc;
    
    var Collection = Schemas[collection];
    
    // console.log(Collection.prototype.schema.options.collection);
    
    var option = option;
    var one;
    var postJob; // 임의로 지정해줄 수도 있고, option으로 받아올 수도 있음 (부가적인 함수)
    
    if(option.postJob) {
        postJob = option.postJob;
    }
    
    var resResult = (result) => { //함수가 끝나고 실행되는 콜백함수
      if (postJob != null) {
         postJob();
      }
      return result;
    };
    
    
    if ( query == QUERY.Aggregate) {
        var aggregatearray = [];
        
        switch (collection) {
            case COLLECTION_NAME.Alarm : 
                break;
            case COLLECTION_NAME.Car :
                break;
        }
        
        if(doc != undefined) {
            if (doc.addFields) {
                aggregatearray.push({$addFields : doc.addFields});
            }
            if (doc.lookup) {
                aggregatearray.push({$lookup : doc.lookup});
            }
            if (doc.unwind) {
                aggregatearray.push({$unwind : doc.unwind});
            }
            if (doc.match) {
                aggregatearray.push({$match : doc.match});
            }
            if (doc.project) {
                aggregatearray.push({$project : doc.project});
            }
            if (doc.sort) {
                aggregatearray.push({$sort : doc.sort});
            }
            if (doc.limit) {
                aggregatearray.push({$limit : doc.limit});
            }
        }
        if (Object.keys(option).length != 0) {
            if (option.limit) {
                
            }
            if (option.sort) {
                
            }
        }
        else {
            var one = await Collection.aggregate([aggregatearray]).then(resResult);
        }
        
        return one;
        
    }
};

 

원래는 각 쿼리별 조건문이 다 들어있으나, 결국 방식은 비슷하기 때문에 mongoose의 쿼리문인 aggregate만 예시로 들었다. 방식은 전에 정의해두었던 consts 파일에서 사용할 schema(열거체)와 query, collection_name를 가져오고 모델을 미리 정의해두었던 schema(모델)을 가져온다.

 

그 다음 modelquery 함수를 정의하고, 인자 값을 query, collection, doc, option을 설정해서 어떤 스키마, 어떤 쿼리, 어떤 데이터가 들어오든 쿼리가 실행이 가능하도록 한다.

 

실제로 라우터에선

//Schemas
const {modelQuery} = require('../schemas/query')
const {COLLECTION_NAME, QUERY} = require('../const/consts');

 

이 것만 위에 선언을 해주고

const agents = await modelQuery(QUERY.Findone,COLLECTION_NAME.Company,{ "CNU" : CNU+"000" },{});

 

이방식대로 써주면 JQuery 뿐만 아니라 React.js_node.js(Back-end), Graphql에서도 활용이 가능하다.

NoSQL이 아닌 SQL 또한 node js sequelize를 사용 할 때 모델을 지정해주는 방법만 바꿔주면 활용이 가능하다.

 

이 방법이 성공했을 때 진심으로 전율을 느꼈다..

728x90
반응형

'DB > MongoDB' 카테고리의 다른 글

MongoDB | Schemas(2)  (0) 2021.09.14
MongoDB | Schemas(1)  (0) 2021.09.14
MongoDB | Consts 만들기  (0) 2021.09.14
MongoDB | 설치하기, 삭제하기  (0) 2021.09.14
728x90
반응형

전 글에서 index.js까지 만들어보았다.

이번 글에서는 schemas.js를 다루어보겠다.

 

1. schemas.js

const mongoose = require('mongoose');

const {  WORKER } = require('../const/consts');

const { Schema } = mongoose;


const workerSchema = new Schema(WORKER.schema, { collection: 'Worker' });

const Worker = mongoose.model('Worker',workerSchema);


const COLLECTIONS = {
    "Worker" : Worker
}

module.exports = COLLECTIONS;

 

먼저 mongoose를 require 해주고, 

기존에 consts에 만들어놨던 WORKER를 가져온다.(schema를 쓰기위해)

 

그다음 mongoose에서 Schema를 가져오고,

 

해당 스키마의 인스턴스를 만들어준다 ( collection 네임과 const 안의 collection_name이 동일해야 합니다. )

 

그다음 Worker라는 모델을 생성해준 후

나중에 query.js에서 쓰기위해 COLLECTIONS에 담아주고 exports 해줍니다. 

728x90
반응형

'DB > MongoDB' 카테고리의 다른 글

MongoDB | Schemas(3)  (0) 2021.09.14
MongoDB | Schemas(1)  (0) 2021.09.14
MongoDB | Consts 만들기  (0) 2021.09.14
MongoDB | 설치하기, 삭제하기  (0) 2021.09.14
728x90
반응형

먼저 이 모듈화를 시작하게 된 계기는 라우터마다 사용할 스키마를 가져오는것이 불편하다 느꼈고, 이를 어떤 상황이라도 모든 쿼리문이 모든 스키마에 적용되도록 설계를 해보게 되었다.

이 방식을 쓰면 모든 라우터에 

//Schemas
const {modelQuery} = require('../schemas/query')
const {COLLECTION_NAME, QUERY} = require('../const/consts');

이와같이 두줄만 쓰면 모든 쿼리문을 사용가능하다. 또한 스키마별로 파일을 생성하지 않아도 되며, 라우터에서 쓰일 열거체들은  const에 스키마와 같이 정의하여 훨씬 깔끔하게 mongo query를 사용할 수 있다.

 

먼저 mongoose를 설치하고, express파일에서 connect를 실행하게끔 하고  index.js파일부터 정의해보자.

sudo npm i mongoose

 

1. 파일 구조

/root
└schemas
 └index.js
 └query.js
 └schemas.js

 

2. index.js

require('dotenv').config();
const mongoose = require('mongoose');

const connect = () => {
    // const mongoCon = 'mongodb://test:test1234@18.140.74.102:9003/admin';
    const mongoCon = 'mongodb://'+process.env.MONGO_ID+':'+process.env.MONGO_PWD+'@'+process.env.MONGO_IP+':'+process.env.MONGO_PORT+'/admin';
    
    if (process.env.NODE_ENV !== 'production') {
        mongoose.set('debug', true);
    }
    mongoose.connect(mongoCon, {dbName: 'OASIS'}, {
    }, (error) => {
        if (error) {
            console.log('DB Connection is Error', error);
        }
        else {
            console.log('DB Connect is SuccessFul!');
        }
    });
};
mongoose.connection.on('error', (error) => {
    console.error('DB Error', error);
});
mongoose.connection.on('disconnected', () => {
    console.error('DB is disconnected, Continue to Connect DB');
    connect();
});

module.exports = connect;

mongoDB에 관한 내용들은 env파일에 담아두었다.

728x90
반응형

'DB > MongoDB' 카테고리의 다른 글

MongoDB | Schemas(3)  (0) 2021.09.14
MongoDB | Schemas(2)  (0) 2021.09.14
MongoDB | Consts 만들기  (0) 2021.09.14
MongoDB | 설치하기, 삭제하기  (0) 2021.09.14
728x90
반응형

1. 파일구조

/root
└const
 └consts.js
 └collection_name.js
 └query.js
 └worker.js

 

2. worker.js - 라우터에서 쓰일 열거체와, mongoose에서 쓰일 schema를 정의한다.

const WORKER = {
    "CNU" : "CNU",
    "WN" : "WN",
    "PN" : "PN",
    "GID" : "GID",
    "EM" : "EM",
    "PU" : "PU",
    "CA" : "CA",
    "UA" : "UA",
    
    schema : {
        CNU: { // Company Number
            type: String,
            required: true,
        },
        WN: { // Worker Name
            type: String,
            required: true,
        },
        PN: { // Phone Number
            type: String,
            unique: true,
        },
        GID:{   // Google Account ID
          type: String,
        },
        EM: { // Email
            type: String,
            unique: true,
            required: true,
        },
        PU: { // Photo URL
            type: String,
        },
        CA: { // Created At
            type: Date,
            default: Date.now,
        },
        UA: { // Updated At
            type: Date,
            default: Date.now,
        }
    }
}

exports.WORKER = WORKER;

 

3. query.js - modelquery 함수에서 쓰일 query문 열거체들을 정리한다.

const QUERY = {
    
    Aggregate : "aggregate",
    Create : "create",
    InsertMany : "insertmany",
    Find : "find",
    Findone : "findone",
    Update : "update",
    Updatemany : "updatemany",
    Updateone : "updateone",
    Updateupsert : "updateupsert",
    Remove : "remove",
    Count : "count",
    CountDoc : "countdoc",
    Distinct : "distinct"
    
};

exports.QUERY = QUERY;

 

4. collection_name.js - 사용할 collection 이름들을 정리한다.

const COLLECTION_NAME = {
    "Worker" : "Worker"
}

exports.COLLECTION_NAME = COLLECTION_NAME;

 

5. consts.js - 한곳에서 import 하기위해 위에 모든 것들을 담는 js파일을 만들어준다.

const {WORKER} = require('../const/worker');
const {COLLECTION_NAME} = require('../const/collection_name');
const {QUERY} = require('../const/query');


exports.WORKER = WORKER;
exports.COLLECTION_NAME = COLLECTION_NAME;
exports.QUERY = QUERY;
728x90
반응형

'DB > MongoDB' 카테고리의 다른 글

MongoDB | Schemas(3)  (0) 2021.09.14
MongoDB | Schemas(2)  (0) 2021.09.14
MongoDB | Schemas(1)  (0) 2021.09.14
MongoDB | 설치하기, 삭제하기  (0) 2021.09.14
728x90
반응형

1.     몽고DB의 public GPG key 주입

ubuntu@dev:~$ wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -

OK

 

2.     몽고DB를 위한 리스트 파일 생성

ubuntu@dev:~$ echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.4.list

 

 

3.     로컬 패키지 데이터베이스 갱신

ubuntu@dev:~$ sudo apt-get update

 

 

4.     몽고DB 설치

ubuntu@dev:~$ sudo apt-get install -y mongodb-org

 

 

5.     몽고 서비스 실행

ubuntu@dev:~$ sudo service mongod start

 

6. 관리자 계정 추가

MongoDB에 다시 접속하여 관리자 계정을 추가한다.

 

$ mongo

 

>use admin

db.createUser({            

    user: “유저아이디" ,            

    pwd: “패스워드",            

    roles: [‘root’]

})

 

uncaught exception: Error: couldn't add user: command createUser requires authentication :

해당 오류가 뜬다면 이는 /etc/mongod.conf에서 security.authorization이 true로 설정되어 있기 때문이었다.
책에서 사용하던 버전에서는 원래 주석처리되어 있었는지 이후에 추가하도록 되어있는데, 이번에 설치한 4.2.9 버전에서는 처음부터 작성되어 설치되어서 문제가 되었다.

잠깐 주석 처리하고 sudo service mongod restart하니 정상적으로 admin 사용자를 추가할 수 있었다

 

 

 

7. 인증 설정

MongoDB에 접속할 때 인증과정이 이루어지도록 설정파일을 수정한다.

우선 MongoDB를 종료한 후 수정을 한다.

ubuntu@dev:~$ sudo service mongod stop

ubuntu@dev:~$ sudo vim /etc/mongod.conf

 

mongod.conf 설정파일의 security 항목의 주석을 해제한 후 그 하단에 authorization: enabled 를 추가한다.

security:

  authorization: enabled

 

8. 인증 접속

MongoDB를 다시 실행한 후 등록한 계정 정보로 접속을 시도해 보자.

ubuntu@dev:~$ sudo service mongod start

ubuntu@dev:~$ mongo admin -u test -p test1234

 

 

9. 외부 접속 설정

MongoDB는 기본적으로 로컬호스트에서만 접속이 가능하도록 설정되어 있다. 외부 접속을 위해서는 net 항목의 bindIp 항목을 0.0.0.0으로 변경한다. (포트도 변경 가능)

net:

  port: 27017

  bindIp: 0.0.0.0

 

10. 몽고 DB 삭제 방법

sudo apt-get remove mongodb-org

sudo apt-get purge mongodb-org*

sudo rm -rf /var/log/mongodb

sudo rm -rf /var/lib/mongodb
728x90
반응형

'DB > MongoDB' 카테고리의 다른 글

MongoDB | Schemas(3)  (0) 2021.09.14
MongoDB | Schemas(2)  (0) 2021.09.14
MongoDB | Schemas(1)  (0) 2021.09.14
MongoDB | Consts 만들기  (0) 2021.09.14
728x90
반응형

1. 먼저 화면 구성을 해준다. 버튼을 눌렀을 경우 onclick으로 함수가 실행되도록 한다.(로그아웃도 동일)

 

 

2. HTML script - get메소드를 쓰기 때문에 location 을 바꿔주어서 백엔드에서 로직이 실행되도록 한다.

// 회원탈퇴 기능
function withdrawal(i18nconvert) {
	var answer;
	//페이지를 이동하기 전에 confirm()을 사용해 다시 한번 확인한다.
	//확인을 선택하면 answer에  true, 취소를 선택하면 false 값이 들어간다.
	answer = confirm(i18nconvert("layout_withdrawal_confirm"));
	//확인을 선택한 경우 자바스크립트를 호출할 때 같이 넘어온 url이라는 변수에 들어있는 주소로 페이지 이동
	if(answer == true){
		location = '/auth/withdrawal';
	}
	else {
		return false;
	}
}

// 로그아웃 기능
function logout(i18nconvert) {
	var answer;
	//페이지를 이동하기 전에 confirm()을 사용해 다시 한번 확인한다.
	//확인을 선택하면 answer에  true, 취소를 선택하면 false 값이 들어간다.
	answer = confirm(i18nconvert("layout_signout_confirm"));
	//확인을 선택한 경우 자바스크립트를 호출할 때 같이 넘어온 url이라는 변수에 들어있는 주소로 페이지 이동
	if(answer == true){
		location = '/auth/logout';
	}
	else {
		return false;
	}
}

 

 

3. 백엔드쪽에서 로그아웃은 쿠키가 삭제되도록, 회원탈퇴는 DB에서 데이터가 삭제되도록 한다.

//logout시 Browser Cookie 삭제
router.get("/logout", async function( req, res, next){
  try {
    await res.cookie("token", req.cookies,{expiresIn:0});
    res.redirect("/");
  } catch(err){
    console.error(err);
    next(err);
  }
});

//withdrawal시 Browser Cookie 삭제 하고 소독이력을 제외한 company에 관련된 내용들 삭제
router.get("/withdrawal", isNotLoggedIn, async function(req, res, next){
  const CID = req.decoded.CID;
  const CNU = req.decoded.CNU;
  
  try {
    await modelQuery(QUERY.Remove,COLLECTION_NAME.Company,{"_id": CID},{});
    await modelQuery(QUERY.Remove,COLLECTION_NAME.Car,{"CNU": CNU},{});
    await modelQuery(QUERY.Remove,COLLECTION_NAME.Device,{"CNU": CNU},{});
    await modelQuery(QUERY.Remove,COLLECTION_NAME.Worker,{"CNU": CNU},{});

    await res.cookie("token", req.cookies, { expiresIn : 0 });
    
    res.redirect("/");

  } catch(err){
    console.error(err);
    next(err);
  }
});
728x90
반응형
728x90
반응형

1. 먼저 nunjucks를 설치해준다.

npm install nunjucks

 

2. express와 nunjucks를 연결해준다.

// app.js
const express = require('express');
const app = express();

app.set('port', process.env.PORT || 3000);
app.set('view engine', 'html')
nunjucks.configure('views', {
  express: app, 
  watch: true, 
});

const indexRouter = require('./routes/index');
app.use('/', indexRouter);

 

3. 라우터에 사용할 변수를 페이지에 렌더링해준다.

const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.locals.title = 'Express'
  res.render('index')
});

module.exports = router;

 

4. 최상위 html 파일에 넌적스 변수를 선언해준다.

// layout.html
<!DOCTYPE html>
<html>
  <head>
    <title>{{title}}</title>
    <link rel="stylesheet" href="/style.css" />
  </head>
  <body>
    {% block content %}
    {% endblock %}
  </body>
</html>

// index.html
{% extends 'layout.html' %}

{% block content %}
<h1>{{title}}</h1>
<p>Welcome to {{title}}</p>
{% endblock %}

 

 

이렇게 하면 백엔드에서 넘겨준 변수를 html에서 쓸 수 있다. {{ }} 이걸로 변수를 감싸주면 끝!

{% %} 이런 형식으로 변수를 이용한 반복문, 또다른 변수선언 등을 할 수도 있다.

728x90
반응형
728x90
반응형

※ 지점, 본사는 무시하셔도 됩니다.

 

먼저 사업자등록번호(아이디)를 입력한 후 존재하면 해당 정보에 등록된 이메일 주소가 일부 가려진 채로

나오게 되고 (혹시나 이메일 주소를 잊었을 경우), 이메일 주소를 입력하고 버튼을 누르면 전송이 되게끔 하였다.

(이메일 보내기는 회원가입 글을 확인 부탁드립니다) 이후에 이메일을 보내는 부분은 회원가입을 했을 경우랑 같고, 

바뀐 임의의 비밀번호를 이메일 주소로 보내게끔 하였으며, 사이트 내에 프로필 수정 화면을 통해 비밀번호를

변경할 수 있도록 했다.

728x90
반응형

+ Recent posts