본문 바로가기

개발/프로그래머스 데브코스

프로그래머스 데브코스 9일차 with. TS 웹 풀스택

📚요약

지난 시간 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가지로 나뉩니다.

  1. 웹 서버(Web Server) : 정적 페이지에 대응하는 서버. 동적 페이지는 웹 애플리케이션 서버로 넘긴다.
  2. 웹 애플리케이션 서버(Web Aplication Server, WAS) : 웹 서버에서 넘어온 동적 페이지에 대해 처리하는 서버. 데이터 연산 처리를 위해 데이터베이스와 연결되어 있다.
  3. 데이터베이스(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은 네트워크 상에서 자원(웹 페이지, 이미지, 비디오 등)이 어디 있는지 알려주기 위한 규약. 웹 주소 또는 링크라고 불림.

URL-위키백과, URL-MDN

// 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;

url을 가져온 터미널 결과

터미널의 결과를 보면 뭔가 이상한게 따라오는 것을 볼 수 있습니다. 찾아보니 브라우저 암흑기의 유물?이라고 표현하면서 크게 문제는 없다고 하니 남겨두고 진행합니다.(덕분에 라우터 파트에서 잠깐 고생합니다...ㅠ)

 

📄라우터(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