반응형
SMALL
Node js
URL
http://opentutorials.org:3000/main?id=HTML&page=12
http
= protocol : 웹브라우저와 웹서버가 데이터를 주고받기 위해 만든 통신규칙opentutorials.org
= host(domain) : 인터넷에 접속되어 있는 각각의 컴퓨터(특정한 인터넷에 연결되어있는 컴퓨터를 가리키는 주소)3000
=port : 접속할 때, 3000번 포트에 연결되어 있는 서버와 통신하게 됨(port 기본 값=80)main
=path : 컴퓨터 안에 있는 어떤 디렉토리에 어떤 파일인지 가리킴id=HTML&page=12
=query string : 웹서버에게 보내고 싶은 데이터 전달- 쿼리스트링의 시작은
?
- 값과 값은
&
로 연결 - 값의 이름과 값은
=
로 구분
Template Literal
- var (변수이름)=
(HTML 코드)
를 통해 HTML styling 가능 ${ }
: template내에 변수 사용
동기 vs 비동기
- 동기적: 순차적으로 해결
- 비동기적: 병렬적으로 여러가지 동시 해결
package manager
- 패키지 매니저(Package manager)는 패키지를 다루는 작업을 편리하고 안전하게 수행하기 위해 사용되는 툴- pm2 사용
pm2 start main.js --watch
- 이전에는 main.js를 수정하면 ctrl+s 후, cmd 창에서 ctrl+c를 눌러야 수정 내용이 반영됐었지만, 이 명령어 실행 후, 웹 서버에서 f5만 누르면 바로 반영됨
pm2 log
- cmd에 문제점 바로 보여줌
Form
(문제 : readdir를 통해 data directory에 접근할 수 있는 것은 자기 자신 뿐이기 떄문에 컨텐츠의 생성은 소유자밖에 못함 )
- Form : 사용자가 서버 쪽으로 데이터를 전송하기 위한 방식
- 누구나 웹을 통해 데이터를 전송하면 사용자가 컨텐츠를 생성하고 삭제할 수 있게 함
<form action="http://localhost:3000/process_create" method="post">//사용자가 입력한 정보를 action에 입력한 서버로 전송
<p><input type="text" name="title"></p> //글씨를 입력할 수 있음
<p>//본문에 여러줄 입력 가능한 태그
<textarea name="description"></textarea>
</P>
<p><input type="submit"></p> //사용자가 입력을 끝낸 후, 전송하는 버튼
</form>
//입력한 각각의 값들이 이름이 있어야 서버 쪽에서 받았을 때 의미가 있기 때문에 name으로 정의해줘야함
서버에서 데이터를 가져올 때에는 ?를 이용하는 쿼리스트링 형태로 사용 (method="get",default 값이기 때문에 생략 가능 )
서버의 데이터를 수정하는 행위를 할 때에는 method="post" 라는 형식을 붙여줘서 user들이 submit해서 들어온 경우에는 서버주소에 쿼리스트링이 보이지 않도록 해줌
- form이라는 태그는 form안에 사용자가 입력한 각각의 정보를 submit버튼을 눌렀을 때, action속성이 가리키는 서버로 쿼리스트링의 형태로 데이터를 전송하는 기능
객체 Vs 배열
- 공통점 : 정보를 정리정돈하는 도구
- 배열: 순서에 따라서 정리를 하고 숫자로 구분을 함 (literal [ ])
- 객체: 순서가 없음, 숫자가 아닌 각각의 고유한 이름으로 구분 가능 (literal { })
//array 반복문 호출
var members=['egoing','k8805','hoya'];
var i=0;
while(i<members.length){
console.log(members[i]);
i+=1;
}
//object 반복문 호출
var roles={
'programmer':'egoing',
'designer':'k8805',
'manager':'hoya'}
for(var name in roles){
console.log('object =>',name,'value =>',roles.name);
}
객체지향 프로그래밍
- js에서 함수는 처리방법들을 담는 구문이면서 함수 자체가 값이 될 수 있다.
- 객체는 값을 담는 그릇처럼 사용
- 함수가 객체 안에서 사용될 때, 함수가 자신이 속한 객체를 참조할 수 있는 경우 this라는 키워드 사용
- 코드의 복잡성을 줄일 수 있음
Module
- 객체를 정리정돈할 수 있는 가장 큰 도구
<mpart.js>
:module 파일
var M={
v:'v',
f:function(){
console.log(this.v);
}
}
module.exports=M;
//M의 객체를 외부에서 사용할 수 있도록 export 하겠다는 뜻
<muse.js>
:module 사용할 파일
var part=require('./mpart.js');
//mpart.js의 모듈을 part라는 변수에다 담음
part.f();//mpart.js의 M객체에서 f라는 함수를 사용할 때
API (Application Programming Interface)
- Application을 Programming하기 위해 제공되는 Interface(언어가 가진 여러가지 기능, 장치들)
- 그 언어가 가지고 있는 조작 장치가 궁금하다면 API를 검색해야함
<main.js>
: 전체 코드
var http = require('http');
var fs = require('fs');
var url=require('url');//url이라는 모듈 사용한다는 것
var qs=require('querystring');
var template=require('./lib/template.js');//tenplate.js의 module사용
var path=require('path');
var sanitizeHtml=require('sanitize-html');//웹을 변경시킬 수 있는 예민한 태그들을 text로 쓰면 제거해버리는 효과
var app = http.createServer(function(request,response){
/*
createServer: 웹서버를 만들고 웹서버에서 요청이 들어올때마다 첫번째 인자에 해당되는 함수를 호출
웹브라우저 들어올때마다 createServer의 callback함수를 nodejs가 호출 `function(request,response){}`
request: 요청할 때 웹브라우저가 user에게 보낸 정보들 담겨 있음
response: 응답할 때 user가 웹브라우저에게 전송할 정보들 담겨 있음
*/
var _url = request.url;
var queryData=url.parse(_url,true).query;
var pathname=url.parse(_url,true).pathname;//어떤 경로로 들어왔는지 확인
if(pathname==='/'){//route일 때
if(queryData.id===undefined){//id 없는 home 말하는 것
fs.readdir('./data',function(error,filelist){//data 폴더에 있는 파일들을 읽어 filelist라는 배열로 만듦
var title='Welcome!';
var description='Hello, Node.js';
var list=template.List(filelist);
var html=template.HTML(title,list,`<h2>${title}</h2>${description}`,
`<a href="/create">create</a>]`);
response.writeHead(200);//200이라는 숫자를 서버가 브라우저에게 주면 파일을 성공적으로 전송했다는 뜻
response.end(html);//웹에 template출력
});
} else{
fs.readdir('./data',function(error,filelist){//data 폴더에 있는 파일들 이름을 filelist라는 배열로 만듦
var filteredId=path.parse(queryData.id).base; //정보보안을 위해 데이터중 base만 전달
fs.readFile(`data/${filteredId}.txt`, 'utf8',
function(err,description){
var list=template.List(filelist);
var title=queryData.id;
var sanitizedTitle=sanitizeHtml(title);
var sanitizedDescription=sanitizeHtml(description);//태그들을 못쓰도록 살균, allowedTags안에 들어있는 태그들은 사용 가능
var html=template.HTML(sanitizedTitle,list,
`<h2>${sanitizedTitle}</h2> ${sanitizedDescription}`,
`<a href="/create">create</a>
<a href="/update?id=${sanitizedTitle}">update</a>
<form action="delete_process" method="post">
<input type="hidden" name="id" value="${sanitizedTitle}">
<input type="submit" value="delete">
</form>`);
response.writeHead(200);
response.end(html);
});
});
}
/*
웹주소에서 id값을 바꾸면 ${title}라고 한 부분, 전체 바뀜
<a href="/?id=CSS"> :href 부분에 id값을 쓰면 그 태그 눌렀을 때,id 값이 바껴서 웹주소 id부분과 title 모두 바뀜
fs.readFile에서 변수 description으로 받았기 때문에 ${}시 해당되는 부분의 본문 출력
*/
} else if(pathname==='/create'){//create 눌렀을 때
fs.readdir('./data',function(error,filelist){
var title='Web - create';
var list=template.List(filelist);
var html=template.HTML(title,list,`
<h2>${title}</h2>
<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>
`,'');//form 을 body에 배치
response.writeHead(200);
response.end(html);
});
} else if(pathname==='/create_process'){//create 창에서 submit 버튼 누른 경우
var body='';
request.on('data',function(data){
//웹브라우저가 post방식으로 전송되는 데이터가 많은 경우를 대비해 request.on 사용
//특정한 양을 수신할 때마다 서버는 콜백함수인 function(data)를 호출해 data라는 인자를 통해 수신한 정보를 주가로 약속
body=body+data;
});
request.on('end',function(){
//더이상 들어올 데이터가 없으면 이 end 뒤의 callback 함수가 실행되도록 약속
var post=qs.parse(body); //post데이터에 지금까지 입력한 data들 들어있는 body를 저장해서 객체화 시킴
var title=post.title;
var description=post.description;
fs.writeFile(`data/${title}.txt`,description,'utf8',function(err){
console.log(description);
response.writeHead(302,{Location:`/?id=${title}`}); //Location으로 redirecrion(파일이 data에 저장되고 바로 서버로 이동)
response.end();
});
});
}else if(pathname==='/update'){
fs.readdir('./data',function(error,filelist){
var filteredId=path.parse(queryData.id).base;
fs.readFile(`data/${filteredId}.txt`, 'utf8',
function(err,description){
var title=queryData.id;
var list=template.List(filelist);
var html=template.HTML(title,list,`
<form action="/update_process" method="post">
<input type="hidden" name="id" 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>
`,
`<a href="/create">create</a> <a href="/update?id=${title}">update</a>`);
/*
html의 input 태그는 value라는 속성에 props 넣어주면 기본값으로 그 props가 들어가게됨
name="id"는 update한 내용을 기존title에 보내기 위해 기존 title과 update된 title을 구분시키려고 만듦(user에게 보일 필요 없으니 type=hidden)
*/
response.writeHead(200);
response.end(html);
});
});
} else if(pathname==='/update_process'){
var body='';
request.on('data',function(data){
body=body+data;
});
request.on('end',function(){
var post=qs.parse(body);
var title=post.title;
var id=post.id;
var description=post.description;
fs.rename(`data/${id}.txt`,`data/${title}.txt`,function(error){
fs.writeFile(`data/${title}.txt`,description,'utf8',function(err){
response.writeHead(302,{Location:`/?id=${title}`}); //Location으로 redirecrion(파일이 data에 저장되고 바로 서버로 이동)
response.end();
});
})
console.log(post);
});
} else if(pathname==='/delete_process'){
var body='';
request.on('data',function(data){
body=body+data;
});
request.on('end',function(){
var post=qs.parse(body);
var id=post.id;
var filteredId=path.parse(id).base;
fs.unlink(`data/${filteredId}.txt`,function(error){
response.writeHead(302,{Location:`/`});//redirection home으로 감
response.end();
})
});
} else{//path가 없는 경로로 접속했다면
response.writeHead(404);//파일을 찾을 수 없는 경우
response.end('Not found');
}
});
app.listen(3000);//요청에 대해서 응답할 수 있도록 http 서버를 구동시킴
반응형
LIST