본문 바로가기

카테고리 없음

Node.js 를 활용한 파일 시스템 조작과 데이터 처리

Node.js의 fs 모듈 소개와 장점

Node.js는 JavaScript를 사용하여 서버 사이드 애플리케이션을 개발할 수 있는 플랫폼입니다. Node.js는 다양한 내장 모듈을 제공하는데, 그 중 하나가 fs(file system) 모듈입니다. fs 모듈은 파일 시스템에 접근하고 조작할 수 있는 기능을 제공합니다. 예를 들어, 파일이나 폴더를 생성하고 삭제하고 읽고 쓰고 수정하고 복사하고 이동하고 압축하고 권한을 변경하고 등등의 작업을 할 수 있습니다.

 

fs 모듈의 장점은 다음과 같습니다.

- 별도의 설치 없이 바로 사용할 수 있습니다. Node.js에 내장되어 있기 때문에 require나 import 키워드로 불러오기만 하면 됩니다.

- 비동기와 동기 두 가지 방식으로 함수를 제공합니다. 비동기 함수는 콜백 함수나 프로미스(promise) 객체를 반환하고, 동기 함수는 바로 결과값을 반환합니다. 상황에 따라 적절한 방식을 선택할 수 있습니다.

- promises API를 통해 프로미스 기반의 비동기 함수를 사용할 수 있습니다. 이를 통해 then과 catch 메서드나 async/await 문법을 사용하여 비동기 코드를 간결하고 가독성 있게 작성할 수 있습니다.

- 스트림(stream) 객체를 사용하여 대용량 파일을 효율적으로 처리할 수 있습니다. 스트림은 파일을 작은 조각으로 나누어 순차적으로 읽거나 쓰는 방식으로, 메모리 사용량을 줄이고 성능을 향상시킬 수 있습니다.

 

fs 모듈의 주요 메서드와 사용 예시

fs 모듈에는 다양한 메서드가 있지만, 여기서는 가장 자주 사용되는 몇 가지 메서드에 대해서만 소개하겠습니다. 각 메서드는 비동기와 동기 두 가지 방식으로 제공되며, 비동기 함수는 이름 뒤에 Async 접미사가 붙습니다. 예를 들어, readFile과 readFileSync, writeFile과 writeFileSync 등이 있습니다.

 

readFile: 파일의 내용을 읽어오는 메서드입니다. 첫 번째 인자로 파일의 경로나 이름을 문자열로 전달하고, 두 번째 인자로 콜백 함수나 옵션 객체를 전달합니다. 콜백 함수는 에러 객체와 데이터 버퍼를 인자로 받습니다. 옵션 객체는 인코딩, 플래그, 모드 등을 설정할 수 있습니다. 아래코드처럼 사용할 수 있습니다.

// 비동기 방식
const fs = require("fs");

fs.readFile("test.txt", (err, data) => {
  if (err) {
    console.error(err);
  } else {
    console.log(data.toString()); // 파일의 내용을 문자열로 출력
  }
});

// 동기 방식
const fs = require("fs");

try {
  const data = fs.readFileSync("test.txt");
  console.log(data.toString()); // 파일의 내용을 문자열로 출력
} catch (err) {
  console.error(err);
}

writeFile: 파일에 내용을 쓰는 메서드입니다. 첫 번째 인자로 파일의 경로나 이름을 문자열로 전달하고, 두 번째 인자로 쓸 데이터를 문자열이나 버퍼로 전달합니다. 세 번째 인자로 콜백 함수나 옵션 객체를 전달합니다. 콜백 함수는 에러 객체를 인자로 받습니다. 옵션 객체는 인코딩, 플래그, 모드 등을 설정할 수 있습니다. 다음과 같이 사용할 수 있습니다.

// 비동기 방식
const fs = require("fs");

fs.writeFile("test.txt", "Hello, Node.js!", (err) => {
  if (err) {
    console.error(err);
  } else {
    console.log("파일 쓰기 완료");
  }
});

// 동기 방식
const fs = require("fs");

try {
  fs.writeFileSync("test.txt", "Hello, Node.js!");
  console.log("파일 쓰기 완료");
} catch (err) {
  console.error(err);
}

 

appendFile: 파일에 내용을 추가하는 메서드입니다. writeFile과 비슷하게 사용하지만, 기존의 파일 내용 뒤에 새로운 데이터를 덧붙입니다. 아래처럼 사용할 수 있습니다.

// 비동기 방식
const fs = require("fs");

fs.appendFile("test.txt", "\nNice to meet you!", (err) => {
  if (err) {
    console.error(err);
  } else {
    console.log("파일 내용 추가 완료");
  }
});

// 동기 방식
const fs = require("fs");

try {
  fs.appendFileSync("test.txt", "\nNice to meet you!");
  console.log("파일 내용 추가 완료");
} catch (err) {
  console.error(err);
}

 

copyFile: 파일을 복사하는 메서드입니다. 첫 번째 인자로 원본 파일의 경로나 이름을 문자열로 전달하고, 두 번째 인자로 복사할 파일의 경로나 이름을 문자열로 전달합니다. 세 번째 인자로 콜백 함수나 플래그를 전달합니다. 콜백 함수는 에러 객체를 인자로 받습니다. 플래그는 복사 옵션을 설정할 수 있습니다. 예시입니다.

// 비동기 방식
const fs = require("fs");

fs.copyFile("test.txt", "test2.txt", (err) => {
  if (err) {
    console.error(err);
  } else {
    console.log("파일 복사 완료");
  }
});

// 동기 방식
const fs = require("fs");

try {
  fs.copyFileSync("test.txt", "test2.txt");
  console.log("파일 복사 완료");
} catch (err) {
  console.error(err);
}

 

unlink: 파일을 삭제하는 메서드입니다. 첫 번째 인자로 삭제할 파일의 경로나 이름을 문자열로 전달하고, 두 번째 인자로 콜백 함수를 전달합니다. 콜백 함수는 에러 객체를 인자로 받습니다. 아래는 예시입니다.

// 비동기 방식
const fs = require("fs");

fs.unlink("test2.txt", (err) => {
  if (err) {
    console.error(err);
  } else {
    console.log("파일 삭제 완료");
  }
});

// 동기 방식
const fs = require("fs");

try {
  fs.unlinkSync("test2.txt");
  console.log("파일 삭제 완료");
} catch (err) {
  console.error(err);
}

 

fs 모듈의 비동기와 동기 함수의 차이와 선택 기준

fs 모듈의 메서드는 대부분 비동기와 동기 두 가지 방식으로 제공됩니다. 비동기 함수는 콜백 함수나 프로미스 객체를 반환하고, 동기 함수는 바로 결과값을 반환합니다. 비동기와 동기 함수의 차이와 선택 기준에 대해 알아보겠습니다.

 

비동기 함수는 파일 시스템 작업을 수행하는 동안 다른 작업을 병렬로 처리할 수 있습니다. 즉, 파일 시스템 작업이 완료될 때까지 기다리지 않고 다음 코드를 실행할 수 있습니다. 이는 Node.js의 이벤트 루프(event loop)와 스레드 풀(thread pool)을 활용하여 비동기적으로 작업을 처리하는 방식입니다. 비동기 함수는 성능과 효율성을 높일 수 있지만, 코드의 복잡도와 에러 처리에 주의해야 합니다. 콜백 함수를 중첩하게 되면 콜백 지옥(callback hell)이라는 현상이 발생할 수 있으므로, 프로미스나 async/await 문법을 사용하여 해결할 수 있습니다.

 

동기 함수는 파일 시스템 작업을 수행하는 동안 다른 작업을 처리할 수 없습니다. 즉, 파일 시스템 작업이 완료될 때까지 기다린 후에 다음 코드를 실행할 수 있습니다. 이는 Node.js의 메인 스레드에서 직접 작업을 처리하는 방식입니다. 동기 함수는 코드의 가독성과 간결성을 높일 수 있지만, 성능과 효율성을 저하시킬 수 있습니다. 특히, 여러 사용자의 요청을 처리하는 웹 서버와 같은 경우에는 동기 함수를 사용하면 안 됩니다. 그렇지 않으면, 한 사용자의 요청이 처리되는 동안 다른 사용자의 요청이 대기 상태가 되어 응답 속도가 느려질 수 있습니다.

 

따라서, 일반적으로는 비동기 함수를 사용하는 것이 권장됩니다. 하지만, 프로그램이 시작되거나 종료될 때 처럼 한 번만 실행되는 경우나, 순서가 중요한 경우에는 동기 함수를 사용할 수 있습니다.

 

fs 모듈의 promises API와 async/await 문법 활용 방법

fs 모듈은 promises API를 통해 프로미스 기반의 비동기 함수를 제공합니다. 이를 통해 then과 catch 메서드나 async/await 문법을 사용하여 비동기 코드를 간결하고 가독성 있게 작성할 수 있습니다. promises API와 async/await 문법의 활용 방법에 대해 알아보겠습니다.

 

promises API를 사용하기 위해서는 fs 모듈을 불러올 때 promises 속성을 명시해야 합니다. 다음과 같이 사용할 수 있습니다.

// promises API 사용
const fs = require("fs").promises;

fs.readFile("test.txt")
  .then((data) => {
    console.log(data.toString()); // 파일의 내용을 문자열로 출력
  })
  .catch((err) => {
    console.error(err);
  });

 

async/await 문법을 사용하기 위해서는 비동기 함수를 async 키워드로 선언하고, await 키워드로 프로미스 객체를 대기시켜야 합니다. 아래와 같이 사용합니다.

// async/await 문법 사용
const fs = require("fs").promises;

async function readTestFile() {
  try {
    const data = await fs.readFile("test.txt");
    console.log(data.toString()); // 파일의 내용을 문자열로 출력
  } catch (err) {
    console.error(err);
  }
}

readTestFile();

 

Node.js를 활용한 파일 시스템 조작과 데이터 처리에 대해 알아보았습니다. fs 모듈은 파일 시스템에 접근하고 조작할 수 있는 다양한 기능을 제공합니다. 비동기와 동기 두 가지 방식으로 함수를 사용할 수 있으며, promises API와 async/await 문법을 활용하여 비동기 코드를 간결하고 가독성 있게 작성할 수 있습니다. fs 모듈로 파일 데이터를 읽고 쓰고 수정하고 삭제하는 방법을 익혀서 Node.js 애플리케이션에서 파일 시스템을 효율적으로 다룰 수 있도록 해보세요.