NodeJS 입출력
Node는 입출력을 처리할 때 이벤트를 기반으로 하는 비동기 방식으로 처리합니다.
그러나 모든 입출력을 비동기 방식으로만 처리하는 것은 아니며 동기방식으로 처리할 수 있는 방법도 제공하고 있습니다. 이러한 처리 방법을 구분하기 위해 메서드에 동기방식의 경우 다음과 같이 Sync라는 접미사를 붙입니다. 즉 Sync라는 접미사가 붙는 메서드의 경우 동기방식으로 입출력을 수행한다고 생각할 수 있습니다.
fs.readFileSync('~~/~~.txt');
fs.writeFileSync('~~/~~.txt');



동기식 입출력과 비동기식 입출력
그럼 비동기방식 입출력이란 무엇이고 동기 입출력과는 어떤 차이가 있는것일까요?
정말 간단히 차이점을 설명하자면 먼저 기존 다른 플랫폼에서의 기본적인 동기 입출력방식은 다음과 같습니다.
입출력이 시작되고 입출력이 끝날때까지 다음 로직을 수행하지 않고 대기하며 입출력이 끝나고 나서야 다음 로직을 수행하게 됩니다.
입출력이 일어나는 시간동안에는 다른 로직의 수행이 막히게(Blocking) 되므로 Blocking 방식이라고도 합니다.



반대로 비동기 방식은 기본 로직의 실행이 이루어짐과 동시에 입출력이 별도로 실행됩니다.
Node에서는 이러한 비동기 방식으로 입출력을 수행 하는데 비동기 입출력이 끝나게 되는 경우 실행될 이벤트리스너를 등록합니다.
다음 그림과 같이 기존 로직은 입출력시 멈추지 않고 그대로 수행되며 입출력이 끝난 후에 등록한 이벤트리스너(콜백함수)를 호출하여 수행하게 됩니다.




입출력 수행하기
Node에서는 파일시스템(File System)을 다루기 위한 fs 모듈을 제공하며 다음과 같이 require()를 통해 불러올 수 있습니다.
var fs = require('fs');

동기식 입력의 경우 다음과 같이 사용가능합니다.
같은 디렉터리 상에 있는 exam.txt 파일을 읽어들인 후 읽어들인 데이터를 출력합니다.
var fs = require('fs');

console.log('입출력 수행');

var data = fs.readFileSync('./exam.txt', 'utf8');

console.log('입출력 수행 종료');

console.log(data);

exam.txt 

exam.txt 파일 입니다.


출력내용 

입출력 수행
입출력 수행 종료
exam.txt 파일 입니다.




비동기식 입력의 경우에는 다음과 같이 사용합니다. readFile() 메서드를 보면 세 번째 파라미터로 콜백함수를 넘기는것을 볼 수 있는데, 입력이 끝나게 되면 해당 콜백함수가 실행되면서 에러가 발생한 경우 에러 정보를 err 파라미터에 넘겨주고 입력으로 불러온 데이터를 data 파라미터로 넘겨주게 됩니다.
여기서 중요한 점은 입출력이 완료되기 전에 '다음 로직 실행' 이 출력되었다는 점입니다. 이는 입출력을 수행하는 동안 메인 프로세스가 멈추지 않고 계속 진행됐다는 것을 의미합니다. 
물론 입출력이 console.log('다음 로직 실행')가 실행되기 전에 끝날 수도 있으므로 출력 결과가 매번 다음과 같다는 것은 보장할 수 없습니다.
var fs = require('fs');

console.log('입출력 수행');

fs.readFile('./exam.txt', 'utf8', function(err, data) {
    console.log(data);
});

console.log('다음 로직 실행');
입출력 수행
다음 로직 실행
exam.txt 파일 입니다.



동기식 출력의 경우 다음과 같이 사용 가능합니다.
첫번째 파라미터로 출력할 파일의 경로를 지정하며 두번째 파라미터로는 출력할 데이터를 지정합니다. 세번째 파라미터로는 입출력시 사용할 옵션값들을 지정하는데 문자 인코딩이나 입출력시 출력 옵션을 지정하는데 'w'인 경우 출력시 경로에 해당 파일이 존재하지 않는 경우 파일을 만들면서 출력하며 이미 파일이 존재하는 경우 내용을 삭제하고 출력 한다는 뜻 입니다. 옵션을 따로 넘기지 않는 경우 기본값으로 utf8과 w가 사용됩니다.
var fs = require('fs');

var data = '파일에 출력할 데이터';

var option = { encoding: 'utf8', flag: 'w' };

fs.writeFileSync('./output.txt', data, option);

output.txt에 출력된 내용

파일에 출력할 데이터



동기식 입출력의 경우 에러가 발생하면 다음과 같이 처리할 수 있습니다. 

try{
    var data = fs.readFileSync('./exam.txt', 'utf8');
}catch(e){
    console.log(e);
}




비동기식 출력의 경우 다음과 같이 사용 가능합니다.
기본적인 내용은 동기식 내용과 같으며 비동기식으로 입출력을 수행한다는 것과 입출력 수행후 실행되는 콜백 함수에 에러가 나는 경우 err 파라미터로 에러 내용이 넘겨진다는 점이 다릅니다.
var fs = require('fs');

var data = '파일에 출력할 데이터(비동기 출력)';
var options = { encoding: 'utf8', flag: 'w' };

fs.writeFile('./output.txt', data, options, function(err) {

    //에러가 없는 경우 null이 넘어오므로 수행되지 않음
    if(err) {
        console.log('Error : ' + err);
    }

    console.log('출력 완료');
});


output.txt에 출력된 내용

파일에 출력할 데이터(비동기 출력)



파일에 내용 추가로 출력하는 방법
파일을 만들면서 입출력하지 않고 기존에 존재하는 파일에 원할때마다 내용을 추가하고 싶은 경우가 있습니다.
이러한 경우 appendFile() 메서드를 이용하면 됩니다.
data 앞에 '\n' 가 있는데 이는 줄넘김을 의미하며 파일에 있는 기존 데이터 뒤에 문자열이 붙지 않고 한 줄 내려 추가되도록 하기 위함 입니다.
appendFile()을 수행할때마다 내용이 한줄씩 추가됨을 알 수 있습니다.
var fs = require('fs');

var data = '\n파일에 추가할 내용';
var options = { encoding: 'utf8', flag: 'a' };

fs.appendFile('./output.txt', data, options);


output.txt

기존내용
파일에 추가할 내용



 

입출력 플래그
입출력 수행시 공통 옵션으로 flag 값을 넘기는것을 알 수 있습니다. 옵션을 따로 넘기지 않는 경우 기본 플래그값들이 사용되지만 임의로 플래그를 지정해서 행동을 제어 할 수 있습니다. 대표적인 플래그는 다음과 같습니다.

플래그
설명
r
입력(read) 시 사용하는 플래그입니다. 지정해준 경로에 대상 파일이 없으면 예외가 발생합니다.
w
출력시(write) 사용하는 플래그입니다. 지정해준 경로에 대상 파일이 없으면 만들어 출력하고
파일이 이미 존재하면 기존 내용을 모두 삭제하고 출력합니다.
w+
입출력시 모두 사용하는 플래그입니다. 지정해준 경로에 대상 파일이 없으면 만들고 파일이 이미 존재하면 기존 내용을 모두 삭제 합니다.
a+
입출력시 모두 사용하는 플래그입니다. 지정해준 경로에 대상 파일이 없으면 만들고 파일이 이미 존재하면 기존 내용에 데이터를 추가 합니다.


블로그 이미지

도로락

IT, 프로그래밍, 컴퓨터 활용 정보 등을 위한 블로그

댓글을 달아 주세요! 질문 환영합니다!