1) Node.js란?
Node.js는 Chrome V8 JavaScript 엔진으로 빌드 된 JavaScript 런타임이다.
1-1) Node.js 설치(MAC)
① node js 홈페이지 - https://nodejs.org/en/download 에서 mac 버전 설치
② 설치 후 터미널에 입력하여 버전 확인
node -v
1-2) REPL
node
를 입력하면 REPL 환경으로 접속이 가능하다.1-3) npm
< npm 사용법 >
npm init
// 프로젝트를 시작할 때 사용하는 명령어
// package.json에 기록될 내용을 문답식으로 입력한다.
npm init --yes
// package.json이 생성될 때 기본 값으로 생성된다.
npm install 패키지 이름
// 프로젝트에서 사용할 패키지를 설치하는 명령어
// 설치된 패키지의 이름과 정보는 package.json의 dependencies에 입력된다.
1-4) package.json
2) Node.js 특징
① 자바스크립트 언어 사용
-> 즉, 자바스크립트 프로그램을 컴퓨터에서 실행할 수 있게 하는 자바스크립트 실행기이다.런타임이란?
프로그래밍 언어가 구동되는 환경이다.
② Single Thread
- 프로세스: 실행 중인 프로그램이며, 운영체제에서 할당하는 작업의 단위이다.
- 스레드: 프로세스 내에서 실행되는 흐름의 단위이며, 프로세스는 스레들를 여러 개 생성하여 여러 작업을 동시에 처리할 수 있다. 또한 같은 주소의 메모리에 접근 가능하므로, 데이터를 공유할 수 있다.
③ Non-blocking I/O
I/O(입출력) : input(입력) / output(출력)
I/O 작업과 같이 자바스크립트 바깥에서 이뤄지는 작업이 끝날 때까지 기다리는 게 아니라, 해당 작업을 실행시키고 나면 그 작업이 완료될 때까지 기다리지 않고 곧바로 다음 작업을 수행하는 방식이다.
블로킹(blocking) 이란?
- 자바스크립트 바깥에서 실해아 가능한 작업을 기다리느라 자바스크립트 코드가 멈춰있는 상황이다.
cf) 싱글스레드 블로킹 모델
: 프로세스 내에서 하나의 스레드가 하나의 요청만을 수행하는데, 해당 요청이 수행될 때 다른 요청을 함께 수행할 수 없다. 진행되고 있는 요청이 예정되어 있는 요청을 블로킹하기 때문이다.
즉, node.js는 동시에 많은 요청들을 비동기로 수행함으로써 싱글 스레드일지라도 논블로킹이 가능하다.
동기(synchronous): 호출된 작업의 리턴하는 시간과 결과를 반환하는 시간이 일치하는 경우이다. 작업 A의 종료시간과 작업 B의 시작시간이 같으면 동기적이라고 한다.
비동기(asynchronous): 호출된 작업의 리턴하는 시간과 결과를 반환하는 시간이 일치하지 않는 경우이다.
④ 비동기적 Event-Driven
이미지 참고: 포스코x코딩온 강의 자료(10_07_Node.js소개.pdf)
+) ① 콜스택 (call stack)
: LIFO(후입 선출) 스택이다.
<script>
function first(){
second();
console.log('첫번째');
}
function second(){
third();
console.log('두번째');
}
function third(){
console.log('세번째');
}
first();
// 세번째 두번째 첫번째
</script>
② 이벤트 루프(event loop)
이벤트를 처리하는 반복되는 동작(loop)이다. 즉, node.js가 비동기-이벤트 동작을 처리하는 일련의 반복 동작이다.
여러 이벤트가 동시에 발생했을 때 어떤 순서로 콜백 함수를 호출할지 판단한다.
호출 스택이 비어있으면 테스크 큐에서 함수를 하나씩 가져와 호출 스택에 넣고 실행한다.
백그라운드(background) : 타이머나 이벤트 리스너들이 대기하는 곳이다. 여러 작업이 동시에 실행될 수 있다.
테스크 큐(task queue) : 이벤트 발생 후 백그라운드로부터 타이머나 이벤트리스너의 콜백 함수를 받는다. 실제로는 여러 개의 큐로 이루어져 있으며, 정해진 순서대로 줄을 서 있어서 callback queue라고도 불린다.
이미지 참고: 포스코x코딩온 강의 자료(10_07_Node.js소개.pdf)
setTimeout
은 비동기식으로 작동하는 비동기식 함수이다.3) 모듈(module)
3-1) 모듈 만들기
① 하나의 모듈 파일에 하나 만들기
<script>
function connect() {
return a + b;
}
module.exports = connect;
</script>
② 하나의 모듈 파일에 여러 개 만들기
<script>
const a = "A";
const b = "B";
// 첫 번째 방법
module.export = {
a,
b
}
// 두 번째 방법 -1
module.exports.a = a;
module.exports.b = b;
// 두 번째 방법 -2
exports.a = a;
exports.b = b;
</script>
3-2) 모듈 불러오기
require(파일 경로)
함수를 호출하여 모듈을 불러온다.require('./prac')
)require()
함수의 반환값은 exports 객체이다.<script>
const str = require('./prac');
// 구조분해해서 가져오기 -> 이름이 동일해야 함
const { a, b } = require('./prac');
</script>
3-3) ES2015 모듈
"type": "module"
을 추가해서 사용한다.① 모듈 내보내기
<script>
// 첫 번째 방법
const a = "A";
const b = "B";
export { a, b };
// =
// module.exports = {
// a,
// b
// }
// 두 번째 방법
function connect() {
return a + b;
}
export default connect;
// =
// module.xports = connect;
</script>
② 모듈 가져오기
<script>
import { a, b } from './prac.js';
import str from './prac.js';
</script>
4) 서버 만들기
4-1) http
웹 서버를 구동하기 위한 node.js 내장 웹 모듈이며, server 객체, request 객체, response 객체를 사용한다.
<script>
const http = requires('http');
const server = http.createServer();
server.listen(8080, function() {
console.log('8080번 포트로 서버 발생!');
});
// listen(port, callback) -> 서버를 첫 번째 매개변수인 포트로 실행한다는 의미이다.
</script>
port란?
: 서버 내에서 데이터를 주고 받는 프로세스를 구분하기 위한 번호이며, 기본적으로 http 서버는 80번 포트를 사용한다.+) localhost란?
: 컴퓨터 내부 조소이며, 자신의 컴퓨터를 가리킨다.
① server : 웹 서버를 생성할 때 사용하는 객체
메서드
listen() | 서버를 실행하고 클라이언트를 기다린다. |
close() | 서버를 종료한다. |
on() | server 객체에 이벤트를 등록한다. |
이벤트
request | 클라이언트가 요청할 때 발생하는 이벤트 |
connection | 클라이언트가 접속할 때 발생하는 이벤트 |
close | 서버가 종료될 때 발생하는 이벤트 |
checkContinue | 클라이언트가 지속적인 연결을 하고 있을 때 발생하는 이벤트 |
upgrade | 클라이언트가 http 업그레이드를 요청할 때 발생하는 이벤트 |
clientError | 클라이언트에서 오류가 발생할 때 발생하는 이벤트 |
server 객체 작성 예시
<script>
server.on('request', function(code) {
console.log('request event!');
}
</script>
② response : 응답 메시지를 작성할 때 두번 째 매개변수로 전달되는 객체
writeHead | 응답 헤더 작성 |
write | 응답 본문 작성 |
end | 응답 본문 작성 후 응답 종료 |
<script>
const server = http.createServer(function (req, res) {
res.wirteHead(200);
res.write("<h1>Hello!</h1>");
res.end("<p>End</p>")
});
</script>
③ request : 응답 메시지를 작성할 때 첫 번째 매개변수로 전달되는 객체
+) html 파일 전송하기
fs
모듈 불러오기
fs
모듈은 filsSystenm의 약자로 파일 처리와 관련된 모듈이며, Node.js에 내장되어 있기 때문에 별도의 라이브러리 설치 없이 바로 사용할 수 있다.
참고1 참고2
<script>
const http = require("http");
const fs = require("fs");
const server = http.createServer((req, res) => {
try {
const data = fs.readFileSync("index.html");
// fs.readFileSync(filename, [options]) 으로 작성
res.writeHead(200);
res.write(data);
res.end();
} catch (err) {
console.log(err);
res.writeHead(404);
res.write(err.message);
res.end();
}
})
server.listen(8000, () => {
console.log(`http://localhost:8000`);
})
</script>
+) http 응답
1XX | 처리 중 - 100: continue - 102: processing |
2XX | 성공 - 200: ok - 201: created - 202:accepted |
3XX | 리다이렉트: 다른페이지로 이동 |
4XX | 요청 오류 - 400: 잘못된 요청 - 401: 권한 없음 - 404: 찾을 수 없음(page not found) |
5XX | 서버 오류 |
4-2) express
① express 설치하기
npm install express
② express 사용하기
<script>
const express = require('express');
const app = express();
// express()
// : express 모듈이 export하는 최상위 함수로, express application을 만든다.
// app 객체
// : express() 함수를 호출함으로써 만들어진 express application
const PORT = 8000;
app.get('/', function (req, res) {
res.send('hello express');
})
app.listen(PORT, function () {
console.log(`listening on port ${PORT}! http://localhost:${PORT}`);
})
</script>
5) 템플릿 엔진
# ejs 템플릿
.ejs
이다.① ejs 템플릿 설치하기
npm install ejs
-> 먼저 터미널에 명령어를 입력하여 ejs 모듈을 설치한다.
<script>
// ejs 템플릿 설정
app.set('view engine', 'ejs');
app.set('views', './views');
// ejs 템플릿 렌더링
// test 경로로 접속했을 때 test 파일 렌더링
// view endgine을 ejs로 했기 때문에 test.ejs에서 확장자명 생략가능
app.get("/test", (req, res) => {
res.render("test");
});
</script>
-> app.js
파일에서 ejs 파일을 사용할 수 있도록 설정해준다.
🤷🏻♀️
view engine
이란?
: 뷰엔진은 서버에서 처리한 데이터 결과 값을 정적인 페이지(html)에 보다 편리하게 출력해주기 위해 사용한다. 뷰엔진에서 요구하는 형태로 템플릿 파일을 만들고, 해당 템플릿 파일에 서버에서 처리한 데이터를 전달하면 해당 데이터를 화면에 출력할 수 있다.
참고
② ejs 문법 사용하기
<% %> | 자바스크립트 코드가 들어가고, 줄바꿈을 할 경우에는 새로운 <% %>를 이용해야 한다. |
<%= %> | 값을 템플릿에 출력할 때 사용한다. |
<%-include('view의 상대 주소') %> | 다른 view 파일을 불러올 때 사용한다. |
<html>
<body>
<%- include('./component/header')%>
<h1>Hello EJS</h1>
<% for (let i = 0; i < 5; i++) { %>
<div>hi~<%= i%>번째</div>
<%= i%> <% } %>
</body>
</html>
6) 미들웨어
<script>
app.set('view engine', 'ejs');
// use 사용하여 미들웨어 등록하기
// express에 있는 static 메소드를 이용해 미들웨어로 로드한다.
app.use('/views', express.static(__dirname + '/views'));
</script>
참고: 포스코x코딩온 강의 자료(10_07_Node.js소개.pdf)
1) 싱글 스레드
하나의 프로세스에서 오직 하나의 스레드로만 실행한다.
장점
① context switch(문맥 교환) 작업을 요구하지 않는다. 문맥 교환은 여러 개의 프로세스가 하나의 프로세스를 공유할 때 발생하는 작업으로 많은 비용을 필요로 한다.
② 자원 접근에 대한 동기화를 신경쓰지 않아도 된다. -> 모든 스레드가 일정 자원에 동시에 접근하거나 똑같은 작업을 실행하려는 경우, 에러가 발생하거나 원하는 값이 나오지 않기 때문에 스레드들이 동시에 같은 자원에 접근하지 못하도록 제어해줘야한다.
③ 단순히 CPU만을 사용하는 작업은 싱글 스레드가 멀트 스레드보다 빠르다.
④ 프로그래밍 난이도가 쉽고, CPU, 메모리를 적게 사용한다. -> 비용이 적게 든다.
단점
① 여러 개의 CPU를 활용하지 못한다.
② 연산량이 많은 작업을 하는 경우, 싱글 스레드는 하나의 작업이 완료되어야 다른 작업을 수행할 수 있기 때문에 사용자 입장에서는 오래 기다려야 한다.
(예: 웹 게임에서 좌표를 계산하는데 3초가 걸리고 계산된 좌료를 받아 DOM에 반영한다고 했을 때, 좌표를 계산하는 동안 다른 작업들을 수행할 수가 없기 때문에 사용자 입장에서는 3초간 멍하니 기다려야 한다.)
③ 에러 처리를 못하는 경우 멈춘다.
-> 멀티 스레드의 경우, 에러 발생 시 새로운 스레드를 생성하여 극복한다.
2) 멀티 스레드
CPU의 최대 활용을 위해 프로그램의 둘 이상을 동시에 실행하는 기술이다.
context switching을 통해서 작업이 이루어진다. 하나의 스레드에서 다음 스레드로 이동을 하면서 컨텍스트 스위칭이 일어나고, 이로 인해 각각의 스레드에 대한 작업을 부분적으로 조금씩 끝내게 되는 것이다. 그리고 컨텍스트 스위칭이 엄청 빠르게 일어나면서, 유저의 시선에서는 프로그램들이 동시에 수행되는 것처럼 보이게 된다.
장점
① 응답성 : 프로그램의 일부분(스레드 중 하나)이 중단되거나 긴 작업을 수행하더라도 프로그램의 수행이 계속 되어 사용자에 대한 응답성이 증가한다. -> 멀티 스레드 모델은 에러 발생 시 새로운 스레들를 생성하여 극복한다.
② 경제성 : 프로세스 내 자원들과 메모리를 공유하기 때문에 메모리 공간과 시스템 자원 소모가 줄어든다. 스레드 간 통신이 필요한 경우에도 쉽게 데이터를 주고 받을 수 있다.
③ 멀티프로세서의 활용 : 다중 CPU 구조에서는 각각의 스레드가 다른 프로세서에서 병렬로 수행될 . 수있으므로 병렬성이 증가한다.
단점
① context switching, 동기화 등의 이류 때문에 싱글 코어 멀티 스레딩은 스레드 생성 시간이 오히려 오버헤드로 작용해 단일 스레드보다 느리다.
② 공유하는 자원에 동시에 접근하는 경우, 프로세스와는 달리 스레드는 데이터와 힙 영역을 공유하기 때문에 어떤 스레드가 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 엉뚱한 값을 읽어오거나 수정할 수 있다.