Post

데브코스 TIL - Day 8

23년 11월 23일 강의를 들은 내용과 추가로 더 학습한 내용을 기록한 글입니다.

node.js

Node.js는 Chrome V8 JavaScript 엔진으로 빌드된 JavaScript 런타임입니다.

https://nodejs.org/en

※ 런타임: 프로그램들을 실행할 수 있는 환경

자바스크립트를 스크립트 언어 이상으로 프로그래밍 언어 역할을 할 수 있도록 지원하는 플랫폼

  • 개수는 많지만 크기는 작은 데이터를 실시간으로 주고 받는 데 적합
  • Node.js는 모두 스레드 하나에서 처리되기때문에 CPU 연산을 많이 요구(대용량 데이터 처리, 이미지나 비디오 처리)같이 CPU를 많이 사용하는 작업에는 적합하지 않음
  • require()함수를 사용하여 원하는 모듈을 가져와서 사용할 수 있음
    • node.js에서 제공하는 모듈과 내가 만든 모듈 모두 사용 가능
    • 내가 작성한 모듈을 사용하고 싶다면 require('파일 경로')를 사용하기

HTTP 구조

http구조

■ header: HTTP Request에 대한 정보를 가지고 있음

  • General Header (공통)

    • Date
      • 현재 시간
    • Content-type:
      • 응답이 어떤 형태인지 작성
      • "Content-Type": "text/html"
  • Request Header

    • Host:
      • 요청하려는 서버 호스트와 포트번호
      • eg. localhost, 5500
    • Authorization
      • 인증 토큰을 서버로 보낼 때 사용
    • Origin
      • POST 요청을 보낼 때 어느 주소에서 보내는지 나타내는 값
      • 요청 보내는 주소와 요청 받는 주소가 다르면 CORS 오류가 발생…
    • Cookie
      • 쿠키 key:value로 표현
  • Response Header

    • Status Code (통신 상태)
      • 200: 정상
      • 404: 클라이언트가 원하는 것을 찾지 못함(서버 정상)
      • 500: 서버 오류
1
2
3
4
5
6
7
function onRequest(request, response) {
  response.writeHead(200, {
    "Content-Type": "text/html"
  });
  response.write("Hello Node.js");
  response.end;
}

■ body

  • 웹 페이지 화면에 뿌려질 내용

URL (Uniform Resource Locator)

인터넷 상에서 웹 페이지가 어디있는지 위치를 알려주는 주소 웹페이지 주소

Node.js 연습 _ 서버 만들어보기

서버 만들기

  • node에서 제공하는 http 모듈을 이용해서 http 서버를 만들기
  • 코드를 작성했다면 터미널에 node 경로/파일을 입력해서 서버를 오픈하기
    • 만약 root 폴더에 server.js파일이 있다면 node server.js
    • 만약 root 폴더-js 폴더에 server.js파일이 있다면 node js/server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// server.js
let http = require("http");

function onRequest(request, response) {
  // 응답이 200이면 html의 파일을 응답한다.
  response.writeHead(200, {
    "Content-Type": "text/html"
  });

  // 응답헤더에 Main Page! 라고 작성한다.
  response.write("Main Page!");

  // 응답 종료
  response.end();

// createServer: server 객체 생성
// listen: 서버 실행(PORT 번호)
http.createServer(onRequest).listen(8888);

터미널에 node server.js를 입력하고, http://localhost:8888/로 들어가면 Main Page!라고 잘 출력된 것을 볼 수 있음

mainpage

■ 하단의 코드처럼 작성하기도 함!! 상단 코드와 동일하게 수행

1
2
3
4
5
6
7
8
9
let http = require("http");

const server = http.createServer((req, res) => {
  res.status = 200;
  res.setHeader("Content-Type", "text/html");
  res.end("Main Page");
});

server.listen(8888);

서버 객체 알아보기

■ server 객체 메서드 구분 | 설명

  • listen(port[, callback])서버 실행
    close()서버 닫기

■ server 객체 이벤트

구분설명
request클라이언트가 요청할 때 발생하는 이벤트
response클라이언트가 응답받을 때 발생하는 이벤트
connection클라이언트가 접속할 때 발생하는 이벤트
checkContinue클라이언트가 계속 연결을 하고 있을 때 발생하는 이벤트
upgrade클라이언트가 HTTP 업그레이드를 요청할 때 발생하는 이벤트
clientError클라이언트에서 오류가 발생할 때 발생하는 이벤트
close서버가 종료될 때 발생하는 이벤트

■ response 객체 알아보기

구분설명
setHeader()응답 헤더 작성
writeHead(statusCode, object)응답 헤더 작성
향후 검색 및 수정 가능성이 있는 경우 사용
한번만 호출되어야 함
write()응답 본문 작성
여러번 호출 가능
end응답 종료 시점 명시
응답 본문 작성
string(문자열) 또는 html 코드 작성 가능 (객체인 경우에는 JSON.stringify()를 사용해 string 형식으로 변환하여 보내줘야 함)

server.js 파일 모듈화하고, 다른 파일에서 사용하기

exports를 사용하면 해당 함수를 외부에서 사용할 수 있도록 모듈로 만들 수 있다.

  • exports.start = start 코드를 작성해서 외부에서 사용할 수 있도록 모듈화하기
  • 사용할 파일에서 require()를 사용해 모듈 가져오기
1
2
3
4
5
6
7
8
9
10
11
// server.js
let http = require("http");

function start() {
  function onRequest(request, response) {
    let { pathname } = new URL(request.url);
  }
  http.createServer(onRequest).listen(8888);
}

exports.start = start;
1
2
3
4
5
// index.js
// start 모듈을 사용할 파일
let server = require("./server");

server.start();

URL(pathname) 정보 받아오기

node.js에서 제공해주는 new URL메소드를 사용하면 쉽게 가져올 수 있음

  • 응답을 요청하는 함수에서 new URL(request.url)을 작성하면 요청하는 url의 pathname 정보를 가져올 수 있음
1
2
3
4
5
6
7
8
9
10
11
12
// server.js
let http = require("http");

function start(route) {
  function onRequest(request, response) {
    const pathname = new URL(request.url);
    console.log(pathname); // /
  }
  http.createServer(onRequest).listen(8888);
}

exports.start = start;

Router 파일 생성하고, pathname별로 다른 내용 출력하기

※ 경로에 따라 페이지 내용을 다르게 출력하기 위한 파일

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// requestHandler.js
function main(response) {
  response.writeHead(200, {
    "Content-Type": "text/html"
  });
  response.write("Main Page!");
  response.end();
}
function orderList(response) {
  response.writeHead(200, {
    "Content-Type": "text/html"
  });
  response.write("Order List Page!");
  response.end();
}

// 해당 경로로 진입했을 때 함수 실행
let handle = {};
handle["/"] = main;
handle["/orderList"] = orderList;

exports.handle = handle;

※ pathname 확인 후 해당 경로에 맞는 함수 실행하는 파일

예시

http://localhost:8888/orderList에 진입시
→ requestHandler.js 파일에 작성된
→ handle[“/orderList”] = orderList 코드에 의해
→ orderList 함수가 실행됨

1
2
3
4
5
6
// router.js

function route(pathname, handle, response) {
  handle[pathname](response);
}
exports.route = route;

※ 요청한 URL의 pathname을 route에 전달하는 파일

1
2
3
4
5
6
7
8
9
10
11
12
// server.js
let http = require("http");

function start(route, handle) {
  function onRequest(request, response) {
    let pathname = new URL(request.url);
    route(pathname, handle, response);
  }
  http.createServer(onRequest).listen(8888);
}

exports.start = start;

※ 모듈 가져오는 파일

1
2
3
4
5
6
7
// index.js

let server = require("./server");
let route = require("./router");
let requestsHandler = require("./requestHandler");

server.start(route.route, requestsHandler.handle);

설정하지 않은 경로에 진입했을 때 서버가 종료되는 오류 수정하기

만약 우리가 설정해둔 '/' 경로나 '/orderList'가 아닌 다른 경로로 진입하게 된다면 일치하는 경로를 찾지 못해 서버가 종료되는 오류가 발생한다.

이를 방지하기 위해 예외의 경우를 처리해줘야함

지금 경우에는 handle[pathname]() is not function과 같은 오류가 발생

handle[pathname]가 함수가 아닐때 예외 처리를 해주면 됨!

  • 함수가 아니기때문에 나타나는 오류이기때문에
1
2
3
4
5
6
7
8
9
10
11
12
13
// router.js
function route(pathname, handle, response) {
  if (typeof handle[pathname] == "function") {
    handle[pathname](response);
  } else {
    response.writeHead(404, {
      "Content-Type": "text/html"
    });
    response.write("Page Not found!");
    response.end();
  }
}
exports.route = route;

테니스 라켓 쇼핑몰 페이지 생성 (프론트엔드)

파일 구조

1
2
3
┌ index.html
├ orderList.html
└ style.html

메인 페이지

테니스마켓

index.html

  • 홈페이지 타이틀
  • 주문내역으로 이동하는 버튼
  • 상품 리스트
코드 접기/펼치기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>테니스 마켓</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <header>
      <h1 class="logo">테니스 마켓</h1>
      <a class="link_btn btn" href="./orderlist.html">주문내역</a>
    </header>

    <div id="main">
      <div class="visual">
        <p id="txt_welcome">테니스 마켓에 오신걸 환영합니다!</p>
      </div>
      <section class="content_container">
        <h4 class="container_title">베스트 상품</h4>
        <ul class="card_list">
          <li class="card">
            <img
              class="card_img"
              src="https://cdn.pixabay.com/photo/2023/04/17/10/31/tennis-7932067_1280.jpg"
              alt="빨간 라켓"
            />
            <p class="card_title">그린델 테니스 라켓</p>
            <input
              class="card_btn btn"
              type="button"
              value="주문하기"
              onclick="alert(1)"
            />
          </li>
          <li class="card">
            <img
              class="card_img"
              src="https://images.unsplash.com/photo-1617883861744-13b534e3b928?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
              alt="빨간 라켓"
            />
            <p class="card_title">네오 테니스 라켓</p>
            <input
              class="card_btn btn"
              type="button"
              value="주문하기"
              onclick="alert(1)"
            />
          </li>
          <li class="card">
            <img
              class="card_img"
              src="https://cdn.pixabay.com/photo/2022/04/17/11/41/tennis-7137976_1280.jpg"
              alt="빨간 라켓"
            />
            <p class="card_title">블루몬 테니스 라켓</p>
            <input
              class="card_btn btn"
              type="button"
              value="주문하기"
              onclick="alert(1)"
            />
          </li>
        </ul>
      </section>
    </div>
  </body>
</html>

주문 내역 페이지

주문내역페이지

orderList.html

  • 홈으로 이동하는 버튼
  • 페이지 타이틀
  • 주문 내역(리스트_table 태그 사용)
코드 접기/펼치기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
```html
<!DOCTYPE html>
<html lang="ko">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>주문 내역</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    <header>
      <h1 class="logo">테니스 마켓</h1>
    </header>
    <div class="content_container">
      <a href="./index.html" class="link_btn btn"> < 홈으로 돌아가기</a>
      <h2>주문내역</h2>
      <section class="order_list">
        <table>
          <thead>
            <th>No</th>
            <th>상품명</th>
            <th>설명</th>
            <th>가격</th>
            <th>주문일</th>
          </thead>
          <tbody>
            <tr>
              <td>1</td>
              <td>네오 테니스 라켓</td>
              <td>테니스 라켓에 대한 설명</td>
              <td>30,000원</td>
              <td>2023-11-23</td>
            </tr>
          </tbody>
        </table>
      </section>
    </div>
  </body>
</html>
```
This post is licensed under CC BY 4.0 by the author.