본문 바로가기

회고록(TIL&WIL)

TIL 2023.03.13 Node.js (NVM, module, express, ejs, mysql)

Node.js

V8 runtime 엔진 사용
라이프사이클이 매우 짧기 때문에 의존성에 맞춰서 사용해야하기 때문에 업데이트를 막해서는 안된다.

NVM (node version manager)을 이용한 설치

NVM 다운로드
node는 하위종속성 때문에 버전관리를 잘해야하는데 NVM을 이용해서 버전을 관리할 수 있도록 해주는 툴이다.

버전 체크, 도움말

nvm --version => nvm -v
nvm --help => nvm -h

node.js 다운로드

nvm install 18.15.0

다운받은 node 버전 확인, node 버전 변경, node 버전 확인

nvm list => node ls
nvm use 18.15.0
node -v

실행

node


이후 자바스크립트 코드를 그대로 사용할 수 있다.

종료

process.exit();
또는 ctrl+c 두번

js파일 실행

node ex01.js

getting started

js 파일 생성 후 실행시키면 서버 생성됨

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
node ex02.js


localhost:3000으로 접근하면 Hello World 확인 가능함

최상위 객체 Global (기존 js에서 Window에 해당)

변수

console.log(__dirname);
console.log(__filename);

console 객체 - 콘솔 화면 관련 기능 수행

메서드

error 에러 출력 (x) 표시
warn 경고 출력 (!) 표시
debug 디버깅 관련 정보
log 로그 출력
info 정보 출력
assert 검증(Assertion)
time(tag) 시간 측정 시작
timeEnd(label) 시간 측정 종료

formatting

console.log('%d <-- number', 1234);
console.log('%d <-- number', 3.14);
console.log('%s <-- string', "abcd");
console.log('%j <-- json', {key1:'val1'});
%% % 문자 자체   

process 객체 - 프로그램과 프로세스 관련 기능 수행

console.log(process.argv, '실행 매개 변수');
console.log(process.env, '실행환경 관련 정보');
console.log(process.version, 'Node의 버전');
console.log(process.versions, '종속된 프래그램 버전');
console.log(process.arch, '프로세서의 아키텍쳐 표시');
console.log(process.platform, '플랫폼 정보 표시');

console.log(process.env.MYSQL_USER);
console.log(process.env.MYSQL_PW);

메서드

exit 프로그램 종료
memoryUsage 메모리 사용 정보 객체 반환
uptime 현재 프로그램이 실행된 시간

exports 모듈과 관련된 기능 수행 (CommonJS)

방법 1

-------------- module01.js
var func1 = function () {
    console.log('func1 run...');
};
exports.func1 = func1;
exports.su1 = 1234;
-------------- ex06.js
var f = require('./module01');
f.func1();
console.log(f.su1);


방법 2

--------------- module02.js
var obj = {
    su2: 4321,
    func2: function() {
        console.log('func2 run...')
    }
};
module.exports = obj;
--------------- ex07.js
var o = require('./module02');
o.func2();
console.log(o.su2);

Node.js에서 자체적으로 제공하는 모듈

Os mudule

메서드
hostname 운영체제의 호스트명을 반환
type 운영체제의 이름을 반환
platform 운영체제의 플랫폼을 반환
arch 운영체제 아키텍처 반환
release 운영체제의 버전을 반환
uptime 운영체제 실행된 시간을 반환
loadavg 로드 평균값 정보 반환 (Array)
totalmem 운영체제 총 메모리 사이즈 반환
freemem 시스템 사용 가능한 메모리 반환
cpus CPU 정보 반환 (Array)
getNerworkInterfaces 네트워크 인터페이스 정보 반환 (Array)

더 자세한 내용은 Document 문서 참조 - OS Module

Url module

parse URL 문자열을 URL 객체로 변환
format URL 객체를 URL 문자열로 변환
resolve 매개변수를 조합, URL 문자열을 생성하여 반환
var url = require('url')
var msg = "https://search.naver.com/search.naver?where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=node"

console.log(url.parse(msg).protocol)
console.log(url.parse(msg).host)
console.log(url.parse(msg).port)
console.log(url.parse(msg).path)
console.log(url.parse(msg).query)
console.log(url.parse(msg).auth)
console.log(url.parse(msg).href)

// query String object 반환
console.log(url.parse(msg, true).query)

 

console.log(url.format(url.parse(msg)));
console.log('-------------');
console.log(url.resolve('https://m.naver.com', 'dept'));

Query String module

parse 쿼리 문자열을 쿼리 객체로 변환
stringify 쿼리 객체를 쿼리 문자열로 변환
var query = require('querystring');
var msg = 'where=nexearch&sm=top_hty&fbm=0&ie=utf8&query=node';
console.log(query.parse(msg));
console.log(query.stringify(query.parse(msg)));

Crypto module

암호화를 위한 모듈

Hash

var crypto = require('crypto');
var msg = 'abcdefg';
var hash = crypto.createHash('MD5'); // 실사용은 sha512로
hash.update(msg);
console.log(hash.digest('hex'));

File System module

readFile(file, encoding, callback) 비동기적 파일 읽기
readFileSync(file, encoding) 동기적 파일 읽기
writeFile(file, encoding, callback) 비동기적 파일 쓰기
writeFileSync(file, encoding) 동기적 파일 쓰기
appendFile(file, encoding, callback) 비동기적 파일 추가
appendFileSync(file, encoding) 동기적 파일 쓰기

readFile

var fs = require('fs');
// 비동기적
fs.readFile('ex01.js', function(err, data) {
    console.log(data.toString('utf-8'));
});
// 동기적
var msg = fs.readFileSync('ex01.js', 'utf-8');
console.log(msg);

두 코드다 결과는 아래와 같음

writeFile

var fs = require('fs');

fs.writeFile('temp01.txt','한글작성', function(err){
    console.log(err);
})

fs.readFile('temp01.txt', function(err,data){
    console.log(err,data.toString('utf-8'));
});

FileSync

var fs = require('fs');

fs.writeFileSync('temp02.txt','한글작성2');

var msg = fs.readFileSync('temp02.txt','utf-8');
console.log(msg);
var fs = require('fs');

fs.writeFile('temp03.txt', '한글작성', function(err){
    console.log(err);
});

var msg = fs.readFileSync('temp03.txt','utf-8');
console.log(msg);

위처럼 하게되면 순서가 보장되지않기 때문에 실제로 쓰기도되고 읽기도 되나 제대로 읽어오지 못한다.
자바스크립트에서는 이처럼 동기적인통신을 하게 되면은 그만큼 성능저하가 되기 때문에 사용하는 것을 지양한다.

mkdir

var fs = require('fs');

fs.mkdir('js01', function(err){
    console.log(err);
});

rmdir

var fs = require('fs');
fs.rmdir('js01', function(err){
    console.log(err);
});

rename

rename은 파일명을 수정하는 용도보단 이동시키는 용도로 더욱더 많이 사용된다.

fs.rename('temp03.txt', './js02/temp05.txt', function(err) {});

readdir

var fs = require('fs');

fs.readdir('.',function(err,files){
    files.forEach(function(ele,idx){
        console.log(ele);
    });
});

events module

var event = require('events');

var obj = new event.EventEmitter();

obj.once('call', function(e){
    console.log('이벤트 발생');
});
obj.on('call2', function(e){
    console.log('이벤트 발생2');
});

obj.emit('call');
obj.emit('call');
obj.emit('call2');

http module

var http = require('http')
// var query = require('querystring');
var url = require('url');
var fs = require('fs');

var server = http.createServer(function(req,res){
    // console.log(query.parse(req.url));
    // console.log(url.parse(req.url).path);
    // console.log(url.parse(req.url, true).query.id); // localhost:3000/?id=admin => admin
    res.writeHead(200,{'Content-Type':'text/html'})
    // res.setHeader('Content-Type', 'text/plain');
    // res.write('abcd');
    // res.write('<h1>abcd</h1>');
    // var msg = fs.readFileSync('ex22.html', function(err, data){
    // res.write(msg);
    fs.readFileSync('ex22.html', function(err, data){
        res.write(data);
        res.end();
    });
    // res.end(); // 여기서 끊으면 위의 콜백함수에서는 write가 안된다.
});

server.listen(3000,function(){
    console.log('server start...');
});

웹서비스 구현

위의 내장 모듈을 이용한 구현

var http = require('http');
var url = require('url');
var fs = require('fs');

http.createServer(function(req,res) {
    var obj = url.parse(req.url, true);
     // localhost:3000/index.html
    if(obj.path=='/index.html'){
        res.writeHead(200, {'Content-Type': 'text/html'})
            .end(fs.readFileSync(__dirname + '/js02/index.html'));
    // localhost:3000/ex01.html
    } else if(obj.path=='/ex01.html'){ 
        res.writeHead(200, {'Content-Type': 'text/html'})
            .end(fs.readFileSync(__dirname + '/js02/ex01.html'));
    } else {
        res.writeHead(404, {'Content-Type': 'text/html'})
            .end(fs.readFileSync(__dirname + '/js02/err.html'));
    }
}).listen(3000);

express.js 라이브러리를 이용한 웹서비스 구현

설치

npm i express

서버 생성

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

Event

// localhost:3000/dept... 인 것만 이벤트 호출됨
app.use('/dept', function(req,rep,next) {
  console.log('/dept 호출...');
  next(); // 일치하는 다음패턴 이벤트도 시행함
})
// 먼저 패턴이 맞으면 실행하고 끝나기 때문에 코드 순서가 중요하다.
app.use('/', function(req,res,next) {
  console.log('/ 호출...');
})

Response

app.use('/', function(req,res,next) {
  res.status(200);
  res.send('<h1>ok 페이지...</h1>')
})

static - 정적파일 로드

// 해당 디렉토리의 정적파일들을 불러 올 수 있게된다.
var f = express.static('js02');
app.use(f);

// localhost:3000/index.html
// localhost:3000/ex01.html

RESTful

app.get('/dept', function(req,res,next) {
  console.log(req.method)
  res.send('<h1>dept 페이지...(get)</h1>')
})
app.post('/dept', function(req,res,next) {
  console.log(req.method)
  res.send('<h1>dept 페이지...(post)</h1>')
})
app.put('/dept', function(req,res,next) {
  console.log(req.method)
  res.send('<h1>dept 페이지...(put)</h1>')
})
app.delete('/dept', function(req,res,next) {
  console.log(req.method)
  res.send('<h1>dept 페이지...(delete)</h1>')
})

PathVariable

app.get('/dept/:deptno', function(req,res,next) {
  // PathVariable
  console.log(req.method, req.params.deptno)
  res.send('<h1>dept 페이지...(get)</h1>')
})

RequestParam

app.get('/dept', function(req,res,next) {
  // RequestParam
  console.log(req.method, req.query.deptno)
  res.send('<h1>dept 페이지...(get)</h1>')
})

body-parser

app.use(express.json())
app.use(express.urlencoded({extended:false}))
app.post('/dept', function(req,res,next) {
  // RequestBody
  console.log(req.method, req.body.deptno)
  res.send('<h1>dept 페이지...(post)</h1>')
})

Template Engine - EJS

설치

npm i ejs

.js

// template
app.set('views', __dirname+'/views')
app.set('view engine', 'ejs')
// localhost:3000/intro
app.get('/intro', function(req,res){
  var arr = ['item1', 'item2', 'item3','item4']
  var obj = {key1:"val1", key2:"val2"}
  var nalja = new Date();
  res.render('intro', {msg:'hello', arr:arr, obj:obj, nalja:nalja})
})

.ejs

<body>
    <h1>ejs page</h1>
    <p><%=msg %></p>
    <ul>
        <% arr.forEach(function(ele,idx){ %>
            <li><%=ele%></li>
        <% }) %>
    </ul>
    <p><%=obj.key1 %></p>
    <p><%=obj.key2 %></p>
    <p><%=nalja %></p>
</body>

connection Mysql

설치

npm i mysql

connect

var mysql = require('mysql')

var conn = mysql.createConnection({
    host: "192.168.99.100",
    user: "scott",
    password: "tiger",
    database: 'lecture'
})

conn.connect(function(err){
    if(err) throw err;
    console.log('Connected!...');
})

mysql 8.0 버전 이상을 사용할 경우 node와 연결이 되지않는 경우가 있는데 이는 mysql 8.0 버전부터 password를 암호화인증 플러그인이 caching_sha2_password방식이기 때문인데 이 달라진 플러그인을 node에서 지원하지 않을 경우 아래의 오류가 발생된다! 


이를 해결하기 위해선 mysql에 root 계정으로 직접 접속해서 아래 명령어로 플러그인을 변경 해주면 된다!.

alter user 'scott'@'%' identified with mysql_native_password by 'tiger';
flush privileges;