2023-01-31 node.js_8

WEB2 – Node.js – 생활코딩

생활코딩 node.js 강의 정리


1. Not found 구현

기존에 코드를 개선할 거다.

대상 코드는 url의 분석해서 존재하는 페이지인지 혹은 존재하지 않는 페이지인지 판단하는 코드다.

// 수정할 부분
...
if(_url == '/'){
    title = 'Welcome';
}
if(_url == '/favicon.ico'){
    response.writeHead(404);
    response.end();
    return;
}
...
response.writeHead(200);
...
Code language: JavaScript (javascript)

우리가 고려해야 할 경우의 수는 3가지다.

var pathname = url.parse(_url, true).pathname;

if(pathname === '/') {
    if(queryData.id === undefined) {
        // 1번 case
    }else{
        // 2번 case
    }
}else{
    // 3번 case
}
Code language: JavaScript (javascript)
  • var pathname = url.parse(_url, true).pathname;
    : url 정보 중 경로(path)에 관한 정보만 추출해 저장한다.

이제 각각의 case일 때 어떻게 동작해야 하는지 생각해 보자.


가. 1번 case

1번 case의 경우 root 페이지를 보여주면 된다.

var title = 'Welcome';
var description = 'Hello Node.js';
var template = ` ... `;
response.writeHead(200);
response.end(template);
Code language: JavaScript (javascript)

나. 2번 case

2번 case의 경우에는 쿼리스트링에 맞게 파일을 읽어와서 본문을 구성하면 된다.

fs.readFile(`data/${queryData.id}`, 'utf-8', function(err, description){
    var title = queryData.id;
    var template = ` ... `;
    response.writeHead(200);
    response.end(template);
});
Code language: JavaScript (javascript)

다. 3번 case

3번 case는 존재하지 않는 페이지라고 알려주면 된다.

주소를 잘못 입력한 경우 자주 겪어봤을 것이다.

우리도 똑같이 하면 된다.

앞서 response.writeHead(200);라는 코드를 많이 봤을 것이다.

해당 코드의 숫자가 바로 HTTP 응답 코드다.

200은 파일이 성공적으로 전송되었음을 나타낸다.

404 코드로 응답하면 Not Found 즉 요청한 파일이 없다는 뜻이다.

response.writeHead(404);
response.end('Not found');
Code language: JavaScript (javascript)

라. 합치기

엑조디아를 완성해 보자.

var http = require("http");
var fs = require("fs");
var url = require("url");

var app = http.createServer(function (request, response) {
  var _url = request.url;
  console.log(_url);
  var queryData = url.parse(_url, true).query;
  var pathname = url.parse(_url, true).pathname;

  if (_url == "/style.css") {
    response.writeHead(200, { "Content-type": "text/css" });
    var fileContents = fs.readFileSync("style.css", "utf-8");
        response.write(fileContents);
    response.end();
  }

  if (_url == "/color.js") {
    response.writeHead(200, { "Content-type": "text/js" });
    var fileContents = fs.readFileSync("color.js", "utf-8");
        response.write(fileContents);
    response.end();
  }

  if (pathname === "/") {
    if (queryData.id === undefined) {
      var title = "Welcome";
      var description = "Hello Node.js";
      var template = `
          <!DOCTYPE html>
          <html lang="en">
            <head>
              <meta charset="UTF-8" />
              <meta http-equiv="X-UA-Compatible" content="IE=edge" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>WEB - ${title}</title>
              <link rel="stylesheet" href="style.css">
              <script src="color.js"></script>
            </head>
            <body>
              <div id="top">
                <h1><a href="/"></a></h1>
                <input type="button" value="night" onclick="nightDayHandler(this)"/>
              </div>
              <div id="grid">
                <ul>
                  <li><a href="/?id=black%20tea">홍차</a></li>
                  <li><a href="/?id=oolang%20tea">우롱차</a></li>
                  <li><a href="/?id=green%20tea">녹차</a></li>
                </ul>
                <div id="article">${description}</div>
              </div>
            </body>
          </html>
        `;

      response.writeHead(200);
      response.end(template);
    } else {
      fs.readFile(`data/${queryData.id}`, "utf-8", function (err, description) {
        var title = queryData.id;
        var template = `
              <!DOCTYPE html>
              <html lang="en">
                <head>
                  <meta charset="UTF-8" />
                  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
                  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                  <title>WEB - ${title}</title>
                  <link rel="stylesheet" href="style.css">
                  <script src="color.js"></script>
                </head>
                <body>
                  <div id="top">
                    <h1><a href="/"></a></h1>
                    <input type="button" value="night" onclick="nightDayHandler(this)"/>
                  </div>
                  <div id="grid">
                    <ul>
                      <li><a href="/?id=black%20tea">홍차</a></li>
                      <li><a href="/?id=oolang%20tea">우롱차</a></li>
                      <li><a href="/?id=green%20tea">녹차</a></li>
                    </ul>
                    <div id="article">${description}</div>
                  </div>
                </body>
              </html>
            `;
        response.writeHead(200);
        response.end(template);
      });
    }
  } else {
    response.writeHead(404);
    response.end("Not found");
  }
});
app.listen(3000);
Code language: HTML, XML (xml)

이렇게 하면 망한다.

왜냐 …

 if (_url == "/style.css") {
    response.writeHead(200, { "Content-type": "text/css" });
    var fileContents = fs.readFileSync("style.css", "utf-8");
        response.write(fileContents);
    response.end();
  }

  if (_url == "/color.js") {
    response.writeHead(200, { "Content-type": "text/js" });
    var fileContents = fs.readFileSync("color.js", "utf-8");
        response.write(fileContents);
    response.end();
  }
Code language: JavaScript (javascript)

이 부분과 …

    } else {
    response.writeHead(404);
    response.end("Not found");
  }
});
Code language: JavaScript (javascript)

이 부분 때문이다.

우리가 style.css와 color.js를 가져오면서 한번 response.end()를 실행한다.

문제는 style.css와 color.js는 우리가 분류한 3번 case에 포함된다.

이에 response.end()가 2번 실행되며 Error [ERR_STREAM_WRITE_AFTER_END]: write after end와 같은 오류가 발행한다.

해결하기 위해서 3번 case를 아래와 같이 수정한다.

} else {
    if (_url == "/style.css") {
      response.writeHead(200, { "Content-type": "text/css" });
      var fileContents = fs.readFileSync("style.css", "utf-8");
      response.write(fileContents);
      response.end();
    } else if (_url == "/color.js") {
      response.writeHead(200, { "Content-type": "text/js" });
      var fileContents = fs.readFileSync("color.js", "utf-8");
      response.write(fileContents);
      response.end();
    } else {
      response.writeHead(404);
      response.end("Not found");
    }
  }
Code language: JavaScript (javascript)

최종적으로 아래와 같이 된다.

var http = require("http");
var fs = require("fs");
var url = require("url");

var app = http.createServer(function (request, response) {
  var _url = request.url;
  console.log(_url);
  var queryData = url.parse(_url, true).query;
  var pathname = url.parse(_url, true).pathname;

  if (pathname === "/") {
    if (queryData.id === undefined) {
      var title = "Welcome";
      var description = "Hello Node.js";
      var template = `
          <!DOCTYPE html>
          <html lang="en">
            <head>
              <meta charset="UTF-8" />
              <meta http-equiv="X-UA-Compatible" content="IE=edge" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>WEB - ${title}</title>
              <link rel="stylesheet" href="style.css">
              <script src="color.js"></script>
            </head>
            <body>
              <div id="top">
                <h1><a href="/"></a></h1>
                <input type="button" value="night" onclick="nightDayHandler(this)"/>
              </div>
              <div id="grid">
                <ul>
                  <li><a href="/?id=black%20tea">홍차</a></li>
                  <li><a href="/?id=oolang%20tea">우롱차</a></li>
                  <li><a href="/?id=green%20tea">녹차</a></li>
                </ul>
                <div id="article">${description}</div>
              </div>
            </body>
          </html>
        `;
      response.writeHead(200);
      response.end(template);
    } else {
      fs.readFile(`data/${queryData.id}`, "utf-8", function (err, description) {
        var title = queryData.id;
        var template = `
              <!DOCTYPE html>
              <html lang="en">
                <head>
                  <meta charset="UTF-8" />
                  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
                  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                  <title>WEB - ${title}</title>
                  <link rel="stylesheet" href="style.css">
                  <script src="color.js"></script>
                </head>
                <body>
                  <div id="top">
                    <h1><a href="/"></a></h1>
                    <input type="button" value="night" onclick="nightDayHandler(this)"/>
                  </div>
                  <div id="grid">
                    <ul>
                      <li><a href="/?id=black%20tea">홍차</a></li>
                      <li><a href="/?id=oolang%20tea">우롱차</a></li>
                      <li><a href="/?id=green%20tea">녹차</a></li>
                    </ul>
                    <div id="article">${description}</div>
                  </div>
                </body>
              </html>
            `;
        response.writeHead(200);
        response.end(template);
      });
    }
  } else {
    if (_url == "/style.css") {
      response.writeHead(200, { "Content-type": "text/css" });
      var fileContents = fs.readFileSync("style.css", "utf-8");
      response.write(fileContents);
      response.end();
    } else if (_url == "/color.js") {
      response.writeHead(200, { "Content-type": "text/js" });
      var fileContents = fs.readFileSync("color.js", "utf-8");
      response.write(fileContents);
      response.end();
    } else {
      response.writeHead(404);
      response.end("Not found");
    }
  }
});
app.listen(3000);
Code language: HTML, XML (xml)

댓글 남기기