데브코스 웹풀스택 과정/TIL

[8기 9회차] 0908 웹 서비스의 이해 - 프론트, 벡엔드 Node.js서버 구현

thinktank911 2025. 9. 8. 16:59

프로젝트 개요

  • 테니스마켓 : 테니스라켓 쇼핑몰 만들기

실전 쇼핑몰 프로젝트

  • 프론트엔드
    • 메인페이지
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Main</title>
<style>
    h1 {
        text-align: center;
    }

    #txt_welcome {
        text-align: center;
        margin-bottom: 50px;
    }

    .flex-container {
        display: flex;
        justify-content: space-evenly;
    }
    .card {
        text-align: center;
    }

    .card_title {
        font-size: 20px;
    }

    .card_button {
        font-size: 25px;
        width: 150px;
        height: 30px;
    }

    .card_img {
        width: 300px;
        height: 300px;
    }
</style>
</head>
<body>
<h1>Tennis market</h1>
<div id="txt_welcome">
    Welcome to Tennis market! <br>
    Enjoy your shopping.
    <br>
    <br>
    <a href="./orderlist.html">order list</a>
</div>
<div class="flex-container">
    <div class="card">
        <img class="card_img" src="./img/redRacket.png">
        <p class="card_title">Red Racket</p>
        <input class="card_button" type="button" value="order" onclick="alert(1)">
    </div>
    <div class="card">
        <img class="card_img" src="./img/blueRacket.png">
        <p class="card_title">Blue Racket</p>
        <input class="card_button" type="button" value="order" onclick="alert(2)">
    </div>
    <div class="card">
        <img class="card_img" src="./img/blackRacket.png">
        <p class="card_title">Black Racket</p>
        <input class="card_button" type="button" value="order" onclick="alert(3)">
    </div>
</div>
</body>
</html>
  • 주문내역페이지
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Order List</title>
  <style>
      h1 {
          text-align: center;
      }

      table {
          margin-left: auto;
          margin-right: auto;
      }

      div {
          text-align: center;
          margin-bottom: 50px;
      }
  </style>
</head>
<body>
  <h1>Order List</h1>
  <div>
      <a href="./main.html">go home</a>
  </div>
  <table style="border: 1px solid black;">
      <th>No</th>
      <th>Product</th>
      <th>Description</th>
      <th>Price</th>
      <th>Order Date</th>

      <tr>
          <td>1</td>
          <td>product1</td>
          <td>description1</td>
          <td>price1</td>
          <td>date1</td>
      </tr>
      <tr>
          <td>2</td>
          <td>product2</td>
          <td>description2</td>
          <td>price2</td>
          <td>date2</td>
      </tr>
  </table>
</body>
</html>

  • 백엔드
    • 백엔드의 구조

웹서비스 구조

1) 웹서버의 역할
- 정적페이지에 대해 대응
- 동적페이지에 대한 처리는 직접 처리하지 않고, 웹 어플리케이션 서버에게 전달

*정적페이지: 화면의 내용/데이터 등의 변동이 없는 페이지
*동적페이지: 데이터 처리/연산을 통해 화면의 내용, 데이터가 변하는 페이지

2) 웹 어플리케이션 서버와 데이터베이스
- 웹 어플리케이션 서버는 동적 페이지 처리
- 필요한 데이터 연산을 위해 데이터베이스와 연결되어 있으며 데이터 조회/수정/삭제에 대한 처리를 요청함

*데이터베이스란: 데이터를 통합하여 효율적으로 관리하기 위한 데이터 집합체

Node.js의 이해

노드 소개 및 설치

자바스크립트를 자바스크립트 언어 이상으로 프로그래밍 언어 역할을 할 수 있도록 지원하는 플랫폼
노드를 이용해 자바스크립트로 백엔드를 구현할 수 있다.
자바스크립트가 백엔드에서 뛰어놀 수 있도록 하는 플랫폼 역할

node.js로 웹 서버 만들기

  • server.js 페이지로 서버 생성
  • cmd 창에 node server.js 작성하여 서버 구동
// node.js의 모듈 중 http 사용하도록 기능들 불러오는 함수 require
let http = require('http');
// url 가져오기
let url = require('url');
// const { route } = require('./router');

function start(route, handle){
    // 클라이언트와 소통 함수
    // node.js가 알아서 요청과 응답 넣어줌
    function onRequest(request, response){
        // 요청받은 url의 문자열을 해석(파싱)해서 pathname 찾기
        // pathname은 포트넘버 뒤 경로를 말함
        // url.parse는 URL 문자열을 속성별로 분해하는 구버전 메서드
        // 최신 버전에서는 new URL() 방식을 쓰는 게 더 안정적이고 표준적임
        let pathname = url.parse(request.url).pathname;
        // route에게 pathname, handle, response 전달
        route(pathname, handle, response);

        // head 적기 : 상태코드, 요청타입
        response.writeHead(200, {'Content-Type' : 'text/html'});
        // write body. body 적기
        response.write('Hello Node.js');
        // response 종료. 전송바람
        response.end();
    }

    // 서버 생성
    // 클라이언트와 소통한 내용의 함수를 바탕으로 서버 만들기
    // listen(클라이언트 주파수: 포트번호)
    // localhost:8888
    // 미구동 상태. 구동 시 명령어 node server.js
    http.createServer(onRequest).listen(8888);
}

// 페이지 외에서도 start 함수 사용하도록 export
exports.start = start;

http (프로토콜) 템플릿

  • Head
    1) 웹 서버의 통신상태 알려줌 ex> 200, 404
    • 200 : 정상 / 404 : 클라이언트가 원하는 걸 못 찾겠다. / 500 : 서버가 이상
    • http (status) code 라고 부름`2) 응답의 형태 : ex> html
  • Body : 웹 페이지 화면에 뿌려질 내용을 담는다
// head 적기 : 상태코드, 요청타입
response.writeHead(200, {'Content-Type' : 'text/html'});
// write body. body 적기
response.write('Hello Node.js');
// response 종료. 전송바람
response.end();

server.js 모듈화

  • index.js : require('모듈 이름')으로 server를 모듈처럼 사용할 수 있다.
  • node index.js 실행
  • 실행하고 싶을 때만 : start 함수 만들어 export 한다.
// index.js 역할
// 모듈 소환하고 서버 기동  

// 서버 모듈화
let server = require('./server');
// 라우터 모듈화
let router = require('./router');
// requestHandler 모듈 소환
let requestHandler = require('./requestHandler');

// 서버가 원할 때만 실행되도록
// route를 서버에 전달
// handle 함수도 서버에 전달
server.start(router.route, requestHandler.handle);

 

url 읽어내기

URL(Uniform Resource Locator)

  • 인터넷상에서 웹 페이지가 어디있는지 '위치'를 알려주는 주소
  • url.parse는 URL 문자열을 속성별로 분해하는 구버전 메서드
  • 최신 버전에서는 new URL() 방식을 쓰는 게 더 안정적이고 표준적임
// url 가져오기
let url = require('url');  

// 클라이언트와 소통 함수
 // node.js가 알아서 요청과 응답 넣어줌
 function onRequest(request, response){
     // 요청받은 url의 문자열을 해석(파싱)해서 pathname 찾기
     // pathname은 포트넘버 뒤 경로를 말함
     // url.parse는 URL 문자열을 속성별로 분해하는 구버전 메서드
     // 최신 버전에서는 new URL() 방식을 쓰는 게 더 안정적이고 표준적임
     let pathname = url.parse(request.url).pathname;
     // route에게 pathname, handle, response 전달
     route(pathname, handle, response);
 }

 

url 따라 다른 콘솔 적기

  • Server : Request를 받는다.
  • Router : Request의 URL에 따라 루트를 정해줌. 길만 정해줌
  • url에 따라 프론트엔드에 다른 response 보내기

<server.js>

  // 라우터 : 경로 정해주는 기능
  function route(pathname, handle, response){
    // pathname은 8888뒤에 오는 경로
    console.log('pathname : '+pathname);

    // handle 변수를 함수처럼 사용하도록 소괄호 지정. response 파라메터 전달
    // 정의되지 않은 url(/favicon.ico 등) 함수를 자동으로 불러오고 있어서 
    // handle[pathname] 이 존재할 때만 실행하도록 조건문
    // 에러일 경우 에러 페이지 띄우기
    if(typeof handle[pathname] === 'function'){
        handle[pathname](response);
    } else{
        console.log('No request handler found for ' + pathname);
        // head 적기 : 상태코드, 요청타입
        response.writeHead(404, {'Content-Type' : 'text/html'});
        // write body. body 적기
        response.write('Not Found');
        // response 종료. 전송바람
        response.end();
    }   
}  

  exports.route = route;

 

<requestHandler.js>

// requestHandler.js
// router가 루트를 정해주면 각 루트 페이지에서 하는 기능 설정
function main(response){
    console.log('main');

    // head 적기 : 상태코드, 요청타입
    response.writeHead(200, {'Content-Type' : 'text/html'});
    // write body. body 적기
    response.write('Main page');
    // response 종료. 전송바람
    response.end();
}

function login(response){
    console.log('login');

    // head 적기 : 상태코드, 요청타입
    response.writeHead(200, {'Content-Type' : 'text/html'});
    // write body. body 적기
    response.write('Login page');
    // response 종료. 전송바람
    response.end();
}

function myname(response){
        console.log('myname');

        // head 적기 : 상태코드, 요청타입
        response.writeHead(200, {'Content-Type' : 'text/html'});
        // write body. body 적기
        response.write('myname is YJ Kim');
        // response 종료. 전송바람
        response.end();
}

let handle = {}; // key:value 쌍으로 이루어진 변수(사전)
handle['/'] = main;
handle['/login'] = login;
handle['/myname'] = myname;

exports.handle = handle;

<학습 외 정리>

http url 구조

2025.09.08 - [개발지식/http] - HTTP URL 구조 살펴보기 / New URL()과 URLSearchParams()

 

HTTP URL 구조 살펴보기 / New URL()과 URLSearchParams()

URL의 기본구조scheme://username:password@host:port/path?query#fragment1. 스키마(Scheme)프로토콜을 지정주요 스키마http : 일반 웹 통신https : 보안 웹 통신ftp : 파일 전송mailto : 이메일file : 로컬 파일2. 사용자정

thinktank911.tistory.com