[생활코딩 WEB2] Node.js
수업의 목적
이전에는 html, css, javascript로 코드를 작성하여 웹 사이트를 구현했다.
만약, 일억개의 웹 페이지에서 공통된 html 태그 하나를 바꿔야된다면 파일을 일일히 바꿔야된다. -> 생산성 문제
또한, 사용자의 의견을 웹 페이지에 구현하려면 이메일에 코드를 직접 짜서 보낸 다음 파일로 저장해야한다. -> 적은 사용자의 권한
이를 해결하기 위해서 나온 툴이 node.js 이다.
페이지 일억개를 저장한게 아니라 사용자가 어떠한 페이지를 요청할 때마다 node.js가 순간순간 웹 페이지를 프로그래밍적으로 생성하기 때문이다.
또한 페이지를 방문하는 사용자에게 읽기 권한 뿐만 아니라 쓰는 권한도 부여한다.
웹서버 만들기
web browser에 주소를 입력해서 web server에 요청하면 web server는 그 요청에 따른 정보를 찾아서 응답해준다.
우리는 전에서 아파치를 웹 서버로 사용하였다.
node.js는 아파치처럼 웹서버 기능이 있다. 웹 서버 기능을 내장하고 있기 때문이다!
깃허브에서 파일을 가져와서 nodejs폴더에 넣은 다음,
main.js 파일을 만들어서
var http = require('http');
var fs = require('fs');
var app = http.createServer(function(request,response){
var url = request.url;
if(request.url == '/'){
url = '/index.html';
}
if(request.url == '/favicon.ico'){
return response.writeHead(404);
}
response.writeHead(200);
response.end(fs.readFileSync(__dirname + url));
});
app.listen(3000);
코드를 붙여넣는다. 이 코드는 후에 해석하고 이걸 자유자재로 사용할 수 있게 하는게 이 수업의 목표다.
그 다음, 검색창에 localhost:3000을 입력한다.
이 때 사이트에 연결할 수 없다 라고 뜬다.
웹 서버가 없기 때문이다.
cmd(명령프롬프트) 를 켜고 폴더에 들어가서
node main.js
를 입력한다. 이때 웹 서버가 생성된다. 내 컴퓨터가 서버가 되는 것이다.
다시 검색창에 localhost:3000을 쓰면 index.html 파일이 웹에 뜬다.
JavaScript-Data type-Number,String
Number
String
두 가지의 데이터 타입을 배운다.
숫자는 그냥 숫자를 입력하면 된다.
syntax/Number.js 에 저장
console.log(1+1);
console.log(3-1);
console.log(3*3);
console.log(12/3);
cmd 에서 node syntax/Number.js 를 입력하면
2
2
9
4
가 뜬다.
문자열을 표기할 때는 "" 이든 '' 이든 상관없다. 짝만 맞춰주자.
console.log('1'+'1'); //11
console.log('가나다라마바사대충일억개가있다고해보자'.length); //19
javascript- 변수
syntax/variable.js 파일을 생성하자
변수 앞에 var 을 붙이자. 유효범위 때문인데 이 내용은 나중에 다룬다.
var a=1;
console.log(a);
a=2;
console.log(a);
// 1 = 2; 주석, 영어로 comment
javascript - Template Literal
줄바꿈을 하고 싶다.
var name = 'k8805';
// String literals
var letter = 'Dear '+name+'\n\nLorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. '+name+' Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa egoing qui officia deserunt mollit anim id est laborum. '+name;// Template literals
var letter = `Dear ${name}Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. ${name} Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ${1+1} Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa egoing qui officia deserunt mollit anim id est laborum. ${name}`;
console.log(letter);
+ 를 쓰기 귀찮고 \n을 붙이기 귀찮아서 나온 방법이 아래 코드에 나온 방법이다. `를 붙이고 변수는 ${} 안에 넣으면 된다.
Node.js - URL로 입력된 값 사용하기
url의 형식에 대해 알아보자.
- protocol: 통신규칙, 사용자가 서버에 접속할 때 어떤 방식으로 데이터를 주고받을지 결정
- host(domain): 인터넷에 접속되어 있는 각각의 컴퓨터, 특정한 인터넷에 연결되어 있는 컴퓨터를 가리키는 주소
- port: 한 대의 컴퓨터 안에 서버가 여러개 있을 수 있기 때문에 특정 포트에 연결된 서버와 소통해야한다.
- path: 그 컴퓨터 안에 어떤 디렉토리 안에 어떤 파일인 것을 보여줌
- query string: 읽고 싶은 정보를 알려준다. 시작은 ? 로, 값과 값은 &, 값의 이름과 값은 = 로 구분한다.
Node.js에서 URL을 통해서 입력된 값을 사용하는 방법
url의 id 값에 따라서 사용자에게 적당한 컨텐츠를 보여준다.
querystring 값에 따라 다른 정보를 보여준다.
url값이 어떻게 전달되는지 확인하기 위에 main.js 에
console.log(url)
코드를 추가한다.
검색창에 localhost:3000/?id=HTML 을 치면
cmd 에 아래와 같이 뜬다.
여기서 /?id=HTML에 주목하자.
main.js 파일을 아래와 같이 바꿔보자.
var http = require('http');
var fs = require('fs');
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것을 nodejs 에게 알려준다.var app = http.createServer(function(request,response){
var _url = request.url;
var queryData = url.parse(_url, true).query;
console.log(queryData.id);
if(_url == '/'){
_url = '/index.html';
}
if(_url == '/favicon.ico'){
return response.writeHead(404);
}
response.writeHead(200);
response.end(queryData.id);});
app.listen(3000);
검색창에
http://localhost:3000/?id=HTML
http://localhost:3000/?id=CCS
를 검색하면
cmd 출력창에 아래와 같이 뜬다.
App - 동적인 웹페이지 만들기
querystring 에 따라서 다르게 동작하는 웹 애플리케이션을 만들어봤다.
이제 그에따른 완성된 페이지를 만들어보자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
var title= queryData.id;
if(_url == '/'){//queryString에 아무것도 없을 때
_url = '/index.html';
}
if(_url == '/favicon.ico'){
return response.writeHead(404);//에러
}
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
var template= `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
<ul>
<li><a href="/?id=HTML">HTML</a></li>
<li><a href="/?id=CSS">CSS</a></li>
<li><a href="/?id=JavaScript">JavaScript</a></li>
</ul>
<h2>${title}</h2>
<p><a href="https://www.w3.org/TR/html5/" target="_blank" title="html5 speicification">Hypertext Markup Language (HTML)</a> is the standard markup language for <strong>creating <u>web</u> pages</strong> and web applications.Web browsers receive HTML documents from a web server or from local storage and render them into multimedia web pages. HTML describes the structure of a web page semantically and originally included cues for the appearance of the document.
<img src="coding.jpg" width="100%">
</p><p style="margin-top:45px;">HTML elements are the building blocks of HTML pages. With HTML constructs, images and other objects, such as interactive forms, may be embedded into the rendered page. It provides a means to create structured documents by denoting structural semantics for text such as headings, paragraphs, lists, links, quotes and other items. HTML elements are delineated by tags, written using angle brackets.
</p>
</body>
</html>
`;
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
app.listen(3000);
이 코드를 main.js 에 입력하고 cmd 에서 실행한 뒤, querystring 부분에 ?id=HTML 을 넣으면 title 부분만 바뀐다.
Node.js - 파일 읽기
정보시스템에서 핵심적인 메커니즘, CRUD
C REATE
R EAD
U PDATE
D ELETE
node 디렉토리 내에 fileread.js sample.txt 파일을 만든다.
sample.txt 에
jkjkkkkjk
라는 아무 의미 없는 메세지를 넣고
fileread.js에
var fs= require('fs');//filesystem 모듈을 다룰 수 있게 된다.
fs.readFile('sample.txt', 'utf8', function(err, data){
console.log(data);
});
코드를 넣은 다음
cmd 에
node fileread
를 입력하면
이렇게 뜬다.
App - 파일을 이용해 본문 구현
querystring 에 따라 본문이 바뀌는 웹 애플리케이션을 만들자.
파일을 읽는 법을 사용해서 구현해보자.
data 디렉토리를 만들어서 본문 내용을 따로 저장하자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
var title= queryData.id;
if(_url == '/'){//queryString에 아무것도 없을 때
title='welcome';
}
if(_url == '/favicon.ico'){
return response.writeHead(404);//에러
}
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var template= `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
<ul>
<li><a href="/?id=HTML">HTML</a></li>
<li><a href="/?id=CSS">CSS</a></li>
<li><a href="/?id=JavaScript">JavaScript</a></li>
</ul>
<h2>${title}</h2>
<p>${description}</p>
</body>
</html>
`;
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
})
});
app.listen(3000);
이 때, data 디렉토리의 파일 내용을 수정해도 main.js 를 껐다 다시 안 키고 새로고침만하면 된다. 사용자가 querystring을 요청하면 nodejs가 프로그램을 주기 때문이다.
JavaScript - Boolean
참과 거짓을 나타낸다. 산술연산자가 아닌 비교연산자이다.
boolean의 데이터 타입은 true 와 false 가 있다
true와 false는 변수로 사용할 수 없다.
JavaScript - 비교 연산자
==: 좌항과 우항의 비교
>,< : 비교연산자
\===: 정확하게 같냐..
console.log(1==1)//true
console.log(1==2)//false
JavaScript - 제어문
프로그래머: 시간의 순서에 따라 컴퓨터의 명령을 설계하는 사람들
조건문, 반복문이 있다.
JavaScript - 조건문
console.log('A');//출력
console.log('B');//출력
if(false){
console.log('C1'); //미출력
} else {
console.log('C2'); //출력
}
console.log('D');//출력
Node.js - 콘솔에서의 입력값
INPUT:
parameter(입력되는 정보의 형식),
argument(그 형식에 맞게 입력한 값)
OUTPUT
App - Not found 오류 구현
없는 페이지를 방문했을 때, 없는 페이지라고 알려주는 것을 만들어보자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var template= `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
<ul>
<li><a href="/?id=HTML">HTML</a></li>
<li><a href="/?id=CSS">CSS</a></li>
<li><a href="/?id=JavaScript">JavaScript</a></li>
</ul>
<h2>${title}</h2>
<p>${description}</p>
</body>
</html>
`;
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
})
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
여기서
>var pathname = url.parse(_url, true).pathname;
이 코드로 조건문을 쓴 이유는 검색할 때,
http://localhost:3000/?id=HTML 이렇게 검색하면 / 뒤의 ? 부터 querystring으로 읽기 시작하기 때문에 /이 pathname이 된다.
하지만 ? 를 쓰지 않고 만약 http://localhost:3000/아무거나씀
이렇게 쓰면 pathname이 /아무거나씀 이 된다.
즉 pathname은 ?를 만날 때까지 계속 읽기 때문에 조건문을 if(pathname==='/')
이렇게 쓴 것이다.
## App - 홈페이지 구현
web 링크를 누르면 undefined 가 뜬다. 대응하는 querystring이 없기 때문인데 이를 해결해보자.
,,,
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
title= 'Welcome';
var template= `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
<ul>
<li><a href="/?id=HTML">HTML</a></li>
<li><a href="/?id=CSS">CSS</a></li>
<li><a href="/?id=JavaScript">JavaScript</a></li>
</ul>
<h2>${title}</h2>
<p>welcome</p>
</body>
</html>
`;
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
}
else{
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var template= `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
<ul>
<li><a href="/?id=HTML">HTML</a></li>
<li><a href="/?id=CSS">CSS</a></li>
<li><a href="/?id=JavaScript">JavaScript</a></li>
</ul>
<h2>${title}</h2>
<p>${description}</p>
</body>
</html>
`;
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
})
}
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
여기서 undefined 에는 ' 을 쓰지 않는다. NULL 이랑 비슷한 듯
JavaScript - 반복문
while, for, do-while이 있다.
console.log('A');
console.log('B');var i = 0;
while(i < 2){
console.log('C1');
console.log('C2');
i = i + 1;
}console.log('D');
출력
A
B
C1
C2
C1
C2
D
JavaScript - 배열
배열은 반복문과 같이 쓰인다.
var arr = ['A', 'B', 'C', 'D']; //배열 초기화
console.log(arr[1]); // B 출력
console.log(arr);//['A', 'B', 'C', 'D']
console.log(arr.length);//4
arr.push('E');arr[4]에 E가 들어간다.
JavaScript - 배열과 반복문
var number = [1,400,12,34];
var i = 0;
var total = 0;
while(i < number.length){
total = total + number[i];
i = i + 1;
}
console.log(total : ${total}
); //total : 447
Node.js - 파일 목록 알아내기
readdir을 사용한다.
var testFolder = './data';
var fs = require('fs');fs.readdir(testFolder, function(error, filelist){
console.log(filelist);
})
여기서 주의할 점은 './data'는 현재 디렉토리의 data 폴더를 얘기하는데..
현재 디렉토리의 기준이 cmd 이기 때문에 nodejs 파일에서
node node/filesearch
를 입력하면 정상적으로 출력되나
node 디렉토리에서
node filesearch
를 입력하면 undefined라고 뜬다.
App - 글목록 출력하기
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
var template= `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
<h2>${title}</h2>
<p>${description}</p>
</body>
</html>
`;
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
}
)
}
else{
fs.readdir('./data', function(error, filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var template= `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
<h2>${title}</h2>
<p>${description}</p>
</body>
</html>
`;
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
readdir 함수를 이용해서 ul 태그를 효율적이게 팩토링한다.
JavaScript - 함수의 기본 문법
반복적으로 등장하는 코드를 함수로 정의한다.
function funcname(){
코드
}
funcname(); //호출
JavaScript - 함수의 입력
입력에 따라 함수를 다양하게 쓰는 법
function sum(first, second){//parameter
console.log(first+second);
}
sum(2,4); //argument
JavaScript - 함수의 출력
function sum(first, second){ // parameter
return first+second;//리턴을 만나면 함수 종료
}
console.log(sum(2,4)); // argument
App - 함수를 이용해서 정리 정돈하기
중복되는 코드를 없애자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
function templateHTML(title, list, body){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
}
)
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
함수 templateHTML()과 templatelist()를 만들었다.
수업의 정상
JavaScript의 기본문법, Node.js의 주요 기능, 웹애플리케이션을 만드는 방법의 본질을 충분히 살펴봤다.
하지만 킵고잉
Node.js - 동기와 비동기 그리고 콜백
동기적(synchronous): 한 일이 끝나면 다른 일이 끝날 때까지 기다린다.
비동기적(asynchronous): 특정 일이 오래걸린다면 일단 일을 시켜놓고 다른 일을 함. 일들이 병렬적으로 이루어짐.-> 시간은 효율적이지만 매우 복잡하다.
node.js는 비동기적인 코드를 구현하는데 좋다.
동기와 비동기 2
node.js 함수를 보면 readFileSync, readFile 처럼 Sync가 붙은 것과 붙지 않은 것들이 있다. Sync를 붙이는 것을 보아 node.js 는 비동기 방식을 선호하는 것을 알 수 있다. 예시를 보자.
syntax/sample.txt
B
syntax/sync.js
var fs = require('fs');
/*
//readFileSync
console.log('A');
var result = fs.readFileSync('syntax/sample.txt', 'utf8');
console.log(result);
console.log('C');
*/
console.log('A');
fs.readFile('syntax/sample.txt', 'utf8', function(err, result){//readfile은 return 값이 없다. function은 콜백함수
console.log(result);
});
console.log('C');
일 때, readFileSync 함수에서는
A
B
C
가 출력되지만, readFile에서는
A
C
B
가 출력된다. readFile 결과가 나오기 전에 console.log('C') 가 먼저 출력되기 때문이다.
callback
파일을 읽은 다음에 함수를 다시 불러와서(callback) 함수 내 코드를 실행한다. 파일을 읽는 동안 다음 코드를 해석한다.->비동기 방식
Node.js - 패키지 매니저와 PM2
pm(packge manager)
npm: node.js 에서 가장 광범위하게 쓰이는 pm, node.js를 설치할 때 같이 설치된다.
npm install pm2 -g //-g : 이 프로그램은 내 컴퓨터의 독립적인 아무 곳에서나 쓸 수 있어야 된다는 옵션
를 cmd 창에 입력한다.
npm을 실행하면
- 서버가 꺼지면 다시 실행해준다.
- main.js 를 수정해도 서버를 껐다 다시 키지 않아도 pm이 감시하고 있기 때문에 자동으로 서버를 업데이트 해주기 때문에 새로고침만 하면된다.
pm2 start main.js
를 입력하면 cmd에 아래와 같은 창이 뜬다.
여기서 Name 의 main은 우리가 실행중인 main.js의 별명이다.
pm2 monit// 서버를 강제 종료해도 바로 다시 켜준다.
pm2 list// 끄고 싶을 때 어떤 걸 종료할지 이름 까먹었을 때 이걸로 확인
pm2 stop main// pm 끄기
pm2 start main.js --watch// main.js의 변경사항을 실시간으로 감시한다.
pm2 log //오류를 보여준다.
HTML - Form
데이터 디렉토리 생성은 현재까지 배운걸로는 관리자만 할 수 있다.
이제부터 사용자가 직접 데이터를 써서 데이터 디렉토리에 저장할 수 있게 하는 것을 배우자.
html 파일로 정보를 입력 받는 방법을 배워보자.
form.html 파일 생성
<form action="http://localhost:3000/process_create">
<p><input type="text" name= "title"></p>
<p>
<textarea name="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
form.html 코드
form 태그를 쓰기 때문에 이 챕터 제목이 HTML-Form 이다.
전송하고자 하는 데이터를 form 태그로 감싸준다. 그리고 action 속성으로 form 안에 담긴 데이터를 보낼 곳을 서버에게 알려준다.
data는 이름이 붙는 것이 좋으므로 name 속성을 만든다. ex) name="description"
이런 페이지가 만들어진다.
칸에 text를 입력하고 제출을 누르면 검색창이 아래와 같이 바뀐다.
전송하는 내용이 검색창에 그대로 나타난다. 위험하기 때문에 form 태그 안에
method="post"
라는 속성과 속성값을 넣는다.
<form action="http://localhost:3000/process_create" method= "post">
<p><input type="text" name= "title"></p>
<p>
<textarea name="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
그렇게 다시 전송 버튼을 누르면 아래와 같이 보낼 정보가 숨겨진다.
데이터를 수정, 삭제, 생성할 때는 반드시 method= "post" 를 쓰자.
App - 글생성 UI 만들기
리스트 아래에 글 쓰는 링크를 만들어 보자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
function templateHTML(title, list, body){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
<a href="/create">create</a>
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){ ///////// /create 와 구분
if(queryData.id=== undefined){ //홈으로 갔느냐
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
});
}
else{ //?id=HTML ?id=CSS ?id=JAVASCRIPT
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){///////// /create
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =templatelist(filelist);
var template= templateHTML(title, list, `
<form action="http://localhost:3000/process_create" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);
response.end(template);
})
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
이렇게 코드를 수정한 뒤에, /create 페이지에서 제출버튼을 누르면 not found 페이지가 뜬다. /process_create pathway가 없기 때문이다.
하지만 크롬 inspector 를 열어서 network를 확인해보면 웹 브라우저와 웹 서버가 정보를 주고 받는 것을 알 수 있다.
network/Name/Headers/Form Data
App - POST 방식으로 전송된 데이터 받기
post 로 전송된 데이터를 받는 코드를 작성해보자.
정보를 받을 create_process 주소가 필요하다. (process_create 에서 create_process 로 변경했다)
pathname이 /create_process인 것이 생겼으므로
else if(pathway==='/create_process') {
response.writeHead(200);
response.end(template);
}
을 추가한다. 이제 post 방식으로 전달된 것을 node.js에서 어떻게 쓰는지 알아보자.
var app = http.createServer(function(request,response){
코드에서 request는 웹 브라우저가 서버에게 보낼 정보, response는 서버가 웹 브라우저에 보낼 정보이다.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var qs = require('querystring');
function templateHTML(title, list, body){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
<a href="/create">create</a>
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
});
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =templatelist(filelist);
var template= templateHTML(title, list, `
<form action="http://localhost:3000/create_process" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
})
}
////////////////////////////////////////////////////////
else if(pathname === '/create_process'){
var body ='';
request.on('data',function(data){//데이터가 조각조각 저장될 때마다 함수가 호출된다. 콜백 방식
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 end라는 정보가 들어오고 이 함수 콜백한다.
var post= qs.parse(body); //post에 post 정보가 들어간다. 객체 형태로 들어감
var title= post.title;
var description= post.description;
});
response.writeHead(200);
response.end('success');
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
App - 파일생성과 리다이렉션
post 형식으로 전송된 데이터를 data 디렉토리 안에 저장하는 법을
nodejs에서 파일을 저장하는 법을 알아보자
fs.writeFile(file,data[,options], callback)
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var qs = require('querystring');
function templateHTML(title, list, body){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
<a href="/create">create</a>
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
});
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =templatelist(filelist);
var template= templateHTML(title, list, `
<form action="http://localhost:3000/create_process" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
})
}
else if(pathname === '/create_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var title= post.title;
var description= post.description;
///////////////////////////////////////////////////
fs.writeFile(`data/${title}`, description, 'utf8', function(err){//이 콜백이 된다는 건 파일 저장이 끝났다는 뜻이다. 따라서 response.writeHead는 이 콜백함수 안에 적혀야 데이터가 성공적으로 저장된 것을 알 수 있다.
//사용자가 success 창 말고 성공적으로 데이터가 전송이 됐는지 보고싶어하기 때문에 리다이렉션을 시켜야한다. ex) /?NodeJs로
response.writeHead(302, {Location: `/?id=${title}`});//302: 페이지를 다른 곳으로 리다이렉션 시켜라
response.end();
})
});
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
리다이렉션: 사용자가 어떤 페이지로 보낸 다음 다른 페이지로 튕겨나가게 하는 것
App - 글수정 - 수정 링크 생성
생성 기능을 만들었으니 수정 기능을 만들어보자.
querystring의 id 값이 없을 때, update 버튼을 만든다. 즉 홈화면에서는 안 보이게 한다. 특정 토픽을 선택하면 update 가 뜨게하도록 한다.
누구를 수정할 것인지 querystring 으로 보내자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var qs = require('querystring');
function templateHTML(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
///////////////////////////////////////
${control}
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`,
////////////////////////////////
``);
response.writeHead(200);
response.end(template);
});
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`<h2>${title}</h2> <p>${description}</p>`,
////////////////////////////////////
`<a href="/create">create</a>
<a href="/update?id=${title}">update</a>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =templatelist(filelist);
var template= templateHTML(title, list, `
<form action="http://localhost:3000/create_process" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
})
}
else if(pathname === '/create_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var title= post.title;
var description= post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
App - 글수정 - 수정할 정보 전송
update 를 클릭했을 때 보이는 창을 만들자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var qs = require('querystring');
function templateHTML(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`,
``);
response.writeHead(200);
response.end(template);
});
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`<h2>${title}</h2> <p>${description}</p>`,
`<a href="/create">create</a>
<a href="/update?id=${title}">update</a>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =templatelist(filelist);
var template= templateHTML(title, list, `
<form action="create_process" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
})
}
else if(pathname === '/create_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var title= post.title;
var description= post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
}
////////////////////////////////////////////
else if(pathname ==='/update'){
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`
<form action="/update_proccess" method="post">
<input type="hidden" name= "id" placeholder= "title" value=${title}>
<p><input type="text" name= "title" placeholder= "title" value=${title}></p>
<p>
<textarea name="description" placeholder="description">${description}</textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
App - 글수정 - 수정된 내용 저장
update_process 로 전송한 값을 받아서 처리하는 법을 배우자
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var qs = require('querystring');
function templateHTML(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`,
``);
response.writeHead(200);
response.end(template);
});
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`<h2>${title}</h2> <p>${description}</p>`,
`<a href="/create">create</a>
<a href="/update?id=${title}">update</a>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =templatelist(filelist);
var template= templateHTML(title, list, `
<form action="create_process" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
})
}
else if(pathname === '/create_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var title= post.title;
var description= post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
}
else if(pathname ==='/update'){
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`
<form action="/update_proccess" method="post">
<input type="hidden" name= "id" placeholder= "title" value=${title}>
<p><input type="text" name= "title" placeholder= "title" value=${title}></p>
<p>
<textarea name="description" placeholder="description">${description}</textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
////////////////////////////////////////////////////
else if(pathname=== '/update_proccess'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var id= post.id;
var title= post.title;
var description= post.description;
fs.rename(`data/${id}`, `data/${title}`, function(error){//파일명 바꾸기
fs.writeFile(`data/${title}`, description, 'utf8', function(err){//description보내기
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
})
});
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
App - 글삭제 - 삭제버튼 구현
delete 버튼을 만든다. 링크로 걸지 말고 form 태그로 만든다.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var qs = require('querystring');
function templateHTML(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`,
``);
response.writeHead(200);
response.end(template);
});
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`<h2>${title}</h2> <p>${description}</p>`,
`<a href="/create">create</a>
<a href="/update?id=${title}">update</a>
//////////////////////////////////////////////////
<form action="delete_process" method="post">
<input type="hidden" name="id" value="${title}">
<input type="submit" value="delete">
</form>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =templatelist(filelist);
var template= templateHTML(title, list, `
<form action="create_process" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
})
}
else if(pathname === '/create_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var title= post.title;
var description= post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
}
else if(pathname ==='/update'){
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`
<form action="/update_proccess" method="post">
<input type="hidden" name= "id" placeholder= "title" value=${title}>
<p><input type="text" name= "title" placeholder= "title" value=${title}></p>
<p>
<textarea name="description" placeholder="description">${description}</textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
else if(pathname=== '/update_proccess'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var id= post.id;
var title= post.title;
var description= post.description;
fs.rename(`data/${id}`, `data/${title}`, function(error){//파일명 바꾸기
fs.writeFile(`data/${title}`, description, 'utf8', function(err){//description보내기
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
})
});
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
App - 글삭제 기능 완성
글 삭제 버튼을 만들었으므로 이제 기능을 넣어보자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var qs = require('querystring');
function templateHTML(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`
}
function templatelist(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>'
return list;
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var title= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =templatelist(filelist);
var template= templateHTML(title, list, `<h2>${title}</h2>
<p>${description}</p>`,
``);
response.writeHead(200);
response.end(template);
});
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`<h2>${title}</h2> <p>${description}</p>`,
`<a href="/create">create</a>
<a href="/update?id=${title}">update</a>
<form action="delete_process" method="post">
<input type="hidden" name="id" value="${title}">
<input type="submit" value="delete">
</form>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =templatelist(filelist);
var template= templateHTML(title, list, `
<form action="create_process" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);
})
}
else if(pathname === '/create_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var title= post.title;
var description= post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
}
else if(pathname ==='/update'){
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= templatelist(filelist);
var title = queryData.id;
var template= templateHTML(title, list,
`
<form action="/update_proccess" method="post">
<input type="hidden" name= "id" placeholder= "title" value=${title}>
<p><input type="text" name= "title" placeholder= "title" value=${title}></p>
<p>
<textarea name="description" placeholder="description">${description}</textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(template);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
else if(pathname=== '/update_proccess'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var id= post.id;
var title= post.title;
var description= post.description;
fs.rename(`data/${id}`, `data/${title}`, function(error){//파일명 바꾸기
fs.writeFile(`data/${title}`, description, 'utf8', function(err){//description보내기
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
})
});
}
////////////////////////////////////////////
else if(pathname=== '/delete_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var id= post.id;
fs.unlink(`data/${id}`, function(eroor){
response.writeHead(302, {Location: `/`});//home화면으로 보낸다.
response.end();
})
});
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
JavaScript - 객체의 형식
Object vs Array
둘 다 정보를 정리정돈한다.
다만 배열은 순서가 있고 객체는 순서가 없다.
var roles = {
'programmer':'egoing',
'designer' : 'k8805',
'manager' : 'hoya'
}
console.log(roles.designer); //k8805
[ 대신 {를 쓴다.
JavaScript - 객체의 반복
var roles = {
'programmer':'egoing',
'designer' : 'k8805',
'manager' : 'hoya'
}
console.log(roles.designer); //k8805
console.log(roles['designer']); //k8805 배열의 인덱스에 이름을 부여해주는 것과 비슷한 것 같다.
for(var n in roles){
console.log('object => ', n, 'value => ', roles[n]);
key 값을 문자로도 불러올 수 있다.
JavaScript - 객체 - 값으로서 함수
Object Oriented Programming(OOP): 객체지향 프로그래밍
변수에 대입할 수 있어야 값이 된다.
var i= if(true){코드}; // 에러가 뜨기 때문에 조건문, 반복문은 값이될 수 없다.
var f = function(){
console.log(1+1);
console.log(1+2);
} //가능하기 때문에 함수는 값이될 수 있다.
var f = function(){
console.log(1+1);
console.log(1+2);
}
var a = [f];
a0;var o = {
func:f
}
o.func();
함수는 값이기 때문에 배열의 원소, 객체의 값으로 쓰일 수 있다. 즉 객체 이름으로 함수를 꺼낼 수 있다.
JavaScript - 객체 - 데이터와 값을 담는 그릇으로서 객체
var q = {
v1:'v1',
v2:'v2',
f1:function (){
console.log(this.v1);
},
f2:function(){
console.log(this.v2);
}
}q.f1();
q.f2();
q라는 객체 안에 v1 , v2라는 변수가 있고 f1(), f2() 함수가 있다.
객체 안의 property를 불러올 때는 객체명.property명 을 쓰면 된다.
ex) q라는 객체에서 f1() 이라는 함수를 불러올 때: q.f()
App -객체를 이용해서 템플릿 기능 정리 정돈하기
코드의 복잡성을 낮춘다는 장점이 있는 객체를 이용해서 템플릿 기능을 정리해보자.
templateHTML과 templateList는 template이라는 접두사를 가지고 있다. template 객체로 묶어 이 두 함수를 정리해보자.
var http = require('http');//http 모듈 사용하겠다.
var fs = require('fs');//fs 모듈 사용하겠다.
var url = require('url'); // 이 애플리케이션은 url이라는 모듈을 사용할 것이란걸 nodejs 에게 알려준다.
var qs = require('querystring');
////////////////////////////////////////////////
var template ={
html: function(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`;
},List:function(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>';
return list;
}
}
var app = http.createServer(function(request,response){
var _url = request.url//사용자가 요청하는 query string을 _url에 저장
var queryData = url.parse(_url, true).query;//queryData는 객체 id, name, page 등등 url의 query string 에 담긴 정보를 모두 담고있다.
var pathname = url.parse(_url, true).pathname;
var html= queryData.id;
console.log(queryData.id);//id만 출력하기 위해 queryData.id를 쓴다.
if(pathname==='/'){
if(queryData.id=== undefined){
fs.readdir('./data', function(error,filelist){
var title = 'Welcome';
var description = 'Hello, Node.js';
var list =template.List(filelist);
var html= template.html(title, list, `<h2>${title}</h2>
<p>${description}</p>`,
``);
response.writeHead(200);
response.end(html);
});
}
else{
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= template.List(filelist);
var title = queryData.id;
var html= template.html(title, list,
`<h2>${title}</h2> <p>${description}</p>`,
`<a href="/create">create</a>
<a href="/update?id=${title}">update</a>
<form action="delete_process" method="post">
<input type="hidden" name="id" value="${title}">
<input type="submit" value="delete">
</form>`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(html);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
}
else if(pathname === '/create'){
fs.readdir('./data', function(error,filelist){
var title = 'Web-create';
var list =template.List(filelist);
var html= template.html(title, list, `
<form action="create_process" method="post">
<p><input type="text" name= "title" placeholder= "title"></p>
<p>
<textarea name="description" placeholder="description"></textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(html);
})
}
else if(pathname === '/create_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var title= post.title;
var description= post.description;
fs.writeFile(`data/${title}`, description, 'utf8', function(err){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
}
else if(pathname ==='/update'){
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var list= template.List(filelist);
var title = queryData.id;
var html= template.html(title, list,
`
<form action="/update_proccess" method="post">
<input type="hidden" name= "id" placeholder= "title" value=${title}>
<p><input type="text" name= "title" placeholder= "title" value=${title}></p>
<p>
<textarea name="description" placeholder="description">${description}</textarea>
</p>
<p>
<input type="submit">
</p>
</form>
`);
response.writeHead(200);//query string 부분이 /favicon.ico가 아니면 정상쟉동한다.
response.end(html);//파일을 가져오는 대신에 파일 내용을 변수에 저장해서 가져온다. query string 이 바뀔 때마다 title 부분만 바뀐다.
});
});
}
else if(pathname=== '/update_proccess'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var id= post.id;
var title= post.title;
var description= post.description;
fs.rename(`data/${id}`, `data/${title}`, function(error){//파일명 바꾸기
fs.writeFile(`data/${title}`, description, 'utf8', function(err){//description보내기
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
})
});
}
else if(pathname=== '/delete_process'){
var body ='';
request.on('data',function(data){
body=body+data;//콜백이 실행될 때마다 데이터가 추가된다
console.log(body);//title=뫄뫄&description=롸롸
});
request.on('end', function(){//더 이상 들어올 정보가 없으면 이 함수 호출
var post= qs.parse(body);
var id= post.id;
fs.unlink(`data/${id}`, function(eroor){
response.writeHead(302, {Location: `/`});
response.end();
})
});
}
else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
Node.js - 모듈의 형식
모듈: 객체를 정리정돈할 수 있는 더 큰 틀
mpart.js
var M = {
v:'v',
f:function(){
console.log(this.v);
}
}module.exports = M; //약속, M이 가리키는 객체를 이 파일 외에서 쓸 수 있게 하겠다.
muse.js
var part = require('./mpart.js');
part.f(); //v
App 제작 - 모듈의 활용
모듈을 활용해보자
template을 lib/template.js 라는 파일에 붙여넣자.
lib/template.js
module.exports ={
html: function(title, list, body, control){
return `
<!doctype html>
<html>
<head>
<title>WEB1 - ${title}</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="/">WEB</a></h1>
${list}
${control}
${body}
</body>
</html>
`;
},List:function(filelist){
var list = '<ul>';
var i =0;
while(i<filelist.length){
list= list + `<li><a href="/?id=${filelist[i]}">${filelist[i]}</a></li>`;
i=i+1;
}
list= list+'</ul>';
return list;
}
}
main.js
var template= require(./lib/template);// 앞에 추가!
API
application programming interface
예를들어, readfile 함수는 node.js 개발자들이 만들었는데 개발자와 사용자 간의 약속장치이라고 볼 수 있다. 이를 interface라고 한다.
이러한 interface들을 이용해서 application을 개발할 수 있다.
Author And Source
이 문제에 관하여([생활코딩 WEB2] Node.js), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@bje5774/web-Node.js저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)