📚요약
지난 시간 HTML, CSS, JS를 활용하는 방법을 배웠습니다. 이어서 페이지를 만들어볼 건데 단순하게 화면만 만들어 보겠습니다. 그리고 이어서 Node.js를 활용해 웹서버도 만들어 보겠습니다.
📖페이지 만들어보기(실습)
화면은 테니스 라켓을 파는 시장을 만들어 볼 것입니다. 배운 것들을 활용해 만들어 보시면 됩니다.
기존 강의에서 제공되는 이미지와 코드는 문제가 될 수 있으므로 따로 구한 이미지를 사용하고 코드는 힌트만 제공됩니다.
Hint!
- 화면 이동
- HTML tag : div, a, input, h1, p, img, table, th, tr, td
- CSS 적용을 위한 class 및 id
- 테니스 라켓 배치 CSS 'display : grid'
- 글씨 가운데 정렬 CSS 'text-align : center'
- 여백을 위한 CSS 'margin'


📖백엔드 구조
저~번 시간에 웹의 구조를 볼 때 요청을 하는 Client와 받는 Server가 있었습니다. 웹 서버는 단순하게 하나로 이루어져 있지 않고 크게 3가지로 나뉩니다.
- 웹 서버(Web Server) : 정적 페이지에 대응하는 서버. 동적 페이지는 웹 애플리케이션 서버로 넘긴다.
- 웹 애플리케이션 서버(Web Aplication Server, WAS) : 웹 서버에서 넘어온 동적 페이지에 대해 처리하는 서버. 데이터 연산 처리를 위해 데이터베이스와 연결되어 있다.
- 데이터베이스(Database, DB) : 데이터를 통합해 효율적인 관리를 위한 데이터 집합체.
정적 페이지 : 저장된 그대로 사용자에게 전달되는 웹 페이지.
동적 페이지 : 런타임에 생성되는 웹 페이지. 웹 애플리케이션 서버에 의해 제어되는 서버 사이드 동적 웹 페이지와 브라우저에서 실행되는 자바스크립트에 의해 제어되는 클라이언트 사이트 동적 웹 페이지가 있다.
📖Node.js
Node.js는 자바스크립트를 스크립트 언어 이상으로 프로그래밍 언어 역할을 할 수 있도록 지원하는 플랫폼으로 Node.js를 이용하여 자바스크립트를 사용해 백엔드를 구현할 수 있다.
플랫폼이란 소프트웨어를 실행할 수 있는 기반(환경)
📖웹 서버 만들기
📄http 모듈 사용
기본적으로 Node.js에서 제공하는 모듈을 이용하면 웹 서버를 쉽게 만들 수 있다. 우리가 사용할 모듈은 http 모듈이고 이를 활용해 Hello Node.js 화면을 보여주는 서버를 열어보겠다.
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);
△server.js
서버를 실행하기 위해서는 터미널을 키고 'node server.js' 명령어를 실행시킨 후 브라우저에서 'localhost:8888'로 접근하면 다음과 같은 화면이 나타납니다.

잠깐! 여기서 localhost:8888이 어디서 나왔는가?
localhost는 본인의 컴퓨터를 가르키는 주소이며 같은 의미로 사용할 수 있는 IP 주소 127.0.0.1을 대신해서 자주 사용됩니다. 8888은 포트 번호(Port Number)로 포트를 구별하기 위해 사용됩니다. 그렇다면 포트는 무엇인가? 포트는 논리적인 접속장소를 의미하며, 클라이언트 프로그램이 특정 서버 프로그램을 지정하는 방법으로 사용합니다.
🍯tip! 서버 실행 및 중지
서버 실행은 터미널을 열어 'node 서버코드파일명.js' 로 실행시킬 수 있으며 'Ctrl + c'로 종료할 수 있다.
📄HTTP 구조
Node.js가 제공해 주는 http 모듈을 사용할 때 response를 가지고 뭔가 하는 것을 볼 수 있는데 이를 위해 HTTP의 구조를 간단하게 보면 헤더(header)와 바디(body)로 나뉘어진다. 헤더에는 다양한 정보가 들어가는데 그중 200은 http status code를 의미하며, content-type : text/html은 해당 응답이 html 파일이라는 것을 writeHead 함수를 통해 알려줍니다. 이어서 바디에는 내용을 write 함수를 통해 담을 수 있는데, 이 결과가 화면으로 나오게 됩니다.
📄모듈(module) 만들기
우리가 사용했던 http와 같은 모듈을 만들어 사용할 수 있습니다. require 함수와 exports 키워드를 사용하면 가능합니다. 원하는 함수를 만들고 exports를 통해 밖에서 사용할 수 있도록 내보내줍니다. 그렇게 내보낸 함수는 require를 통해 받아와 사용할 수 있습니다.
// server.js
let http = require("http");
function start(route, handle) {
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;
// index.js
let server = require("./server");
server.start();
📄URL
이제는 Node.js의 다른 모듈 url 모듈을 한 번 살펴보겠습니다. url 모듈을 사용하게 되면 우리가 흔히 주소라고 불리는 부분에 대한 정보를 가져올 수 있습니다.
URL은 네트워크 상에서 자원(웹 페이지, 이미지, 비디오 등)이 어디 있는지 알려주기 위한 규약. 웹 주소 또는 링크라고 불림.
// 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(404, { "Content-Type": "text/html" });
response.write("not found");
response.end();
}
http.createServer(onRequest).listen(8888);
}
// router.js
function route(pathname) {
console.log("pathname: " + pathname);
}
exports.route = route;

터미널의 결과를 보면 뭔가 이상한게 따라오는 것을 볼 수 있습니다. 찾아보니 브라우저 암흑기의 유물?이라고 표현하면서 크게 문제는 없다고 하니 남겨두고 진행합니다.(덕분에 라우터 파트에서 잠깐 고생합니다...ㅠ)
📄라우터(Router)
라우터는 여러 다양한 의미가 있지만 이곳에서는 주소에 따라 자동으로 연결해 준다라고 받아들이시면 됩니다. 보통 이제 주소창을 잘 안 보겠지만, 페이지마다 주소가 바뀌는 것을 볼 수 있습니다. 그리고 화면 또한 바뀝니다. 이번에는 그것을 간단하게 실습해 보겠습니다.
🍯tip! 그렇게 중요한 부분은 아니지만 위에 단계에서 favicon.ico를 제거하지 않고 넘어오신 분들은 보시면 좋습니다. 바로 'handle[pathname] is not function'이라는 오류 메시지가 발생할 수 있습니다. pathname에 favicon.ico가 넘어가면서 발생하는 문제입니다. 이를 해결하기 위해서는 두 가지 방법이 있습니다.
1. 기존 handle에 favicon.ico를 처리해 준다.
2. 조건문(if)을 통해 handle[pathname]의 타입이 function인 경우에만 동작하도록 한다.
// index.js
let server = require("./server");
let router = require("./router");
let requestHandler = require("./requestHandler");
server.start(router.route, requestHandler.handle);
// 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);
}
http.createServer(onRequest).listen(8888);
}
exports.start = start;
// 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;
// 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();
}
function favicon(response) {
console.log("favicon");
}
let handle = {};
handle["/"] = main;
handle["/login"] = login;
handle["/favicon.ico"] = favicon;
exports.handle = handle;



위에 주소를 보면 '/login'을 추가했더니 아래 화면도 성공적으로 바뀐 것을 볼 수 있습니다. 그리고 이상한 주소를 입력하게 되면 페이지가 없다고 나오게 됩니다.
다음 시간에 계속...
출처 & 참고
김송아 강사님 강의
localhost, 위키백과, 2024.04.18
포트, 위키백과, 2024.04.18
포트 개념 정리 및 종류, 잇트루, 2024.04.18
왜 url이 두번 출력 되는 건데? feat. favicon.ico, tokkiC, 2024.04.19
'개발 > 프로그래머스 데브코스' 카테고리의 다른 글
| 프로그래머스 데브코스 11일차 with. TS 웹 풀스택 (0) | 2024.04.22 |
|---|---|
| 프로그래머스 데브코스 10일차 with. TS 웹 풀스택 (0) | 2024.04.19 |
| 프로그래머스 데브코스 8일차 with. TS 웹 풀스택 (0) | 2024.04.17 |
| 프로그래머스 데브코스 7일차 with. TS 웹 풀스택 (0) | 2024.04.16 |
| 프로그래머스 데브코스 2주차 회고 with. TS 웹 풀스택 (0) | 2024.04.15 |