서버 측 자바스크립트와 Nodejs
내용정리
NodeJs
Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임
확장성있는 네트워크 애플리케이션 구축
구글의 V8 엔진을 자바스크립트 엔진으로 사용 + event-driven 자바스크립트 개발방식 + non blocking IO 입출력 처리
웹브라우저가 아닌 서버쪽에서도 동작하는 자바스크립트로 확장
연결성 javscript & nodejs
FS, HTTP, OS 등 nodejs가 기본적으로 제공하는 기능들을 자바스크립트 프로그래밍 언어의 문법에 맞게 의도하는 바에 해당되는 프로그램을 만든다.
Module NPM
Module : 부품으로 사용될 작은 프로그램들
ex) Express, Underscore, Jade
NPM을 통해 애플리케이션에 담아서 다양한 애플리케이션을 만들 수 있다.
Router & Controller (라우터 & 컨트롤러)
controller 컨트롤러 : 회원가입, 홈페이지, 에러화면 등
Router 라우터 : 사용자의 요청을 어떤 컨트롤러에 전달해 줄 것인가 하는 중개자의 역할
ex) app.get
app.get('/', function(req, res){
res.send('hello~');
});
app.get('/dynamic', function(req,res){
res.send('dynamic');
});
메인 ’/’ 페이지에 들어왔을때 ‘hello~’ 출력
/dynamic 페이지에 들어왔을때 ‘dynamic’ 출력
nodejs 설치
webserver.js
const http = require('http');
const hostname = '127.0.0.1';
const port = 1337;
var server = http.createServer(function(req, res){
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Hello World\n');
});
server.listen(port, hostname, function(){
console.log(`Server running at http://${hostname}:${port}/`);
});
실행
cmd
cd.. : 상위폴더로 이동
cd foldername : 하위폴더로 이동
ctrl + c : 빠져나오기
↑ : 이전 작성 코드 불러오기
node webserver.js
node app.js
var (variable) 변수
const (constant) 상수
한번 할당이 되면 그다음부터 값을 바꿀수없는 상수
Node Package Manager (NPM)
node계의 앱스토어
설치/삭제/업그레이드/의존성 관리
uglify-js
npm install uglify-js -g
//save
uglifyjs pretty.js -o pretty.min.js -m
npm 설치시 플래그 옵션 save
npm install underscore --save
dependencies 가 붙음
의존성, 온전하게 포함
어떠한 모듈을 프로젝트에 포함시키는 방법
새로운 폴더에 이 프로젝트를 다시 시작한다고 하더라도 디펜던시에 있는 모듈을 쉽게 가져올 수 있다.
npm init
프로젝트 처음 시작시 현재 디렉토리를 npm의 디렉토리로 지정
package.json 파일이 생성됨
underscore
var _ = require('underscore');
var arr = [3,6,9,12];
console.log(_.first(arr));
Express
노드를 이용해서 만들어진 웹 프레임워크
웹애플리케이션 구축
설치
npm install express --save
app.js 생성
메인파일, 메인애플리케이션, 엔트리 애플리케이션
최초의 진입점이 되는 메인 애플리케이션 생성
myapp 디렉토리에 app.js라는 이름의 파일을 작성한 후 다음과 같은 코드를 추가
app.js
var express = require('express');
var app = express();
app.get('/', function (req, res) {
res.send('Hello World!');
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
정적파일 재공
app.use(express.static('public'));
동적파일과 정적파일
app.js
var express = require('express');
var app = express();
app.use(express.static('public'));
app.get('/', function(req, res){
res.send('hello~');
});
app.get('/dynamic', function(req,res){
var lis = '';
for(var i=0; i<5; i++){
lis = lis + '<li>coding</li>';
}
var time = Date();
var output = `<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
hello dynamic!
<ul>
${lis}
</ul>
${time}
</body>
</html>`;
res.send(output);
});
app.get('/route', function(req, res){
res.send('hello router, <img src="/Lighthouse.jpg">');
});
app.get('/login', function(req, res){
res.send('login please');
});
app.listen(3000, function(){
console.log('connented 3000 port!');
});
jade 템플릿엔진
npm install jade —save
express 템플릿 렌더링설정
app.set('view engine', 'jade');
app.set('views','./views');
렌더링할 라우트작성
app.get('/template', function(req, res){
res.render('temp');
});
코드를 보기좋게 바꿔줌
app.locals.pretty = true;
템플릿 엔진 Jade 사용법과 문법
반복문 사용시 앞에 -를 붙여야함
html
head
body
h1 hello Jade
ul
-for(var i=0; i<5; i++)
li coding
div= time
div= time
time 은 변수
app.js에 현재 시간을 정의
app.get('/template', function(req, res){
res.render('temp', {time:Date()});
});
query strin (쿼리 스트링)
쿼리스트링은 어떤 애플리케이션에게 정보를전달할때 사용하는 url의 약속되어 있는 국제적인 표준
쿼리스트링으로 전달된 값은 request 영역
같은 패스 안에서 쿼리스트링 id값에 따라서 다른 결과를 전달
?id=3
app.get('/topic', function(req, res){
res.send(req.query.id);
});
req.query
This property is an object containing a property for each query string parameter in the route. If there is no query string, it is the empty object, {}.
request 객체가 갖고 잇는 쿼리라는 객체의 id라는 property를 통해서 사용자가 쿼리스트링으로 접속할 때 전달한 정보를 사용할 수 있다.
사용자가 topic?id=3 을 치고 들어왓을때 이것은 요청임
req / request 정보
복수의 값도 받아 올 수 있음
쿼리스트링을 통해서 애플리케이션에게 전달할 수 있는 값은 여러개 일 수 있다.
?로 시작 &로 연결
app.get('/topic', function(req, res){
res.send(req.query.id+','+req.query.name);
});
http://localhost:3000/topic?id=1&name=song 로 접속했을때
id와 name 인 1,song 을 사용자에게 전송함
query 객체의 활용
app.get('/topic', function(req, res){
var topics = [
'Javascript is....',
'Node js is...',
'Express is...'
];
res.send(topics[req.query.id]);
});
배열에 담고 해당 쿼리스트링 값을 받아와서 출력
링크 클릭 동적으로 보여주기
app.get('/topic', function(req, res){
var topics = [
'Javascript is....',
'Node js is...',
'Express is...'
];
var output = `
<a href="/topic?id=0">Javascript</a><br>
<a href="/topic?id=1">Nodejs</a><br>
<a href="/topic?id=2">Express</a><br><br>
${topics[req.query.id]}
`
res.send(output);
});
Semantic URL (시멘틱 URL)
시멘틱(의미론적) 웹
쿼리스트링이 없이 깔끔한 url을 통해 애플리케이션을 제어 할 수 있음
의미에 좀 더 부합되는 URL체계
app.get('/topic/:id', function(req, res){
var topics = [
'Javascript is....',
'Node js is...',
'Express is...'
];
var output = `
<a href="/topic?id=0">Javascript</a><br>
<a href="/topic?id=1">Nodejs</a><br>
<a href="/topic?id=2">Express</a><br><br>
${topics[req.params.id]}
`
res.send(output);
});
topics/:id
어떠한 값이 오는 경우에 잡아줌
100으로 해도 1000으로 해도…
params
parameter 파라미터
뒤에 오는 정보를 알아낼 수 있는 방법
${topics[req.params.id]}
path방식인 semantic URL을 사용하는 경우 params 를 사용
http://localhost:3000/topic/1/edit
app.get('/topic/:id/:node', function(req, res){
res.send(req.params.id+','+req.params.node);
});
1, edit 출력
GET & POST 방식 정보 전달
GET
어떤 정보를 서버에 요청해서 가져오는 기본적인 방식
POST
사용자의 정보를 서버로 전송할 때의 방식
POST 방식을 통해 사용자로부터 정보를 입력받아서 로그인 또는 글을 쓰게 할 수 있다.
form.jade 파일을 렌더링
app.get('/form', function(req, res){
res.render('form');
});
태그의 속성을 표시하고 싶을 때 () 를 써서 속성 추가
doctype html
html
head
meta(charset='utf-8')
body
doctype html
html
head
meta(charset='utf-8')
body
form(action='/form_recevier')
p
input(type='text' name='title')
p
textarea(name='description')
p
input(type='submit')
form으로 전송하고자 하는 데이터를 하나로 묶음
action : submit 했을 때 입력된 정보들이 서버의 어디로 전송 될 것인가를 웹브라우저에게 알려줌
name 값을 받아서
쿼리 스트링이 자동으로 생성됨
app.get('/form_receiver', function(req, res){
var title = req.query.title;
var description = req.query.description;
res.send(title+','+description);
});
사용자가 전송한 title과 description 값을 저장 할 수 있다.
GET 방식 전송
form(action='/form_receiver' method='get')
form(action='/form_receiver')
생략해도 기본이 GET
URL에 쿼리스트링이 붙음
http://localhost:3000/form_receiver?title=h&description=w
POST 방식 전송
form(action='/form_receiver' method='post')
URL은 쿼리스트링이 붙지 않은 상태로 나옴
http://localhost:3000/form_receiver
Cannot POST /form_receiver 라고 출력
전송 실패가 아니며 사용자의 데이터는 서버로 잘 전송 되었음
다만 데이터 전송방식이 post면 눈에 보이지 않는 방식으로 데이터를 전송
POST 방식으로 사용자가 전송한 데이터를 서버쪽에서 수신하는 방법
app.post('/form_receiver', function(req, res){
res.send('hello, POST');
});
app.post 방식으로 컨트롤러를 연결 시켜서 실행
req.body
app.post('/form_receiver', function(req, res){
var title = req.body.title;
var description = req.body.description;
res.send(title+','+description);
});
그냥 작동시 undefined
Contains key-value pairs of data submitted in the request body. By default, it is undefined, and is populated when you use body-parsing middleware such as body-parser and multer.
body-parser
일종의 플러그인, 확장기능 모듈 을 포함 시켜서 작동하도록 하면 사용 할 수 있음
body-parser 모듈 npm을 이용해 설치
npm install body-parser --save
app.js 에 추가해서 body-parser를 가져옴
var bodyParser = require('body-parser');
app.use 로 bodyParser 연결
app.use(bodyParser.urlencoded({ extended: true }));
모든 요청들은 bodyParser라고 하는 확장기능 (미들웨어)를 먼저 통과한 다음에 라우트가 동작하게 된다.
제일 앞쪽에서 대기하고 있다가 사용자가 POST방식으로 전송한 데이터를 사용할 수 있도록 한다.
request 객체에 body라는 객체가 포함됨
정리 (POST가 동작하는 방식)
1.body parser라는 모듈을 추가
2.use라는 메소드를 통해 연결
3.사용자를 통해 들어오는 요청들은 바디파서가 제일 먼저 실행
4.사용자가 POST방식으로 전송한 데이터가 있다면
5.애플리케이션 안에서 req 객체가 원래 가지고 있지 않았던 body라는 객체를 bodyparser가 추가 함
6.사용자가 전송한 데이터의 이름이 title이라면 body라는 객체에 title이라는 프로퍼티의 값을 넣고,
description이라면 body에 description이라는 프로퍼티를 만들고 값을 넣어서 사용자에게 제공 함
7.그 결과 화면에 출력
POST & GET 차이
GET
어떤 정보에 대한 주소를 나타낼 때
POST
URL상에 정보가 표시 되지 않아야 할 때
대규모 전송, 내용이 많을 때
express가 기본적으로 제공하지 않기 때문에 body-parser라는 미들웨어를 로드
supervisor
소스가 변경되었을 때 애플리케이션을 자동으로 재시작
설치
npm install supervisor -g
사용
supervisuor app.js
서버를 자동으로 재시작