파일 시스템에 접근하는 모듈이다. 파일이나 디렉토리를 생성, 삭제는 물론 읽고 수정할 수 있다.
// 'Read Me!'가 입력되어 있는 readme.txt를 읽는 예
import fs from "fs";
fs.readFile("./readme.txt", (err, data) => {
if (err) {
throw err;
}
console.log(data);
console.log(data.toString());
});
/* 결과
<Buffer 52 65 61 64 20 4d 65 21>
Read Me!
*/
readFile
은 읽어올 파일의 경로를 받아 콜백 함수에서 처리한다. data
에 담긴 Buffer
는 파일 데이터가 저장된 메모리이다. 사람이 읽을 수 있도록 toString
을 통해 문자열로 변환한다. 콜백 함수가 불편하다면 Promise
형식으로 변환하여 사용할 수 있다.
fs.promises
.readFile("./readme.txt")
.then((data) => {
console.log(data);
console.log(data.toString());
})
.catch((err) => console.error(err));
파일의 생성은 writeFile
을 사용한다.
fs.writeFile("./writeme.txt", "Write Me!", (err) => {
if (err) {
throw err;
}
fs.readFile("./writeme.txt", (err, data) => {
if (err) {
throw err;
}
console.log(data.toString());
});
});
/* 결과
Write Me!
*/
인자로 (경로, 내용, 콜백)
을 받으며, 내용 확인을 위해 readFile
을 사용했다.
readFile
은 비동기 메서드로, 여러 번 파일을 읽을 때마다 결과 출력의 순서가 달라진다. 동기적으로 읽어오고 싶다면 readFileSync
를 사용한다.
console.log(1, fs.readFileSync("./readme.txt").toString());
console.log(2, fs.readFileSync("./readme.txt").toString());
console.log(3, fs.readFileSync("./readme.txt").toString());
/* 결과
1 Read Me!
2 Read Me!
3 Read Me!
*/
readFileSync
의 치명적인 단점은 요청이 많이 들어왔을 때의 성능이다. 이전 요청 처리가 끝나야 다음 작업을 진행하기 때문이다. 대부분의 경우에는 비동기 메서드가 훨씬 효율적이다.
비동기 방식으로 하되 실행 순서를 유지하려면 콜백 지옥에서 순차적으로 읽거나 Promise
형식을 사용한다.
// 콜백 지옥형 순차 호출
fs.readFile("./readme.txt", (err, data) => {
if (err) {
throw err;
}
console.log(1, data.toString());
fs.readFile("./readme.txt", (err, data) => {
if (err) {
throw err;
}
console.log(2, data.toString());
fs.readFile("./readme.txt", (err, data) => {
if (err) {
throw err;
}
console.log(3, data.toString());
});
});
});
// Promise 형식 순차 호출
fs.promises
.readFile("./readme.txt")
.then((data) => {
console.log(1, data.toString());
return fs.promises.readFile("./readme.txt");
})
.then((data) => {
console.log(2, data.toString());
return fs.promises.readFile("./readme.txt");
})
.then((data) => {
console.log(3, data.toString());
})
.catch((err) => console.error(err));
fs.access(경로, 옵션, 콜백)
: 폴더나 파일에 접근할 수 있는지 체크한다. 옵션
으로 권한 여부를 확인한다. fs
의 constants
로 가져오며 F_OK
는 파일 존재 여부, R_OK
는 읽기 권한 여부, W_OK
는 쓰기 권한 여부를 확인한다.fs.mkdir(경로, 콜백)
: 폴더를 만든다.fs.open(경로, 옵션, 콜백)
: 파일의 아이디를 가져온다. 파일이 없다면 생성 후 가져온다. 아이디를 활용해 fs.read
or fs.write
로 읽고 쓸 수 있다. 옵션
은 쓰기는 w
, 읽기는 r
, 기존 파일에 추가는 a
를 입력한다.fs.rename(기존 경로, 새 경로, 콜백)
: 파일 이름을 바꾼다.fs.readdir(경로, 콜백)
: 폴더 내부를 확인한다.fs.unlink(경로, 콜백)
: 파일을 지운다. 파일이 없으면 에러가 발생한다.fs.rmdir(경로, 콜백)
: 폴더를 지운다. 폴더 안에 파일이 있으면 에러가 발생한다.fs.copyFile(복사할 파일, 복사될 경로, 콜백)
: 파일을 복사한다.fs.watch(경로, 콜백)
: 파일 변경 이벤트를 감지한다.이벤트를 만들고 호출하는 모듈이다. new EventEmitter()
객체에 이벤트 관리를 위한 메서드가 있다.
on(이벤트명, 콜백)
: 이벤트명
에 콜백을 연결한다.addListener(이벤트명, 콜백)
: on
과 같다.emit(이벤트명)
: 이벤트를 호출한다. on('hello', ()=>{console.log('hello')})
이벤트를 등록했다면, emit('hello')
로 호출할 수 있다.once(이벤트명, 콜백)
: 한 번만 실행되는 이벤트다.removeAllListeners(이벤트명)
: 연결된 모든 이벤트 리스너를 제거한다.removeListener(이벤트명, 리스너)
: 연결된 리스너를 제거한다.off(이벤트명, 콜백)
: removeListener
와 같다.listenerCount(이벤트명)
: 현재 연결된 리스너의 개수를 확인한다.노드는 메인 스레드가 하나이기 때문에 예외(에러) 발생 시 서버 전체가 멈출 수 있다. 따라서 신중한 예외 처리가 필요하다.
내부 모듈에 error
인자를 받는 콜백 함수가 있는 경우, 쉽게 에러를 처리할 수 있다.
fs.readFile("./readme.txt", (err, data) => {
if (err) {
console.log(err);
}
});
throw
로 err
를 보낼 경우 프로세스가 멈춘다. 이때는 try/catch
문으로 처리해야 한다.
프로미스 에러는 반드시 catch
해야 한다.