웹 서비스의 이해 3-1 ~ 4-8(프론트엔드 실습 및 백엔드)

Develop Kim·2024년 8월 24일

programmers

목록 보기
3/40

웹 서비스의 이해: 웹 생태계부터 웹 브라우저, 데이터베이스

3 프로젝트(쇼핑몰 만들기)

3-1 메인 페이지

  • 쇼핑몰 메인 페이지를 만들기 위해 아래와 같이 코드 작성
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title> main </title>
    <link rel="stylesheet" href="shop.css">
</head>
<body>
<h1>Tennis Market</h1>
    <div> <!-- div는 의미없는 단락을 나타내는 태그, 태그 내에 있는 것들을 묶어줌 -->
        Welcome to Tennis Market!
        Enjoy yur shopping.
        <br>
        <br>
        <a href="./orderlist.html"> order list </a>
    </div>
    <div id="widshow">
        <div class="card">
            <img class="card_img" src="./img/redRacket.png">
            <p class="card_title"> Red Racket </p> <!-- 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>
  • CSS로 꾸며주기
body {
    text-align: center;

}

#widshow {
    display:grid; grid-template-columns: 1fr 1fr 1fr;
    /* display는 보여지는 위치, grid는 간격 */
}

.card {
    font-size: 25px;
    color:chocolate;
}

.card_img {
    width: 300px;
    height: 300px;
}

.card_title {
    color:rgb(14, 147, 114);
}

.card_button {
    background-color: white;
    border-radius: 5px;
    border-color: gray;
    font-size: 30px;
    width: 120px;
    height: 40px;
    color:rgb(30, 176, 30);
}

3-2 주문내역 페이지

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title> Order List </title>
  <style>
    h1 {
      text-align: center;
    }

    table {
      /* text-align: center; 테이블은 텍스트 얼라인이 안먹음*/
      margin-left: auto; /* 마진(간격) 왼쪽 오른쪽을 해줘야 가운데 정렬이 됨*/
      margin-right: auto;
    }
    
    /* a { text-align: center;}
    a태그도 텍스트 얼라인이 안 먹으므로 div로 묶어서 적용해야 함*/
    div {
      text-align: center;
      margin-bottom: 50px; /* h1과 너무 붙어있어 간격 띄워줌 */
    }

  </style>
</head>
<body>
  <h1> Order List </h1>
  <div>
  <a href="main.html"> Go Home </a> <!-- 홈으로 돌아가는 링크 -->
  </div>
  <table style="border: 1px solid Black"> <!-- 테이블은 표형태를 만들 때 쓰임 -->
    <!-- border: 테두리, px: 두께, solid: 실선 -->
    <th> No </th> <!-- 테이블 컬럼이름 생성(열 제목), th는 테이블 헤드 -->
    <th> Product </th>
    <th> Description </th>
    <th> Price </th>
    <th> Order Date </th>

    <tr> <!-- 테이블 로우, 첫번째 행 -->
      <td>1</td>
      <td>prduct1</td>
      <td>description1</td>
      <td>price1</td>
      <td>date1</td>
    </tr>

    <tr> <!-- 테이블 로우, 두번째 행 -->
      <td>2</td>
      <td>prduct2</td>
      <td>description2</td>
      <td>price2</td>
      <td>date2</td>
    </tr>

  </table>
</body>
</html>

4 백엔드

4-1 백엔드의 구조

0️⃣ 백엔드(웹 서버) 는 웹서버, 웹 어플리케이션 서버와 데이터베이스를 포함

  • 정적 페이지란? 사용자와 상호작용이 이루어지는 페이지가 아님(만약 한 포탈사이트에서 사과를 검색했을 때 누가 로그인을 하던 사과는 검색이 됨: 정적페이지가 아님, 정적페이지는 데이터베이스와도 소통을 하지 않음)

  • 동적 페이지는 반대로 데이터의 연산, 처리가 필요함(로그인, 사용자 정보 긁어오는 처리가 이루어지는 페이지)

  • 동적 페이지일 경우 웹 어플리케이션 서버에서 받아 데이터 연산을 함

  • 웹 어플리케이션은 데이터베이스에서 데이터 조회/수정/삭제 처리를 요청하고 동적페이지를 표현함

  • 백엔드는 웹 어플리케이션을 중점으로 확인해나가야 함

4-2 Node.js의 이해

0️⃣ Node.js란? 자바스크립트가 백엔드 프로그래밍을 할 수 있게 해주는 플랫폼

  • 자바 스크립트는 스크립트 언어로만 역할을 해왔지만 백엔드 프로그래밍도 가능해짐,
    본래는 프론트엔드에서 화면만 구현이 가능했고 Java, Phython 등 별도의 백엔드 언어를 사용해야 했음

  • Node.js는 백엔드 중 웹 서버의 역할을 하고 웹 어플리케이션 서버의 역할을 만들어줄 수 있음
    자바스크립트의 함수로 웹 서버와 웹 어플리케이션 서버를 만들 수 있음
    또한 Node.js에서 데이터베이스와도 소통(요청/응답)이 가능함

  • 설치 방법: https://nodejs.org/en/download/package-manager/current

4-3 Node.js로 웹서버 만들기

  • 이전에 만들었던 로그인 웹 페이지를 활용하여 웹서버 만들기
let http = require('http'); 
// 'http'(node.js에서 프로토콜 활용을 제공하는 모듈, 클라이언트와 서버가 통신을 하는데 사용하는 약속, 프로토콜)을 require함수를 통해불러옴

function onRequest(request, response) { // onRequest는 클라이언트에게 요청이 오면~ 이라는 의미로 작명, node.js에서 request(요청), response(응답)
  response.writeHead(200, {'Content-Type' : 'text/html'}); // 웹서버가 클라이언트에게 응답을 해줄 때 헤드를 200코드(정상)로 적을 것이고 클라이언트에게 응답하는 타입은 html임 
  response.write('Hello Node.js'); // 바디에 해당하는 구간, 적은대로 화면에 표기됨
  response.end(); // 응답에 담을 거 끝 응답 go 
}

http.createServer(onRequest).listen(8888); 
// node.js의 http모듈은 서버를 만들어주는 createserver 함수를 가지고 있음
// http 모듈을 이용하여 서버를 만들고 이 안에서 onRequest 함수로 통신을 할거고 클라이언트와 소통시 포트번호(주피수)는 8888


// localhost:8888 로 웹에서 호출 가능
// 터미널에서 'node 파일명.js'로 서버를 연동해주고 호출해야 함
// control + c 는 연동을 끊어줌

4-4 HTTP 템플릿

  • 웹의 이해 중에서 프로토콜이 서로 편지주고 받을 때 주는 사람, 받는 사람의 틀이 정해진 것 처럼 인터넷, 웹, 웹, 클라이언트와 서버 등도 통신을 할 때도 약속이 존재함 그 약속을 HTTP라 함

  • 바디에 웹에 뿌려질 내용을 담는다면 헤드에는 웹 서버의 통신상태를 안내해줌 이때 200, 404, 500 error를 HTTP (status) code라 부름

4-5 server.js의 모듈화

0️⃣ 우리가 만든 서버를 모듈처럼 사용이 가능함

  • server.js를 직접 구동하게 되면 서버의 유연성(코드 상에서 활용할 수 있는 방법이 적어짐)이 떨어짐,
  • 앞에서 node.js가 미리 만들어준 모듈과 함수를 사용한 것처럼 우리도 다른 코드에서도 서버를 모듈처럼 불러서 사용하면 좋음, 이를 '모듈화'라고 함
let server = require('./server'); 
// server 변수를 지정하여 모듈처럼 활용, ./는 같은 경로(폴더) 내 파일, 
// 터미널에서 node index.js로 서버 모듈화가 되었는지 확인이 가능
  • 서버를 모듈로 불러왔을 때 자동으로 서버가 켜지는 현상이 발생함 고도화하여 서버실행을 수동으로 바꾸는 것이 효율에 좋음, Start 함수가 있으면 좋음

  • 그래서 start함수를 만들고 index.js에서 실행했더니 에러가 발생함

  • 자바스크립트의 함수는 기본적으로 자기 자신 안에서만 작동이 가능함, 이 함수를 외부로 빼는 기능(exports)을 사용해야 함

let http = require('http'); 

function start() {
  function onRequest(request, response) { 
    response.writeHead(200, {'Content-Type' : 'text/html'});
    response.write('Hello Node.js'); 
    response.end(); 
  }
  
  http.createServer(onRequest).listen(8888); 
}

exports.start = start;

4-6 Url 읽어내기

0️⃣ Url이란? Uniform Resource Locator, 웹 페이지의 위치를 알려주는 주소

let http = require('http'); 
let url = require('url'); 
// 이번에는 http 모듈이 아닌 url 모듈 사용


function start(route) { // 서버도 인덱스가 불러주는 친구임, 서버에서 루트를 사용할 수 있도록 서버도 루트를 밖에서 받아오면 됨
  function onRequest(request, response) { 
    let pathname = url.parse(request.url).pathname;
    /* url 모듈은 parse(문자열을 캐치하는 함수) 함수를 가지고 있고 요청받은 url을 가져오고 읽어서 경로가 어떻게 되는지 확인 */

    route(pathname); // 서버가 캐치를 해둔 패스네임을 루트에게 전달함, pathname은 로컬호스트 뒤에 오는 경로를 말함 8888
    // 그렇다면 여기서 루트는 누가알려주나? 스타트 함수에 넣어버리면 되거나 서버에서 라우터 모듈을 부르면 됨, indexd.js에서 라우터를 모듈로 불러오면

    // console.log('pathname : ' + pathname); 콘솔에 pathname 로그를 찍겠음

    response.writeHead(200, {'Content-Type' : 'text/html'}); 
    response.write('Hello Node.js'); 
    response.end(); 
  }
  
  http.createServer(onRequest).listen(8888); 
}

exports.start = start;
  • 서버는 호출/응답하는 것만 해도 바쁘므로 pathname 은 router.js(경로를 정해줌)에게 전달하는 것이 좋음
    router에서 콘솔로그를 확인할 수 있도록 함수 입력
function route(pathname) { //루트는 서버에서 패스네임을 받아 콘솔을 찍어줌
  console.log('pathname : ' + pathname);
  // 콘솔에 pathname 로그를 찍겠음, 콘솔을 라우터 함수에 넣음

}

exports.route = route;
  • server.js 와 router.js를 index.js에 잘 불러올 수 있도록 연결
let server = require('./server'); // server 변수를 지정하여 모듈처럼 활용, ./는 같은 경로(폴더) 내 파일
let router = require('./router'); // router 모듈화하려 연결

server.start(router.route);

4-7 Url에 따라 다른 콘솔 찍기(아직 백엔드만 구별)

1️⃣ Server와 router의 역할

  • server : Request를 받음
  • Router : Request의 Url에 따라 루트를 정해줌 = 어디로 갈지 길만 정해줌
    그렇다면 각 루트(route)에서 할 일은 누가하나? 👉 requestHandler.js


    👉 index에서 server를 구동시키고, server는 경로분배를 router에게 시킴

2️⃣ 적용 해보기

  • server.js
let http = require('http'); 
let url = require('url'); 
// 이번에는 http 모듈이 아닌 url 모듈 사용


function start(route, handle) { // 루트 뿐 아니라 핸들도 받도록 추가
  /* 1. route, handle를 받아서 */
    function onRequest(request, response) { 
    let pathname = url.parse(request.url).pathname; 
    route(pathname, handle); // 루트에게 핸들 값을 넘겨주도록 포함
    /*2. 8888 뒤에오는 주소값을 루트함수에 보내주면서, index.js에서 소환해뒀던 handle도 같이 전달함 */

    response.writeHead(200, {'Content-Type' : 'text/html'}); 
    response.write('Hello Node.js'); 
    response.end(); 
  }
  
  http.createServer(onRequest).listen(8888); 
}

exports.start = start;
  • router.js
function route(pathname, handle) { /* 3. route는 pathname과 handle을 받아서 */
    console.log('pathname : ' + pathname);

    handle[pathname] (); /* 4. handle에 pathname을 전달함 */

    /* requestHandler.js에서 handle을 변수처럼 만들어 두었지만, 
    밖으로 수출(exports) 되면서 핸들값을 호출할 수 있게 함수처럼 사용함
    그래서 ()소괄호를 붙임 */

}

exports.route = route;

// router는 route를 분배하는 역할을 전담함
  • requestHandler.js
function main() { // '/' 이라는 경로를 찾아오면 함수 작동
  console.log('main');
}

function login() { // '/login' 이라는 경로를 찾아오면 함수 작동
  console.log('login');
}

let handle = {}; // {}중괄호는 key:value 상으로 이루어진 변수 상자임, 사전같은 상자, 예)
handle['/'] = main; // '/'를 찾아오면 main을 만나게 된다는 뜻, []안에 있는 것이 key, 
handle['/login'] = login; // '/login'은 login이야

/* 5. handle은 pathname을 받아서 '/login'을 받아서 login을 호출함 */

// 여기서 handle을 변수처럼 만들어 두었지만, 밖으로 수출(exports) 되면서 핸들값을 호출할 수 있게 함수처럼 사용함

exports.handle = handle;

// 리퀘스트 핸들러는 라우터가 루트를 분배해서 각 경로를 알려주면, 이제 뭐할지 알려주는 역할(요청을 처리함)
  • index.js
let server = require('./server'); // server 변수를 지정하여 모듈처럼 활용, ./는 같은 경로(폴더) 내 파일
let router = require('./router');
let requestHandler = require('./requestHandler')

server.start(router.route, requestHandler.handle);
// 서버 시작 시 requestHandler의 변수 handle도 포함

// 직접 만든 모듈을 소환하는 역할을 함

4-8 Url에 따라 프론트엔드에 다른 response 보내기

1️⃣ requestHandler를 이용하여 response 찍어보기

  • /, /login 을 찍어도 Hello Node.js만 화면에 표출해서 새로운 response를 찍어봄
    requestHandler에서 콘솔로그를 찍어주고 있었으니 고도화하면 됨

  • server.js

let http = require('http'); 
let url = require('url'); 

function start(route, handle) { 
    function onRequest(request, response) { 
      let pathname = url.parse(request.url).pathname; 
      route(pathname, handle, response); // 1. 리스폰 받은 것을 루트에 전달

      
      response.writeHead(200, {'Content-Type' : 'text/html'}); 
      response.write('Hello Node.js'); 
      response.end(); 
  }
  
  http.createServer(onRequest).listen(8888); 
}

exports.start = start;
  • router.js
function route(pathname, handle, response) { // 2. server에서 response를 받고
    console.log('pathname : ' + pathname);

    handle[pathname] (response); // 3. 받은 response를 다시 handle에 전달해줌
    // 7. 때문에 router에서 소괄호로 response를 호출한 것은 함수를 호출하는 것과 같음

}

exports.route = route;

// router는 route를 분배하는 역할을 전담함
  • requestHandler.js
function main(response) { // 5. response는 main 함수가 받음
  console.log('main');

  response.writeHead(200, {'Content-Type' : 'text/html'}); 
  response.write('main page'); 
  response.end(); 
}

function login(response) {  // 5. response는 login 함수가 받음
  console.log('login');

  response.writeHead(200, {'Content-Type' : 'text/html'}); 
  response.write('Login page'); 
  response.end(); 
}

let handle = {}; // 6. 그래서 handl이 변수지만 함수같은 특성을 지님
handle['/'] = main;
// 4. /가 호출이 되면서 무언가를 전달받는 것이 main이 호출되면서 전달받는 것과 같기에
handle['/login'] = login;

exports.handle = handle;

// 리퀘스트 핸들러는 라우터가 루트를 분배해서 각 경로를 알려주면, 이제 뭐할지 알려주는 역할(요청을 처리함)
  • index.js
let server = require('./server'); // server 변수를 지정하여 모듈처럼 활용, ./는 같은 경로(폴더) 내 파일
let router = require('./router');
let requestHandler = require('./requestHandler')

server.start(router.route, requestHandler.handle);
// 서버 시작 시 requestHandler의 변수 handle도 포함



// 직접 만든 모듈을 소환하는 역할을 함

2️⃣ 없는 Url의 Erorr 방지

  • 없는 Url을 접속했을 때 에러페이지가 뜨는 것을 router(경로를 정해주는 역할)에서 처리할 수 있음
function route(pathname, handle, response) { 
      console.log('pathname : ' + pathname);

    // 에러의 원인이 handle[pathname]이 function이 아니기 때문
    if (typeof handle[pathname] == 'function') { // 만약 handle pathname의 타입이 function이라면 response를 하고
      handle[pathname](response);
    } else { // function이 아니면 '찾는 페이지가 없네요ㅠㅠ' 라고 써줘
      response.writeHead(404, {'Content-Type' : 'text/html'}); 
      response.write('NOT FOUND'); 
      response.end(); 
    }

}

exports.route = route;

// router는 route를 분배하는 역할을 전담함
profile
김개발의 개발여정

0개의 댓글