본문 바로가기

애플리케이션 개발/HRC(Home Remote Control)

3-4. Node.js를 이용한 웹 페이지 작성(파일 read/write 구현) 1

앞 시간에 node.js파일을 실행시켜 외부에서도 해당 페이지를 접속하는 방법을 알아보았다. 이번 시간에는 javascript를 이용해 파일을 입출력하는 방법을 구현해 볼 것이다. 

해당 포스팅은 이고잉님의 생활코딩(Node.js)이 굉장히 도움이 되었다. https://opentutorials.org/module/3549/21135

이고잉님께는 이 자리를 빌려 감사함을 전하고 싶다. 

 

이번 개발의 주요 사항은 다음과 같다. 

  • 페이지를 열었을 경우(open, reload, ...) 이전 상태가 유지하기(read)
  • 변경된 상태 반영하기(write)

 

다 작성하고 보니 코드가 너무 길어졌다. js파일에 html문과 script문을 다 넣었기 때문인데, 각각의 파일로 따로 관리하면 좋겠지만, 파라미터를 공유하고 있어서 잘 안되었다. 부분별로 나눠서 살펴보자. (전체 코드는 다음 포스팅을 참고하면 될 것이다)

 

먼저 HTML 문서이다. 

<!-----------------------------HTML GUI---------------------------->
<form action="/create" method="post">
    <h3>Test Buttons</h3>
    <ul>
        <li>
            <label><input type="checkbox" name="test1" id="btn1"> button1 </label>
            <label id = "label1"> ${readStr[0]} </label>
        </li>
        <li>
            <label><input type="checkbox" name="test2" id="btn2"> button2 </label>
            <label id = "label2"> ${readStr[1]} </label>
        </li>
        <p><input type="hidden" id="save"></p>
    </ul>
</form>
<!-----------------------------HTML GUI---------------------------->

"3-1. 서버 할당과 웹페이지 작성(taeminator1.tistory.com/4)"에서 작성한 것과 유사하지만 달라진 부분을 살펴보면, 

  1. 파일 write을 위한 save버튼을 추가했다. 해당 버튼은 체크박스가 누릴 때마다 동작하게 하면 되기 때문에 type을 hidden으로 설정하였다.
  2. <label>, </label> 사이에 checkbox를 넣어 checkbox옆의 이름을 누를 때도 버튼이 선택되도록 변경하였다. 

다음은 스크립트이다. 

//----------------------------JAVASCRIPT----------------------------
var writtenStr = ["", ""];
writtenStr[0] = ${readStr[0]};
writtenStr[1] = ${readStr[1]};

// 웹페이지가 로드될 때 실행
window.onload = function() {
  document.getElementById('btn1').checked = ${readStr[0]};
  document.getElementById('btn2').checked = ${readStr[1]};

  if(document.getElementById('btn1').checked) {
    document.getElementById('label1').innerHTML = 'on';
  } else {
    document.getElementById('label1').innerHTML = 'off';
  }

  if(document.getElementById('btn2').checked) {
    document.getElementById('label2').innerHTML = 'on';
  } else {
    document.getElementById('label2').innerHTML = 'off';
  }
}

// btn1의 상태값 변경시키는 EventListener
btn1.addEventListener('click', (event) => {    
  if(document.getElementById('btn1').checked) {
    document.getElementById('label1').innerHTML = 'on'; 
    writtenStr[0] = "true";
  } else {
    document.getElementById('label1').innerHTML = 'off'; 
    writtenStr[0] = "false";
  }
  document.getElementById('save').form.submit();            // checkbox 누를 때마다 상태 save
});
// btn2의 상태값 변경시키는 EventListener
btn2.addEventListener('click', (event) => {    
  if(document.getElementById('btn2').checked) {
    document.getElementById('label2').innerHTML = 'on'; 
    writtenStr[1] = "true";
  } else {
    document.getElementById('label2').innerHTML = 'off'; 
    writtenStr[1] = "false";
  }
  document.getElementById('save').form.submit();            // checkbox 누를 때마다 상태 save
});
//----------------------------JAVASCRIPT----------------------------

 

역시 크게 달라지지 않았으나, 버튼이 눌렸을 때 HTML문에서 작성한 save버튼이 눌리도록 했다. 그리고 불러온 파일에 있는 데이터를 readStr변수에 추가하여 사용했다. 코드를 정리한다고 했는데 반복되는 부분이 너무 많다. 

 

그리고 대망의 파일 읽기/쓰기 부분이다. 

fs.readFile('data.txt', 'utf8', function(err, description){
    var readStr = description.split("/");
    console.log("Success reading file")
    var template = templateHTML('Hmoe Remote Contorl', `
      <!-----------------------------HTML GUI---------------------------->
      ...
      <!-----------------------------HTML GUI---------------------------->`, `
      //----------------------------JAVASCRIPT----------------------------
      ...
      //----------------------------JAVASCRIPT----------------------------
    `);
    response.writeHead(200);
    response.end(template);
});


var body = '';
request.on('data', function(data){
  body = body + data;
});
request.on('end', function(){
  var post = qs.parse(body);
  var title = "data.txt";
  var description = "";
  if(post.test1 == "on") {
    description = "true/";
  } else {
    description = "false/";
  }
  if(post.test2 == "on") {
    description = description + "true";
  } else {
    description = description + "false";
  }

  fs.writeFile(`${title}`, description, 'utf8', function(err){
    response.writeHead(302, {Location: `/?id=${title}`});
    response.end();
    console.log("Success writing file")
  });
});

read/write를 위해 Javascript에서 제공하는 fs모듈을 이용하였다.

  1. fs.readFile()
    내가 저장하고자 하는 파일의 형태는 str1/str2/str3/... 이므로 split함수를 이용하여 읽은 파일을 '/'를 기준으로 나눈 뒤 각각을 readStr 배열에 저장하였다. 
  2. fs.writeFile()
    post방식으로 전달받은 데이터 값에 따라 description이라는 변수에 다르게(true 또는 false) 저장하였다. 파일을 읽는 경우 '/'를 기준으로 하여, 파일을 쓰는 경우에도, 각 상태마다 '/'를 붙여주었다. 

다음 포스팅에서 전체 코드와 잘 동작하는지 확인해보자.