수업의 정상
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을 개발할 수 있다.
'3-1기 스터디 > 웹개발 기초' 카테고리의 다른 글
[웹개발 기초 스터디] React(1): Part2 (0) | 2021.12.24 |
---|---|
[웹개발 기초 스터디] React(1): Part1 (0) | 2021.12.24 |
[웹개발 기초 스터디]Node.js (1) (0) | 2021.11.17 |
[웹개발기초 스터디] Javascipt (1) | 2021.11.14 |
[2주차] Git : Part2 (0) | 2021.11.03 |
댓글