[포스코x코딩온 웹 풀스택 10기] 5주차 회고_ Node.js

onee·2023년 11월 26일
0
post-thumbnail

📖 수업내용


# Node.js

1) Node.js란?

Node.js는 Chrome V8 JavaScript 엔진으로 빌드 된 JavaScript 런타임이다.

  • JavavScript를 서버에서도 사용할 수 있도록 만든 프로그램이다.
  • Node.js를 통해 다양한 자바스크립트 어플리케이션을 실행할 수 있다.
  • 자바스크립트를 언어로 활용하며, Non-blocking I/O와 단일 스레트 이벤트 루프를 통한 높은 처리 성능을 가지고 있다.

1-1) Node.js 설치(MAC)

node js 홈페이지 - https://nodejs.org/en/download 에서 mac 버전 설치

② 설치 후 터미널에 입력하여 버전 확인

node -v

1-2) REPL

  • Read Eval(evaluation) Print Loop
  • 사용자가 특정 코드를 입력하면 그 코드를 평가하고 코드의 실행결과를 출력해주는 것을 반복해주는 환경
    -> node.js에서 REPL 환경을 지원하기 때문에 자바스크립트 학습 중에 간단한 자바스크립트 코드 등을 즉석에서 바로 실행해 결과를 확인해 볼 수 있다는 장점이 있다.
  • 맥의 경우 터미널 창에 node를 입력하면 REPL 환경으로 접속이 가능하다.


1-3) npm

  • Node Package Manager
  • 노트 패키지를 관리해주는 틀
  • 전 세계의 개발자들이 만든 다양한 기능(패키지, 모듈)들을 관리하는 거대한 생태계라고 할 수 있다.


이미지 참고

< 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

  • Event Driven(이벤트 기반)이란 이벤트가 발생할 때 미리 지정해둔 작업을 수행하는 방식을 의미한다.
    -> 즉, 이벤트 기반 시스템에서는 특정 이벤트가 발생할 때 무엇을 할지 미리 등록해두고, 이벤트가 발생하면 이벤트 리스너에 등록해둔 콜백함수를 호출한다.

이미지 참고: 포스코x코딩온 강의 자료(10_07_Node.js소개.pdf)

참고1    참고2    참고3    참고4


+) ① 콜스택 (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)

  • 특정한 기능을 하는 함수나 변수들의 집합이며, 재사용 가능한 코드의 조각이라고도 할 수 있다.
  • Node.js에서 제공하는 모듈(내장 모듈) 또는 다른 개발자들이 만들어 놓은 모듈(외장 모듈)을 사용해도 되고, 직접 모듈을 만들어서 사용해도 된다.
  • 장점: 코드 캡슐화(코드의 무분별한 변경을 막기 위해 모듈 내부에 코드를 숨길 수 있음), 코드 재사용(-> 기능별로 함수를 만들어 함수를 호출하여 재사용), 유지보수가 용이해짐

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 모듈

  • 자바스크립트 자체 모듈 시스템 문법이다.
  • package.json에 "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응답 본문 작성 후 응답 종료
  • response 객체 작성 예시
    <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 프레임워크는 코드의 가독성과 확장성이 떨어진다는 http 모듈의 단점을 보완하기 위해 만들어졌다.

① express 설치하기

npm install express
  • npm_modules가 만들어지며 express에 관련된 폴더가 생성된다.
    +) npm_modules 파일의 양이 많기 때문에 .gitignore에 작성하여둔다.

② 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) 템플릿 엔진

  • 문법과 설정에 따라 파일을 html 형식으로 변환시키는 모듈이다.

# ejs 템플릿

  • Embedded Javascript의 약자로, 자바스크립트가 내장되어 있는 html 파일이다.
  • 확장자는 .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)



👩🏻‍💻 학습


# 싱글 스레드(Single Thread) & 멀티 스레드(Multi Thread)

이미지 참고

1) 싱글 스레드

  • 하나의 프로세스에서 오직 하나의 스레드로만 실행한다.

  • 장점
    ① context switch(문맥 교환) 작업을 요구하지 않는다. 문맥 교환은 여러 개의 프로세스가 하나의 프로세스를 공유할 때 발생하는 작업으로 많은 비용을 필요로 한다.

    ② 자원 접근에 대한 동기화를 신경쓰지 않아도 된다. -> 모든 스레드가 일정 자원에 동시에 접근하거나 똑같은 작업을 실행하려는 경우, 에러가 발생하거나 원하는 값이 나오지 않기 때문에 스레드들이 동시에 같은 자원에 접근하지 못하도록 제어해줘야한다.

    ③ 단순히 CPU만을 사용하는 작업은 싱글 스레드가 멀트 스레드보다 빠르다.

    ④ 프로그래밍 난이도가 쉽고, CPU, 메모리를 적게 사용한다. -> 비용이 적게 든다.

  • 단점
    ① 여러 개의 CPU를 활용하지 못한다.

    ② 연산량이 많은 작업을 하는 경우, 싱글 스레드는 하나의 작업이 완료되어야 다른 작업을 수행할 수 있기 때문에 사용자 입장에서는 오래 기다려야 한다.
    (예: 웹 게임에서 좌표를 계산하는데 3초가 걸리고 계산된 좌료를 받아 DOM에 반영한다고 했을 때, 좌표를 계산하는 동안 다른 작업들을 수행할 수가 없기 때문에 사용자 입장에서는 3초간 멍하니 기다려야 한다.)

    ③ 에러 처리를 못하는 경우 멈춘다.
    -> 멀티 스레드의 경우, 에러 발생 시 새로운 스레드를 생성하여 극복한다.


2) 멀티 스레드

  • CPU의 최대 활용을 위해 프로그램의 둘 이상을 동시에 실행하는 기술이다.

    context switching을 통해서 작업이 이루어진다. 하나의 스레드에서 다음 스레드로 이동을 하면서 컨텍스트 스위칭이 일어나고, 이로 인해 각각의 스레드에 대한 작업을 부분적으로 조금씩 끝내게 되는 것이다. 그리고 컨텍스트 스위칭이 엄청 빠르게 일어나면서, 유저의 시선에서는 프로그램들이 동시에 수행되는 것처럼 보이게 된다.

  • 장점
    응답성 : 프로그램의 일부분(스레드 중 하나)이 중단되거나 긴 작업을 수행하더라도 프로그램의 수행이 계속 되어 사용자에 대한 응답성이 증가한다. -> 멀티 스레드 모델은 에러 발생 시 새로운 스레들를 생성하여 극복한다.

    경제성 : 프로세스 내 자원들과 메모리를 공유하기 때문에 메모리 공간과 시스템 자원 소모가 줄어든다. 스레드 간 통신이 필요한 경우에도 쉽게 데이터를 주고 받을 수 있다.

    멀티프로세서의 활용 : 다중 CPU 구조에서는 각각의 스레드가 다른 프로세서에서 병렬로 수행될 . 수있으므로 병렬성이 증가한다.

  • 단점
    ① context switching, 동기화 등의 이류 때문에 싱글 코어 멀티 스레딩은 스레드 생성 시간이 오히려 오버헤드로 작용해 단일 스레드보다 느리다.

    ② 공유하는 자원에 동시에 접근하는 경우, 프로세스와는 달리 스레드는 데이터와 힙 영역을 공유하기 때문에 어떤 스레드가 다른 스레드에서 사용 중인 변수나 자료구조에 접근하여 엉뚱한 값을 읽어오거나 수정할 수 있다.

참고




profile
Hello World 💻

0개의 댓글