본문 바로가기

Node

Node.js - 이벤트처리, 파일다루기, 버퍼객체

Node.js는 웹에서 많이 사용하는 내용은 아니지만 회사에선 알아야하므로 흐름은 반드시 알고 있기

 

이벤트 리스너란? 

게임을 예로 들면, 캐릭터가 레벨업을 했다 라는 이벤트에 대해서 캐릭터의 체력과 공격력을 증가시켜주는 로직이 들어있는 이벤트리스너가 등록되어 있을 것이다.

 

 

Node.js가 제공하는 이벤트 처리 클래스 - EventEmitter, events

 

EventEmitter 

  • EventEmitter을 이용하면 직접 이벤트를 만들어 처리할 수 있다
  • 이벤트를 처리하는 방법은 EventEmitter를 상속받은 객체를 만들어 EventEmitter의 메소드를 사용한다

메서드

설명
on(event, listener) 지정한 event에 대한 listener를 추가합니다.
once(event, listener) 지정한 event에 대한 listener를 추가합니다. 다만 이 리스너는 최초 한번만 실행 된 후 제거됩니다.
removeListener(event, listener) 지정한 event에 대한 listener를 제거합니다.

 

process 객체

  • 내부적으로 EventEmitter를 상속 받고 있다.  -> process.on, process.emit 이렇게 사ㅛㅇ 가능
  • Node의 기본 내장객체로서 어디서든 사용 가능

 

 

(1) 내장 이벤트 사용하기 - exit

process.on("exit",function(){
	
	console.log("exit 이벤트 발생 함..");
	
});

setTimeout(function(){
	
	console.log("4초 후에 시스템 종료 시도함...");
	process.exit(); // exit 호출 => 프로젝트 자체가 끝나게 됨 
	
},4000);

 

 

 

(2) 사용자 정의 이벤트 사용하기

* emit(): 프로그램 안에서 이벤트 발생시킬 때 쓰는 메소드

process.on("tick",function(count){
	// 함수는 무언가 작업이 있어야함!!
	console.log("tick 이벤트 발생함: " + count);
	
});

setTimeout(function(){
	
	console.log("2초 후에 tick 이벤트 전달 시도함...");
	process.emit("tick","2"); // exit 호출
	//사용자 정의 이벤트는 emit 이용
	
}, 2000);
// 5초로 맞춰놓으면 process.exit(); 에 의해 process가 먼저 종료가 되므로 실행 안됨

 

calc.js

// js도 인터프리터언어 (위에서 아래로 순서대로 실행됨)
// util.inherits : 상속을 가능하게하는 모듈 
var util = require("util");
var eventEmitter = require("events").EventEmitter;
// 내장모듈 events가 EventEmitter를 상속받음 (원래는 상속이 안돼있어서, util을 이용해서 상속받게끔 한 것)

var Calc = function() {	
	var self = this;	
	//this.on(~) 이라고 써도 됨 
	self.on("stop",function(){		
		console.log("Calc에 Stop event 전달됨");			
	}); 	
};

//Calc가 이벤트 처리를 할 수 있도록 EventEmitter 를 상속받게 한다
util.inherits(Calc, eventEmitter);



// 객체 Calc에 add라는 속성(메소드) 추가 (변수 추가가 아님)
Calc.prototype.add = function(a,b) {
	return a+b;
};

//외부에서 호출 가능하게 한다
module.exports = Calc; 
module.exports.title = "계산기";

 

test3.js

// 파일이 달라도 외부 파일을 불러올 수 있다
// calc.js 불러다 쓴다
var Calc = require("./calc");

var ob = new Calc();

//calc.js 의 Calc 객체의 모든 것을 쓸 수 있다
ob.emit("stop"); 
// "stop" 이라는 이벤트 전달(호출)
// 실상은 stop 이벤트를 calc.js 쪽에 전달해 준 것

console.log(Calc.title + "에 stop 이벤트 전달");

var sum = ob.add(10,20);
console.log(sum);

 

 

응용) calc.js 에는 event들만 쭉 만들어놓고 다른 js파일에서 calc.js를 불러다 써서 그 event들을 호출하게 해도 된다

 


파일 다루기

 

(1) 동기식으로 파일 읽기

var fs = require("fs");

//파일을 동기식으로 읽기
var data = fs.readFileSync("../data.json","UTF-8");
console.log(data);
//파일을 연결한 상태에서 데이터를 읽은 것 
//결과가 올때까지 다른 작업 못함

 

(2) 비동기식으로 파일 읽기

//파일을 비동기식으로 읽기
//다 읽으면 function 수행한다 (읽다가 에러나면 err, 성공적으로 읽었으면 data에 담음)
fs.readFile("../data.json","UTF-8",function(err,data){
	if(err) {
		console.log("Error: " + err);
	}
	console.log(data);
});
// 아래 그 외의 작업들이 있다면 파일을 읽는 동안 계속해서 그 작업들을 수행함

 

(3) 파일에 데이터 쓰기

var fs = require("fs");

fs.writeFile("../output.txt","Hello World",function(err){
	if(err){
		console.log(err);
	}
	console.log("파일에 쓰기 완료");
});

 

(4) 파일 열고 쓰고 닫기

r: 읽기
w: 쓰기

a+ : 읽고 쓰기 (누적 O)
w+ : 읽고 쓰기 (누적 X)

var fs = require("fs");

fs.open("../output.txt","a+",function(err,fd){ // 열고
	
	if(err)
		throw err; //console로 찍는거랑 똑같은 것
	
	var buf = new Buffer("\n안녕!!");

	// null : 저장되는 위치 지정 (여기선 지정 안함)
	fs.write(fd,buf,0,buf.length,null,	// 쓰고
			function(err,written,buffer){
		
		if(err)
			throw err;
		
		console.log(err,written,buffer);
		// written은 버퍼크기 
		// 결과값: 9개 => 여기서 어디에 집어넣을지가 null 넣은 그 위치
		
		fs.close(fd,function(){ //닫고 
			console.log("파일 열고 데이터 쓰고 파일 닫기 완료");
		});
		
	});
 	
});

 

(5) 파일의 일부 내용 읽어오기

var fs = require("fs");

fs.open("../output.txt","r",function(err,fd){
	
	if(err){
		throw err;
	}
	
	console.log(fd);
	
	//버퍼에 사이즈를 주고 그만큼만 읽어오도록 시킨다
	var buf = new Buffer(10);		
	console.log("버퍼타입:" + Buffer.isBuffer(buf));
	
	// fd, buffer, offset, length, position, callback
	fs.read(fd,buf,0,buf.length,null,
			function(err,byteRead,buffer) {
				
				var inStr = Buffer.toString("UTF-8",0,byteRead);
				console.log("파일에서 읽은 데이터 :"+inStr);
		
			})	
	
})

 

(6) 파일을 읽어와서 다른 파일에 쓰기 (output.txt -> output2.txt)

createReadStream(), createWriteStream()

var fs = require("fs");

var infile = 
	fs.createReadStream("../output.txt",{flags:"r"});

var outfile = 
	fs.createWriteStream("../output2.txt",{flags:"w"});

// "data" - 예약어
infile.on("data",function(data){
	console.log("읽어들인 데이터: " + data);	
	outfile.write(data);
});

// "end" - 예약어
infile.on("end",function(){
	
	console.log("파일 읽기 종료");	
	
	outfile.end(function() {
		console.log("파일 쓰기 종료");
	})
	
});

 

(7) 디렉토리 만들고 삭제

// 디렉토리 만들기
var fs = require("fs");

fs.mkdir("../docs", function(err) {
	if(err){
		throw err;
	}	
	console.log("새로운 폴더 생성");	
});
//디렉토리 삭제하기
fs.rmdir("../docs",function(err){
	
	if(err){
		throw err;
	}
	
	console.log("새로운 폴더 삭제");
	
});

 


Buffer 객체

var output="수지!";
var buffer1 = new Buffer(10);
//utf-8 형식으로 집어넣는다 
var len = buffer1.write(output,"utf-8");
console.log("첫번째 버퍼의 문자열: "+ buffer1.toString());
console.log("첫번째 버퍼의 크기: "+ len);


//Buffer 만듬과 동시에 문자를 넣는다
var buffer2 = new Buffer("안녕","utf-8");
console.log("두번째 버퍼의 문자열: "+ buffer2.toString());
console.log("두번째 버퍼의 크기: "+ len);

//변수에 들어있는 것이 버퍼인지 아닌지 확인
console.log("버퍼 객체 타입: " + Buffer.isBuffer(buffer1));

//버퍼 객체에 있는 문자열 데이터를 문자열 변수로 만듬
var bytelen = Buffer.byteLength(output);

//버퍼 크기를 [수지!] 만큼 만듬
var str1 = buffer1.toString("utf-8", 0, bytelen);
//버퍼 크기를 [안녕]만큼 만듬
var str2 = buffer2.toString("utf-8");

//첫번째 버퍼의 객체를 두번째 버퍼로 복사
//복사하는 buffer의 사이즈에 따라.
buffer1.copy(buffer2,0,7,len);
console.log("버퍼 복사 후 문자열: " 
		+ buffer2.toString("utf-8"));

//두 개의 버퍼를 붙이기
var buffer3 = Buffer.concat([buffer1,buffer2]);
console.log("버퍼 붙인 후 문자열: " 
		+ buffer3.toString("utf-8"));