고양이와 코딩
[웹 풀사이클 데브코스 TIL] 2주차 Day 4 - 웹 생태계 전반에 대한 실습(1) 본문
1. 프로젝트 개요
테니스 라켓을 구매하는 쇼핑몰을 만들어 봅시다
페이지 구성
- mainPage - 상품을 구매할 수 있는 페이지
- orderPage - 상품 구매 후 안내해주는 페이지
- order list Page - 구매한 상품의 정보를 확인할 수 있는 페이지
2. 메인 페이지
main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Main</title>
</head>
<body>
<h1>Tennis market</h1>
<div>
Welcome to Tennis market!<br />
Enjoy your shopping.
<br />
<br />
<a>order list</a>
</div>
<img src="./img/redRacket.png" />
<p>Red Racket</p>
<input type="button" value="order" onclick="alert(1);" />
</body>
</html>
지난 시간에 배웠던 태그들이 다 들어있습니다!
3개의 테니스 이미지를 넣을건데요
<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로 한번에 묶어서 복사 붙여넣기 해줬어요
+ 클래스 이름도 지정해 줬습니다 (css를 위해 ㅎㅎ)
3. 주문 내역 페이지
이번에는 orderList 파일을 생성 해 봅니다!
여기서 table 태그를 사용할건데요,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Order List</title>
</head>
<body>
<h1>Order List</h1>
<a href="main.html">go home</a>
<table>
<th>No</th>
<th>Product</th>
<th>Description</th>
<th>Price</th>
<th>Order Date</th>
</table>
</body>
</html>
그렇다면 tr을 사용하면 어떻게 나올까요 ?
<tr>
<td>1</td>
<td>produce1</td>
<td>description1</td>
<td>price1</td>
<td>date1</td>
</tr>
<tr>
<td>1</td>
<td>produce1</td>
<td>description1</td>
<td>price1</td>
<td>date1</td>
</tr>
현재까지 css까지 간략하게 맥인 화면은 이렇습니다 !
4. 백엔드의 구조
* 정적 페이지 : 화면의 내용/데이터 등의 변동이 없는 페이지
* 동적 페이지: 데이터 처리/연산을 통해 화면의 내용, 데이터가 변하는 페이지
* 데이터베이스 : 데이터를 통합하여 효율적으로 관리하기 위한 데이터 집합체
웹 서버는 정적 페이지에 대해 대응해요. 동적 페이지에 대한 처리는 직접 하지 않고 웹 어플리케이션 서버에게 전달합니다 !
웹 어플리케이션 서버는 동적 페이지를 처리합니다.필요한 연산을 위해 데이터베이스와 연결되어 있고 데이터 조회/수정/삭제에 대한 처리를 요청해요
5. Node.js 소개 및 설치
Node.js 란?
- 자바스크립트를 스크립트 언어 이상으로 프로그래밍 언어 역할을 할 수 있도록 지원하는 플랫폼
(자바스크립트가 백엔드 세상에서 뛰어놀수 있는 운동장을 제공하는 친구라고 하시네요 ( •͈ᴗ•͈)◞)
노드는 안정적인 LTS버전으로 받아 주도록 하겠습니다 !
6. Node.js로 웹서버 만들기
저번에 만들었던 WebStart 폴더에서 server.js를 생성해 줬어요
let http = require("http");
http.createServer()
createServer() 함수가 서버를 생성해줘요,
let http = require("http");
function onRequest(request, response) {
response.writeHead(200, { "Content-Type": "text/html" });
response.write("Hello Node.js");
response.end();
}
http.createServer(onRequest).listen(8888);
createServer()는 Node.js의 http 모듈에 있는 함수 중 하나로, 웹 서버를 생성하는데 사용돼요 !
함수의 인자인 function(request, response)는 콜백 함수로, 요청과 응답을 다루는 로직을 담고 있습니다
이제 vscode 터미널에서 명령어를 입력해서 서버를 구동시켜볼게요
node server.js
7. HTTP 템플릿
클라이언트와 서버가 통신을 하고 싶다면, 주파수를 맞춰야 합니다 !
HTTP 프로토콜 템플릿
8. server.js 모듈화
사용을 좀 더 용이하게 하기위해 모듈화를 해볼게요
index.js 파일을 만들어서
let server = require("./server");
입력해 준 뒤
node index.js
명령어로 서버를 구동시킨 뒤 새로고침 해 보면, 직접적으로 node server.js를 입력하지 않아도 잘 나오는걸 볼 수 있어요
내가 만든 서버를 모듈처럼!
Node.js가 미리 만들어 둔 모듈을 우리가 require('모듈 이름'); 으로 사용한 것 처럼,
우리가 만든 서버도 모듈처럼 다른 javascript파일에서 사용할 수 있습니다 ㅎㅎ
server.js <- index.js
그렇다면 서버를 불러와서 실행 시키고 싶을 때 실행하려면 어떻게 해야할까요 ?
function onRequest(request, response) {
response.writeHead(200, { "Content-Type": "text/html" });
response.write("Hello Node.js");
response.end();
}
http.createServer(onRequest).listen(8888);
서버를 실행시키는 이 부분을 함수로 안에 넣고 서버를 실행시키면 오류가 발생합니다 ❗️
함수를 밖으로 내보내서 사용하고 싶다면 export 시켜주어야 해요
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;
server.js
let server = require("./server");
server.start();
index.js
이제 node.index.js로 다시 서버를 실행시켜 보면
9. Url 읽어내기
URL(Uniform Resource Locator) : 인터넷 상에서 웹 페이지가 어디에 있는지 '위치'를 알려주는 주소 === 웹 페이지 주소
let pathname = url.parse(request.url).pathname;
console.log("pathname: " + pathname);
코드를 이렇게 추가하고 서버를 새로고침하면 터미널에
이렇게 현재 url이 찍히는데요, /favicon.ico는 무시하는 코드를 짜면 된다고 하지만 일단은 그냥 진행 해 보도록 할게요 ㅎㅎ
route.js 파일을 만들고
function route(pathname) {
console.log("pathname: " + pathname);
}
exports.route = route;
server.js에서
let http = require("http");
let url = require("url");
function start(route) {
function onRequest(request, response) {
let pathname = url.parse(request.url).pathname;
route(pathname);
response.writeHead(200, { "Content-Type": "text/html" });
response.write("Hello Node.js");
response.end();
}
http.createServer(onRequest).listen(8888);
}
exports.start = start;
route에게 pathname을 전달 해 줍니다. (start 함수 내에 인자로 route를 받는것도요 !!)
그치만 서버에서 route를 어떻게 알 수 있을까요 .. 🧐
server.js에서 start() 함수를 호출해주는 index.js파일에서 작업 할 수 있습니다 !
let server = require("./server");
let router = require("./router");
server.start(router.route);
index.js 파일
그리고 다시 서버를 실행 시켜 보아요
** 하나의 파일에서도 서버가 구동되는데 왜 이렇게 따로따로 작업하는거지? 하는 의문이 들었지만,
역할을 분리시킨 것 뿐이라고 하시니까 바로 이해가 됐습니다...파일에서 함수를 따라따라 가보니 쉽게 알 수 있는 것 같아요 ㅎㅎ
10. URL에 따라 다른 콘솔 찍기 (백엔드만)
저번 시간까지는 Route에서 할 일은 정해주지 않았어요 !
이번 시간에 배워보려고 합니다 ~
requestHandler.js 파일을 만들어서
function main() {
console.log("main");
}
function login() {
console.log("login");
}
let handle = {}; // key:value 쌍으로 이루어진 변수 상자
handle["/"] = main;
handle["/login"] = login;
exports.handle = handle;
이렇게 코드를 작성해줍니다
그리고 저번에도 그랬듯 index.js 파일에서 불러와 보도록 할게요
let server = require("./server");
let router = require("./router");
let requestHandler = require("./requestHandler");
server.start(router.route, requestHandler.handle);
== start라는 함수가 handle 값도 받을 수 있어야 한다!
그러면 start 함수가 있는 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.writeHead(200, { "Content-Type": "text/html" });
response.write("Hello Node.js");
response.end();
}
http.createServer(onRequest).listen(8888);
}
exports.start = start;
start 함수의 인자로 handle을 추가해 주고 route에 pathname과 더불어 handle도 넘겨줘요.
그러면 route를 제공하는 router에도 이 사실을 알려줘야합니다 !!
function route(pathname, handle) {
console.log("pathname: " + pathname);
handle[pathname]();
}
exports.route = route;
router.js 파일에도 handle을 전달해줍시다
❗️TypeError: handle[pathname] is not a function
at route (/Users/jin/Desktop/WebStart/router.js:4:19)
at Server.onRequest (/Users/jin/Desktop/WebStart/server.js:7:5)
at Server.emit (node:events:512:28)
at parserOnIncoming (node:_http_server:1067:12)
at HTTPParser.parserOnHeadersComplete (node:_http_common:119:17)
요런 오류가 발생하네요,,
슬랙에서 답변해 주신걸 보고 수정했습니다 (감사합니다 👾)
function route(pathname, handle) {
console.log("pathname: " + pathname);
if (typeof handle[pathname] === "function") {
handle[pathname]();
} else {
console.log("No request handler found for " + pathname);
}
}
exports.route = route;
이렇게 수정했어요!
requestHandler.js 파일에서 설정 해 준 것처럼 /일때는 main이 출력되고 /login 일때는 login이 출력되는걸 볼 수 있어요
11. URL에 따라 프론트엔드에 다른 response 보내기
현재는 계속 서버를 구동하면 url이 바뀌어도 Hello Node.js만 뜨고 있어요
function start(route, handle) {
function onRequest(request, response) {
let pathname = url.parse(request.url).pathname;
route(pathname, handle, response);
server.js
function route(pathname, handle, response) {
console.log("pathname: " + pathname);
if (typeof handle[pathname] === "function") {
handle[pathname](response);
} else {
console.log("No request handler found for " + pathname);
}
router.js
function main(response) {
console.log("main");
}
function login(response) {
console.log("login");
}
requestHandler.js
이렇게 각 파일들의 인자에 response를 추가 해 주고 server.js 파일 내의
response.writeHead(200, { "Content-Type": "text/html" });
response.write("Hello Node.js");
response.end();
를 잘라와서, response를 이제 route 주고,,, route는 handler 주었기 때문에 결과적으로 requestHandler.js파일에서 불러와 줘야 해요
function main(response) {
console.log("main");
response.writeHead(200, { "Content-Type": "text/html" });
response.write("Main Page");
response.end();
}
function login(response) {
console.log("login");
response.writeHead(200, { "Content-Type": "text/html" });
response.write("Login Page");
response.end();
}
이렇게 !
이제 url에 따라 화면에 보이는 메시지가 달라집니다 !!
그렇다면 없는 url을 입력한다면.. ? 에 대한 처리는 이미 위에서 오류가 났을때 if문으로 처리를 해 주었습니다 ㅎㅎ!!
이렇게 없는 url을 입력하면 No request handler found for + pathname이 출력됩니다
송아쌤 버전으로 수정해보면 router.js를
function route(pathname, handle, response) {
console.log("pathname: " + pathname);
if (typeof handle[pathname] === "function") {
handle[pathname](response);
} else {
response.writeHead(404, { "Content-Type": "text/html" });
response.write("Not Found");
response.end();
}
}
exports.route = route;
이렇게 수정하고 서버를 다시 실행 해 보아요
이렇게 Not Found가 출력됩니다
하 ,,, node.js에서 서버를 구동한것도 이번이 처음이었거든요 ,,
약간 처음 react 컴포넌트 분리할때의 그 기분을 ㅎㅎ 오랜만에 느꼈습니다.. (복습 필수.. ~)
송아쌤이 코드 쪼금만 작성해도 너무너무 잘했다면서 칭찬해주셔서 ㅜㅜ 정말 감사.. 제 자존감 지킴이십니다..
복습하고 더 열심히 해봐야겠어요 (:ᘌꇤ⁐ꃳ 三
앟 그리고 TIL 작성할때 쫌쫌 쓰기 좋은 이모티콘이 많은 사이트를 공유 해 드립니다..
'데브코스 TIL' 카테고리의 다른 글
[웹 풀사이클 데브코스 TIL] 3주차 Day 1, 2 (0) | 2023.11.28 |
---|---|
[웹 풀 사이클 데브코스 TIL] 2주차 Day 5 - 웹 생태계 전반에 대한 실습(2) (0) | 2023.11.24 |
[웹 풀사이클 데브코스 TIL] 2주차 Day 3 - 웹 생태계 전반에 대한 이론(2) (0) | 2023.11.22 |
[웹 풀사이클 데브코스 TIL] 2주차 Day 2 - 웹 생태계 전반에 대한 이론(1) (1) | 2023.11.21 |
[웹 풀사이클 데브코스 TIL] 2주차 Day 1 - Git 고급 (1) | 2023.11.20 |