1️⃣ 웹이 등장한 직후 여러가지 불만들이 쏟아져 나왔다.
수많은 html을 직접 타이핑해서 직접 웹페이지를 수정하는 것에 지침.
방문자들이 마음대로 글을 올리게 하고 싶었지만 그들에게 직접 html의 수정 권한을 주는 것은 위험했고
➡️ 곧 성장의 한계에 직면하게 됐다.
2️⃣ 선구자들 : 귀찮고 반복적인 html 작업은 기계에게 시키자..
3️⃣ 1995년 : 넷스케이프사에서 브랜든 아이크에게 자바스크립트의 제작을 의뢰 => 자바스크립트 탄생.
(웹은 사람과 상호작용하는 애플리케이션의 면모를 갖추게 됨.)
4️⃣ 2008년 : 구글이 크롬 웹브라우저에서 동작하는 자바스크립트의 성능을 개선하기 위해 V8엔진을 개발 후 오픈소스로 공개
라이언달은 V8을 기반으로 하는 Node.js를 탄생시킨다.
(태초의 자바스크립트가 웹브라우저를 제어하는 것이었다면 Node.js는 자바스크립트를 이용해서 웹브라우저가 아닌 컴퓨터 자체를 제어한다. 마치 Python, Java, PHP, 루비가 그런 것처럼.)
웹개발자들은 자신들에게 이미 익숙한 자바스크립트를 이용해서 웹페이지를 자동으로 생성하는 웹 애플리케이션을 만들고 싶어했다.
웹개발자들은 Node.js에 열광했고 웹브라우저라는 울타리에 갇혀있던 자바스크립트는 빠른 속도로 웹브라우저 밖으로 팽창하기 시작했다.
자바스크립트를 이용해서 웹페이지를 찍어내는 거대한 공장인 Node.js의 공장장이 되어 보자.
HTML을 코딩하는 지루한 일은 공장에게 맡기자.
위 그림과 같은 홈페이지가 있다고 가정해보자.
<!doctype html>
<html>
<head>
<title>WEB1 - HTML</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="index.html">WEB</a></h1>
<ol>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ol>
<h2>HTML</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>
소스 코드는 다음과 같고 누군가가 웹페이지의 목록 부분의 번호를 지워달라고 요청했을 때
Node.js가 없다면 우리는 모든 웹페이지의 <ol>
태그를 <ul>
로 바꿔야 한다.
지금이야 바꿀 웹페이지가 4개 밖에 없어서 다행이지만 수정해야 할 웹페이지가 무수히 많다면 엄청난 고생을 하게 될 것이다.
Node.js를 이용한다면 우리는 비슷한 웹페이지를 무수히 제작할 필요가 없다.
사용자가 어떤 페이지를 요청할 때 마다 Node.js와 같은 기술로 그 순간순간에 원하는 웹페이지를 생성한다.
Node.js를 사용하면 사용자의 참여(읽기, 쓰기, 수정, 삭제)를 가능하게 한다.
(Node.js의 경쟁관계 : PHP, JSP, Python의 Django 루비의 루비온레일즈 등등..)
Nodejs란 무엇인가?
웹브라우저 위에서 동작하는 웹 애플리케이션이라는 것을 만들게 된다.
HTML이라는 언어를 통해 웹 애플리케이션 제작.
Node.js도 마찬가지 원리이다.
Node.js 런타임을 설치해서 실행시킨다. (웹브라우저 역할.)
자바스크립트라는 언어를 이용해서 Node.js 애플리케이션 제작.
Nodejs - 3.2.설치 (MacOS)
Node.js 들어가서 안정된 버전 설치.
terminal 접속 => node -v 입력해보자 => 버전이 뜰 것.
node를 입력해서 간단한 프로그램 실행 가능.
나갈 때는 ctrl + c 두번 입력.
Node.js는 웹서버 기능을 내장하고 있기 때문에 웹서버로 사용 가능하다.
터미널을 통해 생활코딩 실습 폴더에 들어가서 node main.js를 입력한 뒤
웹브라우저에 http://localhost:3000/ 를 입력해서 들어가보자.
ctrl + c를 입력하여 node.js를 중단시킨뒤 다시 http://localhost:3000/ 에 들어가보자.
➡️ node.js가 웹서버로 동작함을 확인할 수 있다.
console.log(__dirname + url);
을 입력하고 저장한 뒤에 터미널로 node main.js를 입력하여 작동시켜 보자.
다음과 같이 디렉토리명 + 요청한 파일의 이름이 출력된다.
웹브라우저에 들어가서 다른 링크를 클릭해서 다른 html 파일을 요청해보자.
다음과 같이 요청한 파일이 출력된다. (즉 우리가 읽어들어야 할 파일들을 그때 즉시 찍어내는 것이다.)
__dirname + url
을 통해 사용자가 특정 파일에 접근할 때마다 그 경로를 설정해준다.
Node.js의 기능인 fs.readFileSync()
를 통해 __dirname + url
을 통해 설정된 경로의 파일을 가져온다.
response.end()
안의 내용을 사용자에게 전송한다.
즉 프로그래밍적으로 사용자에게 전송할 데이터를 설정한다.
(Apache는 할 수 없고 Django나 PHP, Node.js 는 할 수 있는 것.)
우리의 목표 : 자바스크립트를 이용해서 Node.js가 갖고 있는 기능을 호출하여 우리가 웹 애플리케이션을 Node.js로 만들 수 있게하는 것.
이제 Node.js의 영역으로 넘어가서 웹 애플리케이션을 구현하는 아주 중요한 스킬을 알아보자.
➡️ 주인공은 url 이다.
강의에 나오는 웹페이지를 살펴보자.
양측의 파일명을 같지만 (Viewtopic.php) 그 뒤에 나오는 숫자 (453376 vs 2111378) 가 다르다.
Viewtopic.php 즉 php라는 애플리케이션이 뒤에 나오는 숫자를 통해 웹브라우저(클라이언트)에게 서로 다른 웹페이지를 생성하여 보내고 있는 것이다.
url의 형식 :
protocol : 통신규칙
➡️ 사용자가 서버에 접속할 때 어떤 방식으로 통신할 것인가에 대한 부분.
HTTP : (Hyper Text Transfer Protocol) 웹서버와 웹브라우저가 서로 데이터를 주고 받기 위해서 만든 통신 규약.
(FTP라는 통신규약도 있다.)
host (domain) : 호스트
➡️ 인터넷에 접속되어 있는 각각의 컴퓨터를 호스트라고 부른다.
(opentutorials.org)는 특정 인터넷에 접속되어 있는 컴퓨터를 가리킨다.
port : 포트 번호
➡️ 한 대의 컴퓨터 안에 여러대의 서버가 있을 수 있다. 클라이언트가 접속했을 때 그 중의 어떤 서버와 통신해야 할지 정한다. 3000번 포트에 있는 서버와 통신한다.
3000번 포트에 우리의 node.js 웹서버를 실행시킨 것이다.
그래서 접속 할 때 3000 이라고 명시하는 것.
포트번호를 80이라고 해보자.
포트번호를 지정해주지 않아도 된다.
웹서버는 굉장히 유명한 서버기 때문에 웹서버는 80번 포트를 쓴다라고 전세계적으로 약속되어 있기 때문에
만약 우리가 http를 통해 접속 했다 : 그건 웹서버에 접속 한 것이기 때문에 포트번호를 빼고 접속하면 자동으로 80번 포트와 통신한다.
path : 파일
➡️ 어떤 파일인지를 가리킨다.
query string : 쿼리 스트링
➡️ 얘가 이번 수업의 주인공
: 쿼리스트링의 값을 변경하면 웹서버에게 어떤 데이터를 전달 할 수 있다.
(?id=HTML&page=12) : 내가 읽고 싶은 정보는 HTML이고 12페이지다.
이렇게 전달 가능하다.
① 쿼리스트링의 시작은 ?
로 하기로 약속했다.
② 값과 값은 &
로 구분한다.
③ 값의 이름과 값은 =
로 구분한다.
다음시간에는 쿼리스트링의 값에 따라서 node.js를 통해 만든 웹서버가 사용자에게 동적으로 생성한 정보를 전송하는 방법을 소개하겠다.
본격적으로 웹 애플리케이션을 만들어 보자.
위 주소로 사용자가 웹 애플리케이션에 접속을 했을 때 우리가 해야할 일은 저 id값 이 무엇이냐에 따라서 사용자에게 적당한 컨텐츠를 보여주는 것이다.
저 분홍색 부분을 쿼리스트링이라 한다.
쿼리스트링에 따라 다른 정보를 보여주는 것을 해보자.
url parse query string
검색 후에 답변을 우리의 main.js 파일에 적용해보자
javascript - Parsing Query String in node.js - Stack Overflow
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);
console.log(_url);
if(_url == '/'){
_url = '/index.html';
}
if(_url == '/favicon.ico'){
return response.writeHead(404);
}
response.writeHead(200);
response.end(fs.readFileSync(__dirname + _url));
});
app.listen(3000);
터미널에 node main.js
입력하여 실행시킨 후 브라우저에 http://localhost:3000/?id=html
입력하여 서버에 접속하면 터미널 창에 다음과 같이 뜬다.
url
모듈을 통해 받은 객체의 parse
메소드의 parameter로 _url
을 넣어 실행하여 리턴된 queryData
가 의미하는 것은 다음과 같은 객체인 것이다.
✅ { id: 'html' }
다음과 같이 end
메서드 부분의 인자를 queryData.id
로 바꾸면 쿼리스트링에 따라서 다른 정보를 출력해 줄 수 있다.
이전 시간에 쿼리스트링에 따라서 다르게 동작하는 node j.s 애플리케이션을 만들어봤다.
우리의 목표 : 그럼 이제 쿼리스트링에 따라서 다르게 표현되는 완성된 웹페이지를 만들어보자
일단 정적인 페이지의 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;
console.log(queryData.id);
if(_url == '/'){
_url = '/index.html';
}
if(_url == '/favicon.ico'){
return response.writeHead(404);
}
response.writeHead(200);
var template = `
<!doctype html>
<html>
<head>
<title>WEB1 - HTML</title>
<meta charset="utf-8">
</head>
<body>
<h1><a href="index.html">WEB</a></h1>
<ol>
<li><a href="1.html">HTML</a></li>
<li><a href="2.html">CSS</a></li>
<li><a href="3.html">JavaScript</a></li>
</ol>
<h2>HTML</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(queryData.id);
});
app.listen(3000);
그리고 동적으로 바꾸고 싶은 부분들을 다음과 같이 처리한다.
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;
console.log(title);
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>
<ol>
<li><a href="/?id=HTML">HTML</a></li>
<li><a href="/?id=CSS">CSS</a></li>
<li><a href="/?id=JavaScript">JavaScript</a></li>
</ol>
<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);
아저씨 저 숫자로 된 리스트목록 숫자 없애주세요~
var template = `
// ...
<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>
`
위와 같이 template
의 ol
만 ul
로 변경해준다.
이렇게 하면 모든 페이지의 리스트 스타일이 변경된다.ㅎㅎ
제목부분은 동적으로 바뀌고 있지만 본문은 여전히 정적이다.
본문을 파일에 본문만 저장하고 사용자의 요청이 들어왔을 때 그 요청에 해당하는 파일의 본문만을 읽어서 우리가 만든 template
만 가져다 넣을 수 있다면..
이건 다음 시간에 알아보자~
이제부터 node.js에서 파일을 다루는 방법을 알아보자
4가지의 처리가 정보를 다루는 핵심적인 처리이다.
먼저 파일을 어떻게 하면 node.js로 읽을까
를 살펴보고
그 다음 어떻게 파일을 생성, 수정, 삭제를 node.js로 하는 법을 차차 알아볼 예정 ㅎㅎ
node.js file read
로 검색해보자
공식문서를 통해 사용법을 익힐 수 있다.
지금까지 배운 것을 총 동원해서 쿼리스트링에 따라 본문이 변경되는 웹 애플리케이션을 만들어보자.
강의 폴더 내부에 data
라는 폴더 만들고 그 안에 각각 HTML
, CSS
, JavaScript
라는 이름의 파일들을 만들어서 p
태그 내부의 본문들을 각각의 파일들에 넣어주자.
쿼리스트링의 값에 따라서 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;
console.log(title);
if(_url == '/'){
title = 'Welcome';
}
if(_url == '/favicon.ico'){
return response.writeHead(404);
}
response.writeHead(200);
fs.readFile(`data/${queryData.id}`, 'utf-8', (err, description) => {
const 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);
조건문을 투입해서 우리의 애플리케이션을 좀 더 정교하고 쓸만한 것으로 만들어보자
url.parse(_url, true)
가 반환하는 것은 무엇일까?
반환된 Url
객체에서 pathname
프로퍼티는 쿼리스트링은 제외한 path만을 보여준다.
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}`, 'utf-8', (err, description) => {
const 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);
조건문을 통해 홈부분을 분리했다.
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) {
fs.readFile(`data/${queryData.id}`, 'utf-8', (err, description) => {
var title = 'Welcome';
var description = 'Hello Node JS';
const 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}`, 'utf-8', (err, description) => {
var title = queryData.id;
const 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);