본문 바로가기

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

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

이전 포스팅에서 개별적으로 살펴본 코드를 합친 전체 코드이다. 전역 변수로 fs모듈을 불러왔고, 공유기에서 설정한 내부 포트 번호도 선언했다. 

 

그리고 HTML 코드가 너무 복잡해서 templageHTML함수를 통해 조금이나마 코드를 보기 쉽게 만들었다. 

 

app.js

var http = require('http');
var fs = require('fs');
var url = require('url');
var qs = require('querystring');

const inPort = 80;            // 내부 포트 번호
 
function templateHTML(title, gui, script) {
  return `
  <!doctype html>
    <html>
    <head>
      <title>${title}</title>
      <meta charset="utf-8">
    </head>
    <body>
      ${gui}
      <script>
        ${script}
      </script>
    </body>
    </html>
  `;
}
var app = http.createServer(function(request,response){
    var _url = request.url;
    var pathname = url.parse(_url, true).pathname;
    if(pathname === '/'){           // URL에 주소 입력시 동작
        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---------------------------->
              <form action="/create" method="post">
                  <h3>Test Buttons</h3>
                  <ul>
                      <li>
                          <label><input type="checkbox" name="test1" id="btn1"> button1 </label>
                          <label id = "label1">  </label>
                      </li>
                      <li>
                          <label><input type="checkbox" name="test2" id="btn2"> button2 </label>
                          <label id = "label2">  </label>
                      </li>
                      <p><input type="hidden" id="save"></p>
                  </ul>
              </form>
              <!-----------------------------HTML GUI---------------------------->`, `
              //----------------------------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----------------------------
            `);
            response.writeHead(200);
            response.end(template);
      });
    } else if(pathname === '/create'){      // submit 버튼 누를 시 동작
      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")
        });
      });
    } else {
      response.writeHead(404);
      response.end('Not found');
    }
});
app.listen(inPort, function() {       // 내부 포트 번호: 80, 외부 포트 번호는 웹브라우저의 주소창에 입력
  console.log("HRC node.js is running on port %d", inPort);
});

 

app.js 파일과 동일한 경로에 data.txt를 추가하고 "true/true"를 입력한 뒤 app.js를 콘솔에서 실행시켰다. 그리고 웹브라우저에서 확인하면 다음과 같이 나오는 것을 알 수 있다. 

여기서 button1의 체크를 해제해 보면, 

다음과 같이 data.txt 안에 데이터가 "false/true"로 수정되는 것을 알 수 있다. 

 

엣지, 크롬, 사파리에서 테스트한 결과 모두 잘 되었다. 그리고 아이폰에서도 정상적으로 잘 동작하는 것을 확인했다. 

개선해야 할 부분은 각각의 부분을 어떻게 독립적으로 만들지(HTML, Javascript 개별적으로)와 여러 가지 예외처리들(텍스트 파일이 없을 경우 어떻게 읽을 것인지, 원하지 않는 사용자가 접속하면 어떻게 할지 등)이다. 

 

서버를 구축하고 통신하는데 시간이 많이 걸렸다. 처음 접해보는 개념들이 너무 많았고, 언어도 처음 다뤄보는 것이어서 그런지 생각보다 더 많은 시간이 걸렸다. 처음에는 굉장히 단순할 거라고 생각했는데, 생각처럼 쉽지 않았다. 그래도 이렇게 구현했으니 앞으로 남은 개발은 조금은 쉽지 않을까?(이 생각이 허황된 것이란 걸 이제는 감으로 알지만...)

 

다음 시간부터 아이폰 애플리케이션에서 해당 웹페이지를 컨트롤하는 방법에 대해 알아볼 것이다.