생활 코딩 강의 목록 : https://opentutorials.org/module/2026/12063
인프런 강의 목록 : https://www.inflearn.com/course/node-js-활용/unit/3586?tab=curriculum
1. 강좌소개
서버측 자바스크립트 기술, Node.js 를 소개하고 사용법을 학습해 간단한 웹 어플리케이션을 만들어 보는 nodejs 강좌입니다. 기본 javascript 와 nodejs 를 이용하기 때문에 타 언어 (PHP 나 JSP) 의 도움없이 오직 javascript 기술로만 웹 어플리케이션을 구현할 수 있는 지식을 전달해줍니다. 앞선 두 강좌에서 학습한 내용과 실습예제들을 통합해 게시물과 로그인 기능이 있는 웹어플리케이션을 직접 만들어 볼수 있는 강좌입니다.
- 선수강좌가 2개 있습니다. 아래것을 먼저 학습하신후 본 강좌를 들으시면 좀더 이해가 쉬우실거에요.
- 자바스크립트의 기초적인 문법은 설명하지 않습니다. 여러 자바스크립트에 대한 다른 수업은 >>여기<< 에서 학습 가능하세요.
- 강의에서 사용하는 소스코드 링크 링크바로가기
소스 : https://github.com/braverokmc79/Take-Nodejs
프로젝트 준비
1) Take-Nodejs 디렉토리 생성
2) $ cd Take-Nodejs
3) $ express .
4) 넌적스 설치 및 vscode 툴에 Nunjucks Snippets 확장패키지 설치
$ npm i nunjucks --save
5)nodemon 설치 및 package.json 변경
"scripts": { "start": "node ./bin/www", "dev": "nodemon ./bin/www", "debug": "DEBUG=myapp:* yarn start" },
6)app.js 변경
var createError = require('http-errors'); var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan'); var indexRouter = require('./routes/index'); var usersRouter = require('./routes/users'); const nunjucks = require('nunjucks'); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); //app.set('view engine', 'jade'); app.set('view engine', 'html'); // 확장자를 html 로도 사용이 가능함. nunjucks.configure('views', { // views폴더가 넌적스파일의 위치가 됨 express: app, watch: true, }); ~
7)넌적스 레이아웃 만들기
view/layout.html
<!DOCTYPE html> <html lang="ko"> <head> <title>{{title}}</title> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title></title> <link rel="stylesheet" href="/stylesheets/style.css" /> </head> <body> <header> {% block header %} {% endblock %} </header> {% block content %} {% endblock %} <footer> {% block footer %} {% endblock %} </footer> </body> </html>
routes/index.js
var express = require('express'); var router = express.Router(); /* GET home page. */ // router.get('/', function (req, res, next) { // res.render('index', { title: 'Express' }); // }); router.get('/', function (req, res, next) { res.render('index', { title: 'Nunjucks' }); // index.html에 title이라는 변수를 전달 }); module.exports = router;
views/index.html
{% extends 'layout.html' %} {% block content %} <h1>{{title}}</h1> <p>Welcome to {{title}}</p> {% endblock %}
8)실행
$ npm run dev
https://mozilla.github.io/nunjucks/
https://mozilla.github.io/nunjucks/templating.html#sort-arr-reverse-casesens-attr
HTTP
1. Javascript 와 HTTP
cookie
2. cookie 1 – intro
3. cookie 2 – counter
app.js
~ var cookieRouter = require('./routes/cookies/index'); ~ app.use('/cookies', cookieRouter);
routes/cookies/index.js
var express = require('express'); var router = express.Router(); router.get('/count', function (req, res, next) { let count = 0; if (req.cookies.count) { count = Number(req.cookies.count); } count += 1; res.cookie("count", count); res.render('cookies/count', { count: count }); }); module.exports = router;
views/cookies/count.html
{% extends '../layout.html' %} {% block content %} count : {{count}} {% endblock %}
http://localhost:3000/cookies/count
4. cookie 3 - 쇼핑카트 1
routes/cookies/index.js
var express = require('express'); var router = express.Router(); router.get('/count', function (req, res, next) { let count = 0; if (req.cookies.count) count = Number(req.cookies.count); count += 1; res.cookie("count", count); res.render('cookies/count', { count: count }); }); const products = { 1: { title: 'The history of web' }, 2: { title: 'The next web' } } router.get("/products", function (req, res, next) { let output = '<ul>'; for (let item in products) { output += `<li> <a href="/cookies/cart/${item}">${products[item].title}</a> </li>`; } output += '</ul>'; res.render('cookies/proudcts', { output: output, products: products }); }); module.exports = router;
views/cookies/proudcts.html
{% extends '../layout.html' %} {% block content %} <h1>Products</h1> <div id="output"> {{output | safe}} </div> <a href="/cookies/cart">Cart</a> {% endblock %}
5. cookie 4 - 쇼핑카트 2
routes/cookies/index.js
const products = { 1: { title: 'The history of web' }, 2: { title: 'The next web' } } router.get("/cart/:id", function (req, res, next) { const id = req.params.id; let cart = {}; if (req.cookies.cart) { cart = req.cookies.cart; } if (!cart[id]) cart[id] = 0; cart[id] = parseInt(cart[id]) + 1; res.cookie('cart', cart); res.render("cookies/cart", { cart: cart }); })
views/cookies/cart.html
{% extends '../layout.html' %} {% block content %} {{cart | dump(2)}} {% endblock %}
6. cookie 5 - 쇼핑카트 3
routes/cookies/index.js
var express = require('express'); var router = express.Router(); router.get('/count', function (req, res, next) { let count = 0; if (req.cookies.count) count = Number(req.cookies.count); count += 1; res.cookie("count", count); res.render('cookies/count', { count: count }); }); const products = { 1: { title: 'The history of web' }, 2: { title: 'The next web' } } router.get("/products", function (req, res, next) { let output = '<ul>'; for (let item in products) { output += `<li> <a href="/cookies/cart/${item}">${products[item].title}</a> </li>`; } output += '</ul>'; res.render('cookies/proudcts', { output: output, products: products }); }); router.get("/cart", function (req, res, next) { const cart = req.cookies.cart; let output = ''; if (!cart) { res.send('Empty!'); } else { output = '<ul>'; for (let id in cart) { output += `<li>${products[id].title}(${cart[id]})</li>`; } output += "</ul>"; } res.render("cookies/cart", { output: output }); }); router.get("/cart/:id", function (req, res, next) { const id = req.params.id; let cart = {}; if (req.cookies.cart) { cart = req.cookies.cart; } if (!cart[id]) cart[id] = 0; cart[id] = parseInt(cart[id]) + 1; res.cookie('cart', cart); res.redirect('/cookies/cart'); }) module.exports = router;
views/cookies/cart.html
{% extends '../layout.html' %} {% block content %} <h1>장바구니</h1> {{output | safe}} <br> <a href="/cookies/products">Products List</a> {% endblock %}
7. cookie 6 – cookie & 보안
.
1) cookieParser 에 임의 암호문자 입력
app.use(cookieParser('3213e1da4523fa'));
2) 암호화 된 쿠키값 가져올때
예 ) req.signedCookies.count
3) 쿠키 암호화 저장하기
옵션으로 { signed: true }
res.cookie("count", count, { signed: true });
routes/cookies/index.js
var express = require('express'); var router = express.Router(); router.get('/count', function (req, res, next) { let count = 0; if (req.signedCookies.count) count = Number(req.signedCookies.count); count += 1; res.cookie("count", count, { signed: true }); res.render('cookies/count', { count: count }); }); const products = { 1: { title: 'The history of web' }, 2: { title: 'The next web' } } router.get("/products", function (req, res, next) { let output = '<ul>'; for (let item in products) { output += `<li> <a href="/cookies/cart/${item}">${products[item].title}</a> </li>`; } output += '</ul>'; res.render('cookies/proudcts', { output: output, products: products }); }); router.get("/cart", function (req, res, next) { const cart = req.signedCookies.cart; let output = ''; if (!cart) { res.send('Empty!'); } else { output = '<ul>'; for (let id in cart) { output += `<li>${products[id].title}(${cart[id]})</li>`; } output += "</ul>"; } res.render("cookies/cart", { output: output }); }); router.get("/cart/:id", function (req, res, next) { const id = req.params.id; let cart = {}; if (req.signedCookies.cart) { cart = req.signedCookies.cart; } if (!cart[id]) cart[id] = 0; cart[id] = parseInt(cart[id]) + 1; res.cookie('cart', cart, { signed: true }); res.redirect('/cookies/cart'); }) module.exports = router;
Session
8. session 1 - intro
9. session 2 - counter 1
10. session 3 - counter 2
설치
$npm i express-session
참조 :
https://www.npmjs.com/package/express-session
app.js
const session = require('express-session'); const sessionRouter = require('./routes/session/index'); const app = express(); app.use(session({ secret: 'keyboard cat', resave: false, saveUninitialized: true })) ~ app.use('/session', sessionRouter); ~
routes/session/index.js
const express = require('express'); const router = express.Router(); router.get('/count', function (req, res, next) { if (req.session.count) { req.session.count++; } else { req.session.count = 1; } res.render('session/count', { msg: req.session.count }); }); router.get('/tmp', function (req, res, next) { res.json("result : " + req.session.count); }) module.exports = router;
views/session/count.html
{% extends '../layout.html' %} {% block content %} {{msg}} <br> <a href="/session/tmp">tmp</a> {% endblock %}
11.session 4 - login 1
routes/session/index.js
const express = require('express'); const router = express.Router(); router.get('/count', function (req, res, next) { if (req.session.count) { req.session.count++; } else { req.session.count = 1; } res.render('session/count', { msg: req.session.count }); }); router.get('/tmp', function (req, res, next) { res.json("result : " + req.session.count); }) router.get('/auth/login', function (req, res, next) { res.render("session/login"); }); module.exports = router;
views/session/login.html
{% extends '../layout.html' %} {% block content %} <form action="/session/auth/login" method="post"> <p><input type="text" name="username" placeholder="username"></p> <p><input type="password" name="password" placeholder="password"></p> <p> <input type="submit"> </p> </form> {% endblock %}
12.session 5 - login 2
body-parser를 설치
npm install body-parser
모듈을 불러오고, express에 붙여 사용합니다.
const express = require('express') const app = express(); app.use(express.json()); app.use(bodyParser().json())app.post('/profile', function(req, res) => { console.log(req.body) })
routes/session/index.js
const express = require('express'); const router = express.Router(); router.get('/count', function (req, res, next) { if (req.session.count) { req.session.count++; } else { req.session.count = 1; } res.render('session/count', { msg: req.session.count }); }); router.get('/tmp', function (req, res, next) { res.json("result : " + req.session.count); }) router.get('/auth/login', function (req, res, next) { res.render("session/login"); }); router.post('/auth/login', function (req, res, next) { let user = { username: 'egoing', password: '1111' } const uname = req.body.username; const pwd = req.body.password; if (uname === user.username && pwd === user.password) { res.redirect("/session/welcome"); } else { res.render("session/login", { error: "아이디 또는 비밀번호가 일치하지 않습니다." }); } }) router.get('/welcome', function (req, res, next) { res.render("session/welcome"); }); module.exports = router;
views/session/login.html
{% extends '../layout.html' %} {% block content %} <h1>Login</h1> <span style="color:red">{{error}}</span> <form action="/session/auth/login" method="post"> <p><input type="text" name="username" placeholder="username"></p> <p><input type="password" name="password" placeholder="password"></p> <p> <input type="submit"> </p> </form> {% endblock %}
views/session/welcome.html
{% extends '../layout.html' %} {% block content %} <h1>Welcome</h1> {% endblock %}
13.session 6 - login 3
routes/session/index.js
~ router.get('/auth/login', function (req, res, next) { res.render("session/login"); }); router.post('/auth/login', function (req, res, next) { let user = { username: 'egoing', password: '1111', displayName: 'Egoing' } const uname = req.body.username; const pwd = req.body.password; if (uname === user.username && pwd === user.password) { //세션 저장 req.session.displayName = user.displayName; res.redirect("/session/welcome"); } else { res.render("session/login", { error: "아이디 또는 비밀번호가 일치하지 않습니다." }); } }) router.get('/welcome', function (req, res, next) { res.render("session/welcome", { session: req.session }); }); ~
views/session/welcome.html
{% extends '../layout.html' %} {% block content %} {% if session.displayName %} <h1>Hello, {{session.displayName}}</h1> <a href="/session/auth/logout">Logout</a> {% else %} <h1>Welcome</h1> <a href="/session/auth/login">Login</a> {% endif %} {% endblock %}
14.session 7 - login 4
로그아웃
router.get("/auth/logout", function (req, res, next) { delete req.session.displayName; res.redirect("/session/welcome"); }); ~
15.session 8 - session store-file
session-file-store
https://www.npmjs.com/package/session-file-store
npm install session-file-store
const express = require('express'); const app = express(); const session = require('express-session'); //세션관리용 미들웨어 const fileStore = require('session-file-store')(session); // session file store app.use(session({ secret: 'secret key', // 암호화 resave: false, saveUninitialized: true, cookie: { httpOnly: true, }, store: new fileStore() // 세션 객체에 세션스토어를 적용 })); app.get('/', (req, res, next) => { console.log(req.session); if(!req.session.num){ // 해당 세션키가 없다면 req.session.num = 1; // 세션 생성 } else { req.session.num = req.session.num + 1; } res.send(`Number : ${req.session.num}`); }); app.listen(3000, () => { console.log('listening 3000port'); });
app.js
const createError = require('http-errors'); const express = require('express'); const path = require('path'); const cookieParser = require('cookie-parser'); const logger = require('morgan'); const nunjucks = require('nunjucks'); const app = express(); const session = require('express-session'); const FileStore = require('session-file-store')(session); const indexRouter = require('./routes/index'); const usersRouter = require('./routes/users'); const cookieRouter = require('./routes/cookies/index'); const sessionRouter = require('./routes/session/index'); app.use(session({ secret: 'secret key', // 암호화 resave: false, saveUninitialized: true, cookie: { httpOnly: true, }, store: new FileStore() // 세션 객체에 세션스토어를 적용 })); ~
16.session 9 - session store-mysql
https://www.npmjs.com/package/express-mysql-session
1) mysql 설치
$npm i mysql
2) express-mysql-session 설치
$ npm i express-mysql-session
Usage
Use with your express session middleware, like this:
var express = require('express'); var app = module.exports = express(); var session = require('express-session'); var MySQLStore = require('express-mysql-session')(session); var options = { host: 'localhost', port: 3306, user: 'session_test', password: 'password', database: 'session_test' }; var sessionStore = new MySQLStore(options); app.use(session({ key: 'session_cookie_name', secret: 'session_cookie_secret', store: sessionStore, resave: false, saveUninitialized: false }));
3)테이블 생성 및 권한 부여
CREATE database opentutorials; CREATE USER `opentutorials`@`localhost` identified by '1111'; GRANT ALL privileges on opentutorials.* to `opentutorials`@`localhost` ;
4) mysql 접속 테스트
const mysql = require('mysql'); // 비밀번호는 별도의 파일로 분리해서 버전관리에 포함시키지 않아야 합니다. const connection = mysql.createConnection({ host: 'localhost', user: 'opentutorials', password: '1111', database: 'opentutorials' }); connection.connect(); console.log("connection.connect() ", connection);
실행
$ nodemon nodejs/mysql.js
5)적용
s'); const app = express(); const session = require('express-session'); const MySQLStore = require('express-mysql-session')(session); // session DB 저장 방식 - session 테이블이 자동 생성되고 세션이 passport의해 저장 된다. app.use(session({ secret: '12312dajfj23rj2po4$#%@#', resave: false, saveUninitialized: true, store: new MySQLStore({ host: 'localhost', port: 3306, user: 'opentutorials', password: '1111', database: 'opentutorials' }) }));
세션이 정상적으로 DB에 저장된 후 redirect 처리하기
router.get("/auth/logout", function (req, res, next) { delete req.session.displayName; req.session.save(function () { res.redirect("/session/welcome"); }) });
17.session 10 - session store- 몽고 DB
A. 몽고 DB 윈도우 설치 및 실행
[MongoDB] 몽고디비 GUI 개발/관리도구 Studio 3T 설치 (Robo 3T)
1) 윈도우 설치
Mongodb 설치Permalink
1. Mongodb 홈페이지 접속 후 다운로드Permalink
공식 홈페이지 : https://www.mongodb.com/try/download/community
원하는 버전 선택 후 msi 파일로 다운로드
2. 설치파일 실행Permalink
경로를 커스텀 하지 않았다면 C:\Program Files\MongoDB 경로에 설치가 됨.
(선택) 3. 환경변수 설정Permalink
선택사항. 매번 몽고DB 설치 경로(C:\Program Files\MongoDB)로 이동해서 명령어를 날려도 상관 없으면
스킵해도 상관 없음.
어느 경로에서나 몽고DB를 실행하고 싶다면 필요.
내 컴퓨터 -> 속성 -> 고급 시스템 설정 -> 환경 변수
Path 변수에 C:\Program Files\MongoDB\Server\ {버전} \bin 추가
4.명령 프롬프트(CMD) 창에서 Mongodb 실행 및 data/db 디렉토리 생성Permalink
실행 -> CMD
3의 환경변수 설정을 했다면 어떤 경로에서나 실행 가능
변수 설정 안했다면 mongodb 설치 경로로 가서 실행 가능
서버 실행Permalink
mongod
서버 접속Permalink
mongo
별 다른 작업 없이 mongod 명령어로 서버 실행 할 경우 아마 Exception이 발생 할 것이다.
내용은 Data 경로가 없다는 내용. 쉘에서 mkdir Data/db/ 생성해주든, 해당 경로가서 마우스 우클릭으로 새 폴더 생성해주던 상관 없음.
중요 : 실행 오류시
다음과 같이 디렉토리를 생성해 준다. C:\Data\db
5.확인 (웹브라우저)Permalink
웹브라우저에서 http://localhost:27017 접속
It looks like you are trying to access MongoDB over HTTP on the native driver port.
위와 같은 문구가 나온다면 정상.
Mongodb의 기본 포트는 27017
2 ) 몽고 DB 클라우드 설치 시
MongoDB 무료로 사용하기 - MongoDB Atlas
3) 몽고 DB 툴로 연결 할 경우
로컬일 경우 : mongodb://localhost:27017
클라우드일 경우 : mongodb+srv://macaronics:<password>@mongo-macaronics.y37mjuf.mongodb.net/test
몽고DB 연결 참조 : https://velog.io/@dev_cecy/NODE.JS-MONGO-DB-연동하기-FEAT.-EXPRESS-MONGOOSE
4) nodejs 몽고 DB 연결 라이브러리 설치
$ npm install mongoose
nodejs/mongodbURI.js
const mongodbURI = "mongodb+srv://macaronics:<password>@mongo-macaronics.y37mjuf.mongodb.net/test"; module.exports = mongodbURI;
nodejs/mongodb.js
const express = require('express') const app = express() const port = 5000 const mongodbURI = require('./mongodbURI') const mongoose = require("mongoose"); // MongoDB 연결 1 // '단' 하나의 데이터베이스 연결 시 유효. mongoose.connect( mongodbURI, // MongoDB url // { // useNewUrlParser: true, // useUnifiedTopology: true, // useCreateIndex: true, // useFindAndModify: false, // } // options // MongoDB 5 버전부터 useNewUrlParser 옵션을 사용해주지 않으면 에러가 뜹니다. //Mongoose 6 사용으로 에러 발생시. //useNewUrlParser, useUnifiedTopology, //useFindAndModify 및 useCreateIndex는 더 이상 지원되지 않는 옵션입니다. //Mongoose 6은 항상 useNewUrlParser, useUnifiedTopology 및 useCreateIndex가 true이고 // useFindAndModify가 false인 것처럼 작동합니다.코드에서 이러한 옵션을 제거하십시오. ).then(() => console.log("MongoDB Connected...")).catch(err => console.error("에러 :", err)); app.get('/', (req, res) => { res.send('Hello World! 안녕하세요.') }) app.listen(port, () => { console.log(`Example app listening on port ${port}`) });
연결 테스트 확인
$ node nodejs/mongodb.js
B. 몽고 DB Session Store 설정
connect-mongodb-session
https://www.npmjs.com/package/connect-mongodb-session
설치 :
$ npm i connect-mongodb-session
var express = require('express'); var session = require('express-session'); var MongoDBStore = require('connect-mongodb-session')(session); var app = express(); var store = new MongoDBStore({ uri: 'mongodb://localhost:27017/connect_mongodb_session_test', collection: 'mySessions' }); // Catch errors store.on('error', function(error) { console.log(error); }); app.use(require('express-session')({ secret: 'This is a secret', cookie: { maxAge: 1000 * 60 * 60 * 24 * 7 // 1 week }, store: store, // Boilerplate options, see: // * https://www.npmjs.com/package/express-session#resave // * https://www.npmjs.com/package/express-session#saveuninitialized resave: true, saveUninitialized: true })); app.get('/', function(req, res) { res.send('Hello ' + JSON.stringify(req.session)); }); server = app.listen(3000);
적용하기
app.js
const createError = require('http-errors'); const express = require('express'); const path = require('path'); const cookieParser = require('cookie-parser'); const logger = require('morgan'); const nunjucks = require('nunjucks'); const app = express(); const session = require('express-session'); const MySQLStore = require('express-mysql-session')(session); const MongoDBStore = require('connect-mongodb-session')(session); const FileStore = require('session-file-store')(session); const indexRouter = require('./routes/index'); const usersRouter = require('./routes/users'); const cookieRouter = require('./routes/cookies/index'); const sessionRouter = require('./routes/session/index'); // app.use(session({ // secret: 'secret key', // 암호화 // resave: false, // saveUninitialized: true, // cookie: { // httpOnly: true, // }, // //store: new FileStore() // 세션 객체에 세션스토어를 적용 // })); // session DB 저장 방식 - session 테이블이 자동 생성되고 세션이 passport의해 저장 된다. // app.use(session({ // secret: '12312dajfj23rj2po4$#%@#', // resave: false, // saveUninitialized: true, // store: new MySQLStore({ // host: 'localhost', // port: 3306, // user: 'opentutorials', // password: '1111', // database: 'opentutorials' // }) // })); //몽고 MongoDBStore 설정 app.use(session({ secret: '12312dajfj23rj2po4$#%@#', resave: false, saveUninitialized: true, store: new MongoDBStore({ uri: 'mongodb://localhost:27017/take-ndoejs', collection: 'sessionStore' }) }));
댓글 ( 4)
댓글 남기기