👩💻
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);
위 코드는 Node.js에서 작동하는 간단한 웹 서버를 생성하는 코드이다. 이 서버는 HTTP 모듈을 사용하여 요청을 처리하고, 파일 시스템 모듈(fs)을 사용하여 파일을 읽어 클라이언트에게 응답한다.
이 코드에서는 require
함수를 사용하여 http
모듈과 fs
모듈을 가져온다. http
모듈은 웹 서버를 생성하고, fs
모듈은 파일을 읽는데 사용된다.
그리고 http.createServer()
함수를 사용하여 서버를 생성한다. 이 함수는 콜백 함수를 인자로 받는다. 이 콜백 함수는 요청(request)과 응답(response)매개변수를 가지며, 클라이언트의 요청에 대한 응답을 처리한다.
콜백 함수에서는 먼저 request.url
을 검사하여 클라이언트가 요청한 URL을 확인한다. 만약 요청한 URL이 /
인 경우 url
변수를 /index.html
로 설정한다. 이는 기본 페이지로 사용 될 index.html 파일을 의미한다.
그 다음 /favicon.ico
를 요청한 경우, 404 상태 코드를 반환하고 함수를 종료한다. 이는 웹 브라우저가 파비콘을 요청하는 경우이다.
그 외의 모든 요청에 대해서는 200 상태 코드를 반환하고 fs.readFileSync()
함수를 사용하여 해당 파일을 동기적으로 읽은 후에 응답(response)으로 보낸다.__dirname + url
은 현재 실행 중인 스크립트 파일의 디렉토리와 요청한 URL을 조합하여 파일의 경로를 생성한다.
마지막으로, app.listen(3000)
을 호출하여 서버를 3000번 포트에서 실행한다. 이제 웹 서버가 해당 포트에서 요청을 대기하고 클라이언트에게 파일을 제공할 수 있다.
url 예시)
http
protocol 통신규칙, 사용자가 서버에 접속할 때 어떤방식으로 통신할 것인가에 대한 부분. 웹브라우저와 웹서버가 서로 데이터를 주고받기 위해서 만든 통신 규칙, 만약 FTP를 사용한다면 이 부분은 FTP가 된다.
opentutorials.org
host(domaim), 인터넷에 접속되어 있는 각각의 컴퓨터.
3000
port(포트번호). 한대의 컴퓨터안에 여러대의 서버가 있을 수 있다. 이럴 경우 클라이언트가 접속 했을 때 어떤 서버와 통신할지 애매하다. 그래서 접속할 때 포트번호를 지정해 그 포트번호와 연결된 서버에 접속하게 된다.
main
path. 컴퓨터안에 있는 어떤 디렉토리의 어떤 파일인지를 가리킨다.
id=HTML&page=12
quert string. 이 값을 변경하면 웹서버에게 데이터를 전달 할 수 있다. 그리하여 query string 앞에는 '?'가 붙고 값과 값은 '&'를 쓰기로 약속되어 있고 값의 이름과 값은 '='로 구분하기로 약속되어 있다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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);
위 코드에서는 요청한 URL을 통해 입력된 값을 사용할 수 있도록 코드가 추가되었다.
url
모듈은 URL 파싱에 사용된다.
parse() : URL 문자열을 입력하면 URL 객체를 만든다. 'format()'의 반대
request.url
을 통해 클라이언트가 요청한 URL을 가져온다. url.parse
함수를 사용하여 URL을 파싱하고, query
객체에서 id
속성을 가져온다. queryData.id
는 URL 쿼리 문자열에서 id라는 이름의 매개 변수의 값을 나타낸다.
위 코드와 같이 입력한다면 id 값은 HTML이 된다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
var app = http.createServer(function(request,response){
var _url = request.url;
var queryData = url.parse(_url, true).query;
var title = queryData.id;
if(_url == '/'){
title = 'Welcome';
}
if(_url == '/favicon.ico'){
return response.writeHead(404);
}
response.writeHead(200);
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);
});
app.listen(3000);
queryData.id
값을 title
변수에 저장한다. 이 값은 URL의 'id' 쿼리 매개 변수의 값을 나타내고, _url
이 /
인 경우 title
을 Welcome
으로 설정한다.
template
변수에는 HTML코드를 담았다. 이 HTML 코드는 서버가 클라이언트에게 반환하는 응답의 본문이다.
${title}
은 변수 title
의 값을 출력한다.response.end(template)
은 응답 헤더를 보내고, template
변수의 값을 응답 본문으로 전송하여 클라이언트에게 응답을 완료한다.
var fs = require('fs');
fs.readFile('sample.txt', 'utf8', function(err, data){
console.log(data);
});
이 코드는 Node.js에서 파일을 읽는 방법을 보여준다.
fs
모듈을 가져와서 readFile()
함수를 호출한다. readFile()
함수는 파일 이름, 인코딩 및 콜백 함수를 인수로 받는다. 콜백 함수는 파일 읽기 작업이 완료되면 호출되며 두 개의 인수인 에러와 데이터를 받는다. 오류가 없으면 data
인수는 파일의 내용을 포함하는 문자열이다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
var app = http.createServer(function(request,response){
var _url = request.url;
var queryData = url.parse(_url, true).query;
var title = queryData.id;
if(_url == '/'){
title = 'Welcome';
}
if(_url == '/favicon.ico'){
return response.writeHead(404);
}
response.writeHead(200);
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);
})
});
app.listen(3000);
fs
모듈의 readFile
함수를 사용하여 파일 시스템에서 데이터 파일을 읽어온다. 데이터 파일의 경로는 data/${queryData.id}
로 지정된다. ${queryData.id}
는 URL의 'id' 쿼리 매개 변수의 값을 나타낸다. 파일은 utf8
인코딩으로 읽혀지며, 콜백 함수에서 읽어온 데이터를 description
변수에 저장한다.
template
변수에 있는 HTML 코드의 <p>${description}</p>
부분은 description
변수에 저장된 데이터를 출력하는 부분이다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
var app = http.createServer(function(request,response){
var _url = request.url;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
var title = 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);
response.end(template);
});
} else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
pathname
변수를 사용하여 요청된 URL의 경로 부분을 추출한다. url.parse(_url, true).pathname
을 통해 얻어진다.
그리고 if(pathname === '/')
는 경로가 /
인 경우에만 파일 읽기 및 응답을 처리하는 로직을 실행하고, 경로가 /
가 아닌 경우에는 404 오류 응답을 반환한다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
var app = http.createServer(function(request,response){
var _url = request.url;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
if(pathname === '/'){
if(queryData.id === undefined){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = 'Welcome';
var description = 'Hello, Node.js';
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);
response.end(template);
});
} else {
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>
<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);
response.end(template);
});
}
} else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
pathname에 따른 분기처리 후, queryData.id
의 유무를 추가로 확인해 응답을 처리한다.
if (queryData.id === undefined)
는 queryData.id
가 정의되지 않은 경우에 대한 처리이다. 즉, URL에 id
쿼리 매개 변수가 없는 경우를 의미한다. 이 경우에는 기본적인 환영 메세지를 표시하는 HTML 응답을 보낸다.
var testFolder = './data';
var fs = require('fs');
fs.readdir(testFolder, function(error, filelist){
console.log(filelist);
})
이 코드는 testFolder
폴더에 있는 모든 파일의 목록을 출력해준다.
var testFolder = './data';
는 testFolder라는 이름의 폴더를 가리키는 문자열을 생성.var fs = require('fs');
는 fs 모듈을 가져옴.fs.readdir(testFolder, function(error, filelist){...}
는 fs 모듈의 readdir()
함수를 호출. 이 함수는 testFolder 폴더에 있는 모든 파일의 이름을 배열로 반환.Node.js에서 파일 입출력 처리를 할 때에는 fs모듈을 사용한다. fs모듈에는 파일 읽기, 쓰기, 삭제등 파일관련 기능을 제공한다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
var app = http.createServer(function(request,response){
var _url = request.url;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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);
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);
response.end(template);
});
});
}
} else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
fs.readdir('./data', function(error, filelist){})
는 ./data
디렉토리에서 파일 목록을 가져오는 기능을 추가한다. 이를 통해 파일 목록을 반복하고, 각 파일에 대한 링크를 생성하여 페이지의 목차 부분에 표시할 수 있다.
list
변수는 파일 목록을 가지고 <ul>
태그를 생성한다. while
루프를 사용해 파일 목록을 반복하고, 각 파일에 대한 링크를 <li>
태그로 생성하여 list
변수에 추가한다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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;
}
var app = http.createServer(function(request,response){
var _url = request.url;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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>${description}`);
response.writeHead(200);
response.end(template);
})
} else {
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`);
response.writeHead(200);
response.end(template);
});
});
}
} else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
코드의 가독성과 재사용성을 높이기 위해 templateHTML
, templateList
함수를 생성하였다.
templateHTML
함수는 HTML 템플릿을 생성하는 역할을 한다. title
, list
, body
를 매개변수로 받아 템플릿에 적용해 완전한 HTML 문자열을 반환한다.templateList
함수는 파일 목록을 기반으로 목차를 생성하는 역할을 한다. fileList
를 매개변수로 받아 파일 목록을 반복하고 각 파일에 대한 링크를 생성해 <ul>
태그로 둘러싼 문자열을 반환한다.이처럼 함수로 분리하여 중복 코드를 제거하고 코드의 가독성과 재사용성이 개선됐다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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>${description}`);
response.writeHead(200);
response.end(template);
});
} else {
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`);
response.writeHead(200);
response.end(template);
});
});
}
} 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/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 기능이 추가됐다. create 페이지를 생성하여 사용자가 제목과 설명을 입력할 수 있는 양식을 제공하고, 제출 시 해당 내용을 처리하는 기능이 구현됐다.
새로운 페이지 생성을 위해 /create
경로가 추가되었다. 접근 시 사용자가 제목과 설명을 입력할 수 있는 양식이 표시된다.
templateHTML
함수가 수정되어 새로운 페이지 생성 양식을 포함하도록 변경됐다. 새로운 양식은 title
과 description
필드가 있는 <form>
태그로 구성되어 있으며, submit 버튼 클릭시 process_create
경로로 데이터가 전송된다.
해당 코드에서는 /process_create
경로는 아직 구현되어 있지 않으므로 아무런 동작이 수행되진 않는다.
app
서버 리스너 내에 /create
경로에 대한 조건문이 추가되었다. 이 조건문은 /create
경로에 대한 요청을 처리하며, 파일 목록과 함께 templateHTML
함수를 사용하여 새로운 페이지 생성 양식을 포함한 HTML 템플릿을 생성한다.
하여 이전 코드의 기능을 유지하면서 create 페이지를 추가하여 사용자가 새로운 페이지를 생성할 수 있는 기능을 제공한다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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>${description}`);
response.writeHead(200);
response.end(template);
});
} else {
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(title, list, `<h2>${title}</h2>${description}`);
response.writeHead(200);
response.end(template);
});
});
}
} 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);
response.end(template);
});
} else if(pathname === '/create_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 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);
create 기능을 완전히 구현하였다. 사용자가 제목과 설명을 입력하고 제출하면 해당 내용을 파일로 저장하는 기능이 추가됐다.
qu
모듈을 추가, 사용하여 POST 요청의 본문(body)데이터를 파싱한다. 이를 통해 사용자가 입력한 제목과 설명을 추출할 수 있다.
/create_process
경로에 대한 조건문이 추가되었다. 이 조건문은 POST 요청의 본문 데이터를 수신하고, 해당 데이터를 파싱하여 제목과 설명을 추출한다. 그 후, 추출한 데이터를 사용하여 새로운 파일을 생성하고, 생성된 파일로 리다이렉트 한다.
fs.writeFile
함수를 사용하여 추출한 제목을 파일 이름으로, 추출한 설명을 파일 내용으로 하는 파일을 생성한다.
이렇게 변경된 코드는 create 페이지에서 제목과 설명을 입력받아 파일로 저장하는 기능을 완성한다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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>${description}`,
`<a href="/create">create</a>`
);
response.writeHead(200);
response.end(template);
});
} else {
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(title, list,
`<h2>${title}</h2>${description}`,
`<a href="/create">create</a> <a href="/update?id=${title}">update</a>`
);
response.writeHead(200);
response.end(template);
});
});
}
} 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);
response.end(template);
});
} else if(pathname === '/create_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 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);
update 기능을 추가하였다. 사용자는 특정페이지에서 update 링크를 클릭해 해당 페이지의 제목과 내용을 수정할 수 있다.
templateHTML
함수에 control
매개변수를 추가해 페이지 상단에 표시되는 추가 컨트롤 요소를 나타냈다. 이것으로 create링크와 update링크를 표시하는 데 사용된다.
/
경로에서 특정페이지를 표시할 때, 해당 페이지의 제목과 내용 아래에 update 링크가 추가되었다. 이 링크는 해당 페이지의 내용을 수정하는 페이지로 이동하는 역할을 한다.
/update
경로를 추가하여 특정 페이지의 제목을 수정할 수 있는 페이지로 이동한다. 수정된 제목을 받아와 해당 페이지의 내용을 수정할 수 있게된다.
fs.writeFile
함수 호출 시 Location
헤더의 URL이 변경된다. 그리하여/?id=${title}
형식으로 리다이렉트되어 해당 페이지의 내용이 수정된 것을 표시한다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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>${description}`,
`<a href="/create">create</a>`
);
response.writeHead(200);
response.end(template);
});
} else {
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(title, list,
`<h2>${title}</h2>${description}`,
`<a href="/create">create</a> <a href="/update?id=${title}">update</a>`
);
response.writeHead(200);
response.end(template);
});
});
}
} 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);
response.end(template);
});
} else if(pathname === '/create_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 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 title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(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>`
);
response.writeHead(200);
response.end(template);
});
});
} else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
update
경로에 대한 조건문이 추가되었다. 해당 경로에서는 기존 페이지의 내용을 수정할 수 있는 양식이 표시된다. 이 때, 양식의 각 입력 필드에는 기존 제목과 내용이 미리 입력되어 있다.
update
양식을 제출하면 /update_process
경로로 POST 요청이 전송된다. 이 경로에서는 제출된 내용을 받아와 해당 페이지의 제목과 내용을 수정하고, 수정된 내용을 파일에 저장한다.
input
요소의 type="hidden"
를 추가하여 수정할 페이지의 제목을 식별한다. 이 input
요소는 사용자에게 표시되지 않고 양식을 제출할 때 전송된다.
이로인해 update 기능을 추가하여 사용자가 페이지의 내용을 수정할 수 있도록 한다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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>${description}`,
`<a href="/create">create</a>`
);
response.writeHead(200);
response.end(template);
});
} else {
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(title, list,
`<h2>${title}</h2>${description}`,
`<a href="/create">create</a> <a href="/update?id=${title}">update</a>`
);
response.writeHead(200);
response.end(template);
});
});
}
} 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);
response.end(template);
});
} else if(pathname === '/create_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 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 title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(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>`
);
response.writeHead(200);
response.end(template);
});
});
} 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 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){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
});
} else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
fs.rename
함수를 추가해 수정된 페이지의 파일명을 변경한다. 이 함수는 기존 파일명 id
를 새 파일명 title
로 변경한다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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>${description}`,
`<a href="/create">create</a>`
);
response.writeHead(200);
response.end(template);
});
} else {
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(title, list,
`<h2>${title}</h2>${description}`,
` <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);
response.end(template);
});
});
}
} 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);
response.end(template);
});
} else if(pathname === '/create_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 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 title = queryData.id;
var list = templateList(filelist);
var template = templateHTML(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>`
);
response.writeHead(200);
response.end(template);
});
});
} 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 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){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
});
} 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;
fs.unlink(`data/${id}`, function(error){
response.writeHead(302, {Location: `/`});
response.end();
})
});
} else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
delete 기능을 추가하였다.
/delete_process
경로를 추가하여 삭제 작업을 처리할 수 있다. 해당 경로로 POST 요청이 전송되면 해당 파일을 삭제하는 작업이 수행된다.
각 페이지에 삭제버튼이 추가됐다. 사용자는 삭제 버튼을 클릭하여 해당 페이지를 삭제할 수 있다. 삭제 버튼은 /delete_process
경로로 제출된다.
fs.unlink
함수를 추가하여 파일을 삭제한다. 이 함수는 파일을 제거한다.
수정된 페이지에는 create, update, delete 버튼이 함께 표시된다. 사용자는 수정 버튼을 통해 페이지를 수정하고, 삭제 버튼을 통해 페이지를 삭제할 수 있다.
👩💻
var http = require('http');
var fs = require('fs');
var url = require('url');
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;
var queryData = url.parse(_url, true).query;
var pathname = url.parse(_url, true).pathname;
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>${description}`,
`<a href="/create">create</a>`
);
response.writeHead(200);
response.end(html);
});
} else {
fs.readdir('./data', function(error, filelist){
fs.readFile(`data/${queryData.id}`, 'utf8', function(err, description){
var title = queryData.id;
var list = template.list(filelist);
var html = template.HTML(title, list,
`<h2>${title}</h2>${description}`,
` <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);
response.end(html);
});
});
}
} 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);
response.end(html);
});
} else if(pathname === '/create_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 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 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>`
);
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 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){
response.writeHead(302, {Location: `/?id=${title}`});
response.end();
})
});
});
} 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;
fs.unlink(`data/${id}`, function(error){
response.writeHead(302, {Location: `/`});
response.end();
})
});
} else {
response.writeHead(404);
response.end('Not found');
}
});
app.listen(3000);
template
객체를 사용하여 기존의 templateHTML
, templateList
함수를 HTML
, list
라는 두 개의 메서드로 변경했다. 이 메서드는 HTML과 파일목록을 생성하는 역할을 한다.
최종적으로 이 코드는 CRUD 기능을 제공하며, 요청된 경로에 따라 적절한 응답을 생성한다.