그럼에도 불구하고

👨‍💻

[Node.js] writeFile vs writeFileSync 본문

Node.js/Node.js basics

[Node.js] writeFile vs writeFileSync

zenghyun 2023. 1. 28. 00:13

fs.writeFile과 fs.writeFileSync에 대해 알아보자

 

https://despiteallthat.tistory.com/131

 

[Node.js] 응답 헤더 / 라우터 요청 / 요청 리디렉션 / 요청 분석

응답 헤더 / 라우터 요청 / 요청 리디렉션 / 요청 분석에 대해 알아보자 [ 응답 헤더 ] const http = require('http'); // require 파일을 불러오는 방법 const server = http.createServer((req,res) => { res.setHeader('Content-Ty

despiteallthat.tistory.com

 

 

// 요청 본문 분석
// http 모듈 사용  
const http = require('http'); // require 파일을 불러오는 방법 
// ./:  상대경로 /: 절대경로 

const fs = require('fs');
const { parse } = require('path');


const server = http.createServer((req, res) => {
  const url = req.url;
  const method = req.method;

  if (url === '/') {
    res.write('<html>');
    res.write('<head><title>Enter Message</title></head>');
    res.write('<body><form action="/message" method="POST"><input type ="text" name="message"><button type="submit">Send</button></form></body>');
    res.write('</html>');
    return res.end();
  }

  if (url === '/message' && method === 'POST') {
    const body = [];
    req.on('data', (chunk) => {
      console.log(chunk);
      body.push(chunk);
    });
    req.on('end', () => {
      const parsedBody = Buffer.concat(body).toString();
      console.log(parsedBody);
      // input name을 message라고 지어서 message= 출력된다.
      const message = parsedBody.split('=')[1];
      fs.writeFileSync('message.txt', message);
    });

    res.statusCode = 302;
    res.setHeader('Location', '/');
    return res.end();
  }
  res.setHeader('Content-Type', 'text/html');
  res.write('<html>');
  res.write('<head><title>My First Page</title></head>');
  res.write('<body><h1>Hello from my Node.js Server!</h1></body>');
  res.write('</html>');
  res.end();
}); // 서버를 생성할 때 꼭 필요한 메서드 

server.listen(3000);

 

지난 글에서 작성한 js 파일이다.

 

여기서 message.txt를 만들 때 fs.writeFileSync 메서드를 사용했다.

여기서 Sync는 동기화를 의미하며, 이 파일이 생성되기 전까지 코드 실행을 막는 특별한 메서드를 말한다. 

파일이 완료될 때까지 코드의 다음 라인이 실행되지 않도록 하는 것을 동기화 모드라고 하는 것이다. 

 

우리가 입력하는 짧은 텍스트의 경우 알아차리지도 못할 정도로 아주 빠르지만, 수백 메가바이트 이상의 큰 파일에서 writeFileSync의 경우 읽거나 복사하는 등의 상황에서 코드 실행을 막는 경우 다음 줄과 다른 모든 코드가 파일 운영이 완료될 때까지 실행을 멈출 것이다. 

 

또한, 다른 유저들이 보내서 새로 유입되는 요청들도 파일 운영이 끝나기 전까지는 취급되지 않을 것이다. 

 

그래서 매우 짧은 파일 운영만을 진행하는 경우에는 사용할 수 있지만 그렇다 하더라도 writeFile 메서드를 사용하는 편이 좋다. 

 

writeFile 메서드의 경우 경로와 데이터를 받아들일 뿐만 아니라 세 번째 인수인 콜백까지도 사용할 수 있으며, 따라서 완료된 뒤에 실행되어야 하는 함수에 해당된다. 그래서 서버 생성때와 마찬가지로 Node.js는 암묵적으로 이벤트 리스너를 등록시킨다. 

 

   fs.writeFile('message.txt', message, err => {
        res.statusCode = 302;
        res.setHeader('Location', '/');
        return res.end();
      });

 

세 번째 인수에서 다른 함수를 넘기고 이 콜백은 오류 객체를 전달받을 수 있다. 

위의 코드와 같이 사용한다면 오류가 발생하지 않았을 때는 공란으로 남지만, 권한 누락을 비롯한 어떤 오류가 발생한 경우라면 세 번째 인수에 적힌 함수의 { }으로 가져오게 된다. 그리고 사용자에게 오류가 발생했음을 나타내는 오류 응답 등을 반환하고 그렇지 않다면  위의 코드처럼 정상 응답을 반환하는 방식으로 처리할 수 있다. ( 지금은 오류가 나지 않는 상황을 가정 ) 

 

위와 같이 작성하면 이벤트 리스너와 함께 요청을 파싱하는 것이 끝난 뒤 실행하게 될 매서드, 내지는 함수를 확보하게 된다. 또한 추후 언젠가 실행될 해당 함수 내부에도 또 다른 이벤트 리스너가 있고 이렇게 중첩된 함수는 파일을 기록하는 과정이 끝난 뒤에 실행될 것이다. 

 

이벤트 드리븐 아키텍처에서는 Node.js에게 작업을 진행하도록 지시하며, 이후 Node.js가 해당 프로세스를 멀티 스레딩을 사용하는 운영체제에 전달한다. 또한, 이벤트 콜백을 파악하기 위해 이벤트 루프를 계속하면서 코드 실행을 막지 않도록 할 것이다. 

 

운영체제에서 작업이 끝난 뒤에는 항상 복귀하는 식의 구조를 지니는데 이것이 Node.js의 구조이며 개발자의 코드를 절대 막지 않고, 서버를 막는 일도 없으며, 계속해서 운영체제에게 작업들을 할당하고 완료된 뒤에는 돌아와서 콜백에서 응답을 전달하는 등의 작업을 진행한다.

 

이는 헤더 몇 개만 진행하면 끝나는 작업이므로 전체 운영을 막는 일이 없다. 

 

간단하게 요약하자면 writeFileSync 보다는 writeFile 메서드를 사용하는 것이 좋을 것 같다.

Comments