일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- presignedurl
- 중간이들
- 99클럽
- 파이썬
- MySQL
- 꿀단집
- 데이터베이스시스템
- aws
- TiL
- 방송대컴퓨터과학과
- 방송대
- 엘리스sw트랙
- Git
- SQL
- Python
- 항해99
- 코드잇
- 파이썬프로그래밍기초
- 코딩테스트준비
- node.js
- 개발자취업
- Cookie
- CSS
- redis
- 프로그래머스
- 코딩테스트
- HTML
- 유노코딩
- nestjs
- JavaScript
- Today
- Total
배꼽파지 않도록 잘 개발해요
[코드잇] Node.js 기본기 ① - Node.js 시작하기 및 기본 개념 본문
◆ Node.js 시작하기
◆ Node.js 기본 개념
Node.js 시작하기
Node.js는 무엇인가
서버(server) : 웹 브라우저나 모바일 앱으로 어떤 요청을 보냈을 때 응답을 해주는 컴퓨터
Ryan Dahl : 2009년 자바스크립트 컨퍼런스
프레임워크들의 단점 설명하면서 Node.js 제작했음을 발표함.
장점 : 하나의 웹 서비스를 만들 수 있음.
ex. PayPal, Uber, Linkedin, NETFLIX
Node.js는 프레임워크가 아니고, 자바스크립트라는 언어의 '실행 환경'임.
Node.js로 자바스크립트 실행해보기
해당 파일(test.js) 실행
node test.js
모듈의 확장자인 .js를 꼭 붙이지 않아도 됨.
node test
node가 test.js파일의 자바스크립트 코드를 실행함.
자바스크립트 코드를 노드로 실행할 때는 파일 이름에 꼭 js라는 확장자를 붙이지 않아도 됨.
REPL 모드에서 실행해보기
Read, Eval, Print, Loop
- Read : 사용자가 입력한 내용을 읽고,
- Eval : 그 결과값을 구한 다음,
- Print : 결과값을 출력
- Loop : 이런 과정을 계속 반복하는 모드
파일 안의 자바스크립트 코드를 통째로 실행하는 게 아니라 노드와 대화하는 것처럼 코드를 실행함.
터미널에서 REPL모드 실행
node
모든 내용 초기화
Ctrl + l (엘)
줄바꿈
enter
나가기
.exit
· undefined가 출력되는 이유
- 어떤 코드가 결과값을 별도로 리턴하지 않으면 undefined를 리턴한 것으로 란주함.
- undefined가 보기 싫으면 어떤 값을 반드시 리턴하도록 함.
· repL모드는 긴 코드 실행에는 부적절함. 짧은 코드를 간단하게 테스트하기에 유용함.
Node.js 기본 개념
모듈
- 전체를 이루는 부품 하나하나로, JavaScript 파일 하나를 의미함.
- 모듈들이 모여서 하나의 프로그램이 됨.
· require() : 모듈을 로드해서 객체 1개를 리턴
- require가 반환하는 객체를 사용하기 위해서 그 객체를 변수에 대입해주면 됨.
- 변수(let) 보다는 상수(const)로 받는 것이 더 안전함.
const m = require('./math-tools.js');
main.js
let m = require('./math-tools.js');
console.log(m.add(1, 2));
require이 리턴하는 객체를 갖다 쓸 수 있도록 변수를 대입해주면 됨.
math-tools.js
function add(a, b) {
return a + b;
}
exports.add = add;
exports.add = add;
• 왼쪽 add : 모듈 외부로 공개할 이름
• 오른쪽 add : 모듈 내부에서의 이름
모듈 내부의 것을 외부에 공개해주어야 다른 곳에서 사용할 수 있음.
math-tools.js
function add(a, b) {
return a + b;
}
exports.plus = add;
main.js
let m = require('./math-tools.js');
console.log(m.plus(1, 2));
하나의 객체로 모아서 외부에 공개하기
main.js
const m = require('./math-tools.js');
console.log(m.PI);
console.log(m.add(2, 4));
console.log(m.subtract(1, 2));
console.log(m.multiply(1, 2));
console.log(m.divide(1, 2));
math-tools.js
exports.PI = 3.14;
exports.add = function add(a, b) { return a + b; };
exports.subtract = function subtract(a, b) { return a - b; };
exports.multiply = function multiply(a, b) { return a * b; };
exports.divide = function divide(a, b) { return a / b; };
이렇게 변수를 하나씩 설정해서 불러오는 방법 외에 다른 방법도 있음.
객체를 만들어서 해당 객체만 외부로 내보내기
let calculator = {
PI: 3.14,
add: (a, b) => a + b,
subtract: (a, b) => a - b,
multiply: (a, b) => a * b,
divide: (a, b) => a / b,
}
module.exports = calculator;
모듈 내부의 것을 외부에 공개하는 방법
- exports : 모듈 안에 있는 것들을 하나씩 공개 (exports.프로퍼티 이름 = 프로퍼티 값)
- module.exports : 공개하고 싶은 것들을 모은 객체를 외부에 공개할 때 사용 (module.exports = 객체)
Arrow function
함수의 파라미터를 통해 다른 함수의 인자로 들어가는 함수(콜백함수)를 표현할 때 화살표 함수를 많이 사용함.
// Function Declaration(함수 선언식)
const arr = [1, 2, 3, 4, 5];
function getSquare(x) {
return x * x;
}
const newArr = arr.map(getSquare);
console.log(newArr);
// Function Expression(함수 표현식)
const arr = [1, 2, 3, 4, 5];
const newArr = arr.map(function(x) {
return x * x;
});
console.log(newArr);
// Function Expression(함수 표현식)
// Anonymous Function을 Arrow Function 형태로 나타냄
const arr = [1, 2, 3, 4, 5];
const newArr = arr.map((x) => {
return x * x;
});
console.log(newArr);
exports와 module.exports
node.js는 모듈을 로드하기 전에 그 전체 코드를 Module wrapper function이라는 것으로 감싸준다.
Module wrapper function은 그 5개의 인자에 각각 적절한 값이나 객체를 설정해주는데,
(exports, require, module, __filename, __dirname)
우리가 모듈 내의 코드에서 exports 인자로 넘어와서 그 프로퍼티를 하나씩 채워나가는 객체
(또는 module 인자의 exports 프로퍼티로 설정되는 객체) 가 다른 모듈에서 이 모듈을 require 함수로 로드했을 때 리턴되는 객체임.
function add(a, b) {
return a + b;
}
exports.add = add;
exports 객체와 module 객체의 exports 프로퍼티가 가리키는 객체는 서로 같음.
exports 객체
module 객체의 exports 프로퍼티
require 함수는 'exports 객체(=module 객체의 exports 프로퍼티가 가리키는 객체)'를 리턴함.
권장되지 않는 방법
새로운 객체를 할당함.
// moduleA.js
exports = { someProperty: 'someValue' };
exports(moduleA.js에서와 같이)에 새 객체를 할당하면 모듈과 연결된 원래 exports 객체에 대한 참조가 끊어짐.
권장되는 방법
원래 module객체의 exports 프로퍼티의 속성에 접근
// moduleA.js
exports.someProperty = 'someValue';
코어 모듈
모듈
· 내가 직접 만든 모듈 (커스텀 모듈)
· 이미 만들어져 있는 모듈 : 코어 모듈, 서드파티 모듈
- 코어모듈 : node 실행 파일 안에 이미 포함되어 있는 모듈, 노드 설치하고 바로 사용 가능함
- 서드파티 모듈 : 여러 개발자 또는 회사들이 만들어서 인터넷 공개 저장소에서 제공하는 모듈들
fs : fileSystem
파일이나 디렉토리에 관한 작업을 할 때 꼭 필요한 코어 모듈
디렉토리 생성, 파일 삭제 등과 같은 작업을 코드로 해야할 때 필요함.
노드 안에 내장되어 있기 때문에 require 함수 인자로 경로를 쓸 필요가 없음.
const fs = require('fs');
readdirSync 함수
특정 디렉토리 안에 있는 파일 목록들을 배열 형식으로 리턴하는 함수
const fs = require('fs');
let fileList = fs.readdirSync('.')
console.log(fileList);
writeFileSync 함수
new라는 파일의 'Hello Node.js!'라는 내용을 쓰는 함수
기존에 new라는 파일이 없으면 파일을 새로 생성하고 내용을 생성함.
const fs = require('fs');
fs.writeFileSync('new', 'Hello Node.js!');
OS : Operating System
컴퓨터에 운영체제 관련 정보를 가져올 수 있음.
const os = require('os');
console.log(os.cpus());
위 작업들은 브라우저에서 자바스크립트로 하지 못하는 작업들임.
Node.js와 브라우저의 차이
차이점
- 제공하는 API가 다르다
- 자바스크립트를 실행하는 엔진이 다르다
API (Application Programming Interface)
· 어떤 플랫폼이나 실행환경 등에서 제공하는 인터페이스
· 특정 환경에서 자유롭게 가져다 쓸 수 있는 함수나 객체 등을 의미
Node.js | 브라우저 | |
API 차이 | 시각적 표현 필요 X → UI 관련 API X | 시각적 표현 필요 O → UI 관련 API O |
window, document 객체 X 컴퓨터 제어 API X |
window, document 객체 O 컴퓨터 제어 API O (파일 생성, 컴퓨터 정보 확인 등) |
|
실행하는 엔진 | V8 엔진 | V8 엔진 혹은 다른 엔진 firefox : SpiderMonkey Edge : V8(최신), Chakra(옛날) |
node.js + Electron : PC 프로그램 제작
VSCode도 electron으로 제작됨.
node.js 개발 팁
특정 브라우저가 자바스크립트 표준 문법 중에서 어디까지를 지원하는지 확인하는 게 중요함.
https://compat-table.github.io/compat-table/es6/
ECMAScript 6 compatibility table
Sort by Engine types Features Flagged features Show obsolete platforms Show unstable platforms <!-- --> V8 SpiderMonkey JavaScriptCore Chakra Carakan KJS Other ⬤ Minor difference (1 point) ⬤ Small feature (2 points) ⬤ Medium feature (4 points) ⬤ La
compat-table.github.io
서드파티 모듈
서드파티(3rd party) 모듈
· 다른 개발자나 회사들이 만들어서 인터넷상의 공개 저장소에서 제공하는 모듈
· Node Package Manager : 서드파티 모듈에 관한 작업을 할 때 필요한 프로그램
→ 하나의 서드파티 모듈이 설치될 때는 그것이 의존하는 다른 서드파티 모듈들도 함께 설치됨.
· 모듈은 하나의 파일일 수도 있고, 하나의 디렉토리일 수도 있음.
• package-lock.json : 해당 디렉토리 안에 설치된 모든 서드파티 모듈들에 관한 정보가 있음.
- dependencies : 설치된 서드파티 모듈들의 이름과 버전 정보가 저장되어 있음.
• node_modules : 서드파티 모듈들이 실제로 설치되는 공간
npm install cowsay를 입력
npm install cowsay
const cowsay = require('cowsay');
console.log(cowsay.say({
text: "I love javascript",
}));
비동기 프로그래밍과 콜백
비동기 실행 : 특정 작업이 완료되었을 때 실행할 콜백을 등록해두고 바로 다음 코드로 실행을 넘기는 것
- readFileSync 함수 : 동기 실행
- readFile 함수 : 비동기 실행
node.js는 비동기 실행 함수를 사용하는 것이 권장되는 실행 환경임.
readFileSync 함수 (동기)
// fs 모듈을 가져옴
const fs = require('fs');
// 프로그램 시작 메시지 출력
console.log('Start');
// readFileSync로 new라는 파일의 내용을 동기적으로 읽어옴.
// utf8 인코딩이 지정되어 텍스트 파일로 읽어옴.
let content = fs.readFileSync('./new', 'utf8');
console.log(content);
// 프로그램 종료 메시지 출력
console.log('Finish');
readFile 함수 (비동기)
// fs 모듈을 가져옴
const fs = require('fs');
// 프로그램 시작 메시지 출력
console.log('Start');
// 'readFile' 함수를 사용하여 'new' 파일의 내용을 비동기적으로 읽어옴.
// 'utf8' 인코딩이 지정되어 텍스트 파일로 읽어옴.
// 콜백 함수는 파일 읽기가 완료된 후 호출되며, 오류와 데이터 매개변수를 전달받음.
fs.readFile('./new', 'utf8', (error, data) => {
console.log(data);
})
// 프로그램 종료 메시지 출력
console.log('Finish');
node.js에서는 'error'와 같은 인자를 앞에 둠.
1. readFile 함수가 실행되어 new 파일을 읽음.
2. 실행될 콜백함수를 등록함.
3. console.log를 실행함.
4. new 파일 읽기 작업이 끝나면 콜백을 실행함.
5. new 파일 내용을 data로 받아서 console.log로 출력함. 혹은 에러가 error로 넘어감.
· Node.js는 CPU-intensive job(고화질 이미지 처리, 복잡한 시뮬레이션 계산, 딥러닝 작업 등)에는 적절하지 않음.
· 만약 CPU-intensive job을 메인으로 처리해야하는 서버라면 Node.js보다는 다른 서버 프레임워크 등을 사용하는 게 좋음.
· Node.js로 개발할 때는 메인 스레드에 부하를 주면 안 됨.
node.js 공식문서
https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback
File system | Node.js v21.6.0 Documentation
nodejs.org
Node.js의 비동기 실행은 libuv라는 라이브러리를 통해서 이루어짐.
https://docs.libuv.org/en/v1.x/design.html
Design overview - libuv documentation
Previous Home
docs.libuv.org
비동기 프로그래밍과 이벤트
Node.js에서 이벤트란 어떤 일이 발생했음을 알리는 신호
// EventEmitter 클래스가 있어야 이벤트 사용 가능함.
const EventEmitter = require('events');
// myEmitter라는 객체 생성
const myEmitter = new EventEmitter();
// on : 이벤트가 발생했을 때 실행할 콜백을 등록하는 함수
// test 이벤트 발생시 success 문자열 출력되도록 콜백 등록
myEmitter.on('test', () => {
console.log('Success!');
});
// test 이벤트를 발생시킴
myEmitter.emit('test');
1. on 메소드에서 test라는 이벤트가 발생했을 때 실행할 콜백을 미리 설정
2. emit 메소드로 test라는 이벤트를 발생시킴.
3. 등록해둔 콜백이 실행됨. → console.log 함수
Node.js에서 제공하는 주요 API들은 이벤트 기반 구조 위에서 생성되었고, 그 구조에서는 특정 객체가 이벤트를 발생시키면 그 이벤트에 관한 콜백이 실행된다.
이벤트를 발생시키는 모든 객체들은 EventEmitter 클래스의 객체임.
Node.js에서 비동기 프로그래밍은
- 비동기 함수 사용
- EventEmitter 객체 사용 = 이벤트 기반 프로그래밍
EventEmitter 객체 사용법
• EventEmitter 객체를 사용할 때는 이벤트를 발생시키기 전에 콜백 설정을 먼저 해줘야 함.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.emit('test');
myEmitter.on('test', () => {
console.log('Success!');
});
on과 emit 메소드의 순서를 바꾸면 아무것도 실행되지 않음.
test 라는 이벤트를 발생시킨 후 on 메소드로 test 이벤트에 대한 콜백을 설정하였기 때문임.
• 하나의 이벤트에 대해 여러 개의 콜백을 설정할 수 있음.
설정한 콜백들은 설정한 순서대로 하나씩 진행됨.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.on('test', () => {
console.log('1');
});
myEmitter.on('test', () => {
console.log('2');
});
myEmitter.on('test', () => {
console.log('3');
});
myEmitter.emit('test');
• 이벤트를 발생시키고 그 이벤트에 대한 콜백이 실행되는 현상은 하나의 EventEmitter 객체 내에서만 이루어짐.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
const myEmitter2 = new EventEmitter();
myEmitter.on('test', () => {
console.log('1');
});
myEmitter.on('test', () => {
console.log('2');
});
myEmitter2.on('test', () => {
console.log('3');
});
myEmitter.emit('test');
이벤트 이름이 똑같이 test라고 하더라도 다른 EventEmitter 객체의 이벤트에 반응하지는 않음.
on, addListener 메소드
· 특정 이벤트에 대한 이벤트 핸들러를 등록
emitter.addListener(eventName, listener)
emitter.on(eventName, listener)
emit 메소드
· 인위적으로 이벤트 발생시킴.
· 실제로 사용할 일이 잘 없음.
once 메소드
· 특정 이벤트에 대한 이벤트 핸들러를 등록
· 해당 이벤트에 대해 딱 한번만 반응해서 실행되도록 함.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.once('test', () => {
console.log('Success!');
});
myEmitter.emit('test'); // once 특성에 따라 이것만 실행됨
myEmitter.emit('test');
myEmitter.emit('test');
listeners 메소드
· 특정 이벤트에 대한 이벤트 핸들러들을 출력해줌.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.once('test', () => {
console.log('A');
});
myEmitter.once('test', () => {
console.log('B');
});
myEmitter.once('test', () => {
console.log('C');
});
console.log(myEmitter.listeners('test'));
off 메소드
· 등록한 이벤트 제거
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
const callback = () => {
console.log('Success!');
};
myEmitter.on('test', callback);
myEmitter.off('test', callback);
myEmitter.emit('test');
on으로 등록했을 때와 같은 형태로 off를 써야됨.
익명함수 표시 X
이벤트에 추가 정보 함께 전달하기
• emit 메소드에 test 이벤트 외에도 추가 정보를 인수로 넣어서 전달할 수 있음.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.on('test', (...arg) => {
console.log("Success!");
console.log(arg)
})
// 전달하고 싶은 내용을 인자로 추가해줌.
myEmitter.emit('test', 'apple', 'banana', 'pear');
이벤트 리스너((...args) => {...})는 "Success!"와 전달된 인수를 표시함.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.on('test', (...arg) => {
console.log("Success!");
console.log(...arg)
})
// 전달하고 싶은 내용을 인자로 추가해줌.
const arr = ['hello', 'hi', 'goodbye']
myEmitter.emit('test', arr);
• 이벤트와 함께 전달한 인자를 콜백이 꼭 모두 받아야 하는 것은 아님.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.on('test', (arg1, arg2) => {
console.log(arg1);
console.log(arg2);
})
// 세번째 인자를 받지 않도록 함
myEmitter.emit('test', 'hello', 'hi', 'goodbye');
세 번째 인자를 받지 않도록 코드를 수정함.
• 이벤트에서 함께 보낸 인자보다 콜백에서 더 많은 인자를 받으려고 할 때
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// 이벤트에 함께 보낸 인자보다 콜백에서 더 많은 인자를 받으려고 함.
myEmitter.on('test', (arg1, arg2, arg3, arg4) => {
console.log(arg1);
console.log(arg2);
console.log(arg3);
console.log(arg4);
})
myEmitter.emit('test', 'apple', 'banana', 'pear');
매칭되지 않은 인자는 undefined가 됨.
• 실무에서는 여러 정보를 담고 있는 객체 하나만 전달하는 것이 더 깔끔함.
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
const obj = {type: 'text', data: 'Hello JavaScript', date: '2024-01-22'};
myEmitter.on('test', (info) => {
console.log(info);
})
myEmitter.emit('test', obj);
자바스크립트 실행 원리
- 1단계 : 하나의 메인 스레드가 자바스크립트 코드를 쭉 실행함.
- 2단계 : 이후 그 스레드가 Event Loop라는 로직에서 각각의 콜백들에 대한 실행 여부를 판단함.
- 3단계 : 다음으로 Queue에 넣은 후, Queue에 담긴 콜백들을 실행한다.
setTimeout 함수에서 시간(delay) 인자로
2147483647보다 큰 값 또는 1보다 작은 값을 주면,
시간(delay) 인자에 실제로는 1이 설정됨.
// 1보다 작은 값
setTimeout(() => {
console.log('Delay less than 1');
}, 0);
// 2147483647보다 큰 값
setTimeout(() => {
console.log('Delay greater than 2147483647');
}, 2147483648);
https://nodejs.org/en/guides/event-loop-timers-and-nexttick
Node.js — The Node.js Event Loop, Timers, and process.nextTick()
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
nodejs.org
https://nodejs.org/en/guides/dont-block-the-event-loop
Node.js — Don't Block the Event Loop (or the Worker Pool)
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
nodejs.org
'코드잇 Codeit > Back-End' 카테고리의 다른 글
[코드잇] 관계형 데이터베이스를 활용한 자바스크립트 서버 만들기 (0) | 2024.06.25 |
---|---|
[코드잇] Express 기본기 - ② ORM으로 하는 데이터베이스 작업, 배포하기 (0) | 2024.02.01 |
[코드잇] Express 기본기 - ① Express 기본 익히기 (0) | 2024.01.23 |
[코드잇] Node.js 기본기 ② - 웹서버 제작, 서드파티 모듈과 npm (0) | 2024.01.23 |
[코드잇] SQL 데이터베이스 - 데이터베이스 모델링 (1) | 2023.05.24 |