Node.js 환경에서 파일을 읽고 쓰기 위한 모듈이 File System(fs) 모듈입니다. 파일을 읽고, 쓸수도 있고 폴더를 생성할 수도 있습니다.
Node.js는 1개의 스택을 가진 프로그래밍 언어로 비동기 방식을 사용해 파일을 읽고 쓰게 됩니다. 이 때 필요한 개념이 Promise입니다. fs 모듈에서는 동기로 사용할 수 있는 readFileSync와 Promise 기능을 지원합니다.
Read File
먼저 파일을 읽어들이기 위해서는 fs 모듈의 readFile 함수를 사용합니다.
fs 모듈의 readFile은 첫번째 인자로 파일의 경로를 입력받습니다.
두번째 인자로는 콜백함수를 전달받아 data를 핸들링할 수 있습니다.
const fs = require("fs")
fs.readFile('./newFile.txt', (err, data)=>{
if(err) throw err;
console.log(data);
})
자 이제 위 코드를 실행해보면 Buffer가 등장합니다. fs 모듈은 기본적으로 buffer 형식으로 파일을 읽어들이게 됩니다. 사람이 읽기 위한 코드가 아니므로, toString을 사용해 읽을 수 있습니다.
<Buffer 74 65 73 74 20 74 65 78 74>
buffer로 전달된 코드를 toString()으로 변경해 출력했습니다. toString() 에는 인코딩을 위한 다양한 옵션이 존재합니다. 'base64', 'utf8' 등으로 인코딩을 하면 양식에 맞게 버퍼가 변경되어 출력됩니다.
console.log(data.toString());
test text
콜백 형식으로 fs 모듈을 사용하면 불편하기 때문에 promise 형태로 변경해 사용가능합니다. require('fs') 뒤에 promises를 붙여줘서 모듈을 가져옵니다.
비동기 형식인 promise로 전달된 fs 결과물을 then() ~ catch()로 받아 결과물을 출력합니다.
const fs = require("fs").promises;
fs.readFile("./test.txt")
.then((result) => {console.log(result.toString())})
.catch((err) => console.log(err));
Write File
fs 모듈로 쓰기 과정은 writeFile 함수를 사용합니다.
첫번째 인자로는 생성할 파일명을 적어주시고,
두번째 인자로는 입력할 데이터를 보내줍니다.
아래 예제는 파일을 생성하고 readFile 함수로 데이터를 읽어와 출력하는 간단한 예제입니다.
const fs = require("fs").promises;
fs.writeFile("./newFile.txt", "test text")
.then(() => {
return fs.readFile("./newFile.txt");
})
.then((data) => {
console.log(data.toString());
})
.catch((err) => {
console.error(err);
});
Fils System 동기 VS 비동기
Javascript는 단 1개의 스택을 가지고 작동하는 프로그램 환경입니다. 이 말인즉슨 동시에 여러개의 프로세스를 처리할 수 없다는 말이 됩니다. 하지만 우리는 프로그램을 작성할 때 setTimeout도 사용하고 비동기 모듈인 fs도 사용합니다. 어떻게 이게 가능할까요?
JS에서 비동기를 처리하기 위해서는 스택외에 Queue라는 또 다른 자료구조가 존재합니다. 백그라운드에서 작동하는 Queue는 비동기로 넘어온 프로세스들을 관리하고 JS가 마치 멀티 프로세스 프로그램처럼 작동하도록 도와줍니다.
fs 모듈도 비동기 모듈이기 때문에 아래 예제처럼 작동시키면 작동순서를 보장할 수 없습니다. test3.txt가 제일 먼저 출력되는 경우도 있고, 아닌 경우도 있습니다. 비동기 모듈이기 때문에 모든 처리를 백그라운드에서 진행되기 때문에 발생되는 일입니다. 즉, 읽기 과정을 백그라운드에 위임하고, 읽기가 완료되면 메인 스레드에 완료를 알리고 console.log() 가 찍히게 됩니다.
const fs = require("fs")
fs.readFile('./test1.txt', (err, data)=>{
if(err) throw err;
console.log(data.toString());
})
fs.readFile('./test2.txt', (err, data)=>{
if(err) throw err;
console.log(data.toString());
})
fs.readFile('./test3.txt', (err, data)=>{
if(err) throw err;
console.log(data.toString());
})
fs 모듈을 동기 모듈로 사용하기 위해서는 readFileSync() 나 writeFileSync() 함수를 사용하면 됩니다. 동기 모듈은 파일을 읽어오는 과정을 백그라운드에 위임하지 않고 메인스레드에서 처리합니다. 만약 대규모의 요청이 들어오면 100% 병목현상이 생기는 문제가 있지만 실행 순서를 보장할 수 있습니다.
const fs = require('fs');
const data1 = fs.readFileSync('./test1.txt')
console.log(data1.toString());
const data2 = fs.readFileSync('./test2.txt')
console.log(data2.toString());
const data3 = fs.readFileSync('./test3.txt')
console.log(data3.toString());
콜백 지옥을 피하면서 순서를 보장하면서 비동기로 fs 모듈을 사용하기 위해서는 Promise 형태로 fs 모듈을 사용하면 문제를 해결할 수 있습니다.
const fs = require("fs").promises;
fs.readFile("./test1.txt")
.then((data1) => {
console.log(data1.toString());
return fs.readFile("./test2.txt");
})
.then((data2) => {
console.log(data2.toString());
return fs.readFile("./test3.txt");
})
.then((data3) => {
console.log(data3.toString());
});
'Programming' 카테고리의 다른 글
Node.js Error Handling Object 에러 처리하기 (0) | 2022.09.03 |
---|---|
Node.js fs.access fs.mkdir fs.open fs.rename 사용법 (0) | 2022.09.03 |
Buffer Stream 이란? Node.js 버퍼 스트림 파이프 사용법 (0) | 2022.09.02 |
Node.js crypto 비대칭키 대칭키 구현하기 (0) | 2022.09.02 |
Node.js cookie 사용법 (로그인에 쿠키를 사용하면 안되는 이유) (1) | 2022.08.27 |
댓글