10~11강. 라우팅, 익스프레스

한시현·2024년 3월 29일

UDR 백엔드 야생형

목록 보기
5/15

Section 1.

10강. 라우팅

라우팅

지난 시간에 서버를 만든 코드를 활용할 것이다.

const http = require("http");

const server = http.createServer((req, res)=>{
    res.setHeader("Content-type", "text/plain");
    res.write("Hello Node");
    res.end();
});

server.listen(3000, () => {
    console.log("서버가 실행 중");
});

이번엔 localhost:3000, 즉 요청 경로에 아무 단어를 붙여 볼 것이다.

이런 식으로 단어를 붙여도

이렇게 똑같은 메뉴가 나온다.

실제로 우리가 만들고 싶은 웹은 예를 들어 about이라는 메뉴를 누르면 주소가 about이라고 뒤에 서브폴더 형태로 붙으며 그에 해당하는 내용이 나오는 것이다.

ex) node.js 홈페이지

node.js 홈페이지의 About을 누르면

주소 뒤에 about이 포함되며 그 페이지로 이동한다. 우리가 만든 페이지는 그렇지 않다는 것이다.

이것은 라우팅이라는 개념 때문이다.

라우팅 : 클라이언트에서 들어오는 요청에 따라 그에 맞는 함수를 실행하는 것

라우팅을 이용하면 사용자가 입력하는 url에 따라 다른 내용을 보여줄 수 있다. 이 때 함께 고려하는 것이 요청 메서드, 즉 요청 방식이다. GET, POST, PUT, DELETE 같은 요청 메서드에 따라 처리할 함수를 다르게 연결할 수 있다. 이렇듯 http 에는 요청을 서버로 보낼 때 여러 방식을 사용할 수 있는데, 이번엔 그 중 GET을 보겠다.

이런 식으로 구글 사이트에 접속하고 네트워크를 확인해보면 각 파일을 가져올 때의 요청 url과 요청 메서드가 존재한다.

요청 url은 내가 가져오려고 하는 이미지, 문서, 파일 등이 어디에 있는지를 나타낸다.
요청 메서드이 파일을 가지고 무엇을 할 것인지를 나타낸다.
그리고 요청 메서드의 GET가져와서 브라우저 창에다가 전달해 달라는 뜻이다.

그래서 라우팅이라는 것은 사용자가 요청하는 경로, 선택한 요청 방식의 두 가지 조합을 통해 실행할 명령을 지정 해주는 것을 말한다.\

코드로 살펴보자.

server-5.js

req에는 요청, res에는 응답에 관련된 정보가 포함된다고 했었다.
요청하는 경로와 방식을 어디서 알아낼 수 있을까?

req.url : 요청 경로 (req 객체 안의 url)
req.method : 요청 방식 (req 객체 안의 method)

const http = require("http");

const server = http.createServer((req, res)=>{
    
    const {url, method} = req;

    res.setHeader("Content-type", "text/plain");

    if (method==="GET" && url ==="/home"){
        res.write("HOME");
        res.end();
    }
    else if (method==="GET" && url==="/about"){
        res.end("ABOUT");
    }
    else{
        res.end("Not Found");
    }
});

server.listen(3000, () => {
    console.log("서버가 실행 중");
});

server-5.js code 분석

js의 구조 분해 할당 기능을 통해 다음과 같이 작성할 수 있다.

    const {url, method} = req;

이부분은 const url에는 req.url값을, const method 에는 req.method 값을 저장해 달라는 것을 한 줄로 표현한 것이다. 즉, const url = req.url, const method = req.method와 같다. 이는 디스트럭팅이라고도 한다.

if (method==="GET" && url ==="/home"){
        res.write("HOME");
        res.end();
    }

method가 GET 방식이고, 요청 /url이 home이면 화면에 HOME이라 표시하고 응답을 끝내라는 의미이다.

    else if (method==="GET" && url==="/about"){
        res.end("ABOUT");
    }

method가 GET 방식이고, url이 /about이면 화면에 ABOUT이라 표시하고 응답을 끝내라는 의미이다.
화면에 표시할 write문이 하나밖에 없는 경우에는 res.write와 res.end를 하나로 합쳐서 위와 같이 표현할 수 있다.

    else{
        res.end("Not Found");
    }

두 가지 경우에 해당하는 것이 아니라면 Not Found라고 표시해주고 응답을 종료하겠다.
요청이 생겼을 때, 그 요청 객체에서 요청 경로와 요청 방식을 가져올 것이다.

실행 결과


우리는 코드에서 루트(/)일 경우를 지정하지 않았기 때문에 localhost:3000의 경우 Not Found로 표시된다.

/home을 붙이면 HOME 이 표시된다.

/about도 마찬가지이다.

그러나 사이트 하나에서 처리해야 할 라우트는 한 두개가 아니다. 그렇게 때문에 이것을 if, else if를 사용해 연결하면 가독성도 떨어지고 작성도 굉장히 힘들어질 것이다.

서버를 만들고 그 안에서 라우팅을 처리하는 과정을 돕는 것이 바로 express 프레임워크이다.

Section 2.

11강. 익스프레스

express 프레임워크를 사용하여 서버를 만들고 관리하는 방법을 배워보자.
우리는 http 모듈을 사용하여 서버를 만들수도 있지만, express에는 http 모듈의 기능은 물론 http 모듈에서는 지원하지 않는 다양한 기능들이 포함되어 있다.

  • 라우팅 : http 모듈보다 훨씬 쉽다.
  • 미들웨어 : 클라이언트의 요청, 서버의 응답 사이에서 중간 처리 함수들을 쉽게 다룰 수 있다.
  • 템플릿 엔진 : 웹 브라우저 화면에 어떻게 보여질 것인지를 결정하는 여러 엔진을 골라 사용할 수 있다.
  • 정적인 파일 지원

작업 폴더 추가

연락처 관리자를 위한 애플리케이션을 만들 폴더를 추가하자.
그리고 npm 초기화를 통해 node.js 환경을 만들어 보겠다.

npm init

우선 터미널에서 초기화를 진행한다.

package name: (mycontacts) contacts-manager
version: (1.0.0)
description: simple contacts manager
entry point: (request.js) app.js
test command:
git repository:
keywords:
author:
license: (ISC)
  • package name : 내가 지금 만드려는 애플리케이션을 설명하는 것이다. 여기에 원하는 이름을 넣으면 되지만, 웬만하면 소문자를 사용하는 것이 좋다.

  • version : 버전을 넣어주면 된다. 애플리케이션은 기능이 달라질 때마다 버전이 업데이트 된다. 여기에 원하는 버전을 지정해주면 된다.

  • description : 다른 사용자가 이 애플리케이션을 쉽게 이해할 수 있는 간단한 설명을 넣어주면 된다.

  • entry point : 애플리케이션을 시작하는 파일 이름을 넣어주면 된다. 작업 폴더 안에서 어떤 파일을 실행해서 앱을 시작할 것인가 이다.

  • test command : 애플리케이션을 완성하기 전에 여러번 테스트를 거칠 수 있는데 그때 사용할 명령을 지정할 수 있다. 생략도 가능하다.

  • git repository : 애플리케이션을 git에 push하고 있다면 git 저장소를 지정하면 된다.

  • keyword : 애플리케이션을 다른 사람이 쉽게 검색할 수 있도록 필요한 키워드를 넣어주면 된다.

  • author : 애플리케이션 제작자 이름을 넣어주면 된다.

  • license : 이 애플리케이션에 대한 라이선스를 지정하면 되는데 종류가 많다. 특별히 뭔가를 지정해야 한다 하면 그 라이선스를 넣어주면 되고, 기본값 (ISC) 로 가고 싶다면 그냥 enter를 누르면 된다.

About to write to C:\Users\user\Desktop\doit-node\myContacts\package.json:

{
  "name": "contacts-manager",
  "version": "1.0.0",
  "description": "simple contacts manager",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this OK? (yes) yes

그러면 터미널에 package.json 파일이 만들어질 것이고 그 안에 이러한 내용을 들어갈 것이라 표시된다. yes를 누르자.

package.json

{
  "name": "contacts-manager",
  "version": "1.0.0",
  "description": "simple contacts manager",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}

생성된 package.json 파일 안에 입력한 내용대로 작성이 된 것을 확인할 수 있다.

express 패키지 설치

우리는 express 를 이용해 서버를 만들 것이기 때문에 익스프레스 패키지를 설치 해 줘야 한다.

터미널에서 패키지를 설치해보자.

npm i express // i 대신 install도 사용 가능

설치가 끝나면 작업 폴더에 node_modules라는 새로운 폴더가 생긴 것을 확인할 수 있다.
이 폴더에는 express 패키지와 관련된 파일이 저장되어 있다.
폴더를 열어보면 express와 이 express를 사용하기 위해 필요한 다른 여러 패키지들도 함께 설치되어있다.

  "dependencies": {
    "express": "^4.19.2"
  }

또한 이전에 생선된 package.json 파일에 dependency 항목이 생기면서 이 애플리케이션은 express 패키지를 사용하고 있고, 몇 버전을 사용하는지 자동으로 기록된다.

이렇게 express를 사용할 준비가 모두 끝났다...

사실 한가지 더 설치해야 할 것이 있는데, nodemon 패키지이다.

nodemon 패키지 설치

서버 코드를 수정했을 경우, 기존에 실행하던 서버를 멈추고 다시 서버를 실행해야만 수정 내용이 반영된다. 수정할때마다 매번 서버를 끄고 키는건 정말 번거롭기 그지없다.
이런 불편함을 줄이기 위해 등장한 패키지이다.

nodemon 패키지 : 코드를 수정했을때 서버를 재시작하지 않고도 수정 내용을 바로 적용해준다.

npm i nodemon --save-dev -g

nodemon의 경우 모듈 자체가 개발의 어떤 기능에 영향을 주는 것이 아닌, 개발의 편의성을 위해 사용하는 것이므로 dependencies(의존성)에 등록할 필요가 없다. 그렇기 때문에 nodemon을 설치할 때는 몇 가지 옵션을 사용하게 된다.

  • --save-dev : 이 모듈은 개발하는 동안에만 사용할 것이고, 나중에 앱 코드를 배포할 때 는 포함시킬 필요가 없다는 의미이다.
  • -g : 글로벌을 의미한다. 한번 설치하면 시스템에 있는 다른 곳에서도 자유롭게 사용 할 수 있도록 한다.

이렇게 패키지를 설치하면, package.json의 dependencies에 express와 달리 포함되지 않는다. nodemon은 앱 코드 자체에는 영향을 주지 않는다는 뜻이다.

이제 필요한 모듈 두 가지를 모두 설치했다. express를 이용해서 서버 만드는 방법을 알아보자.

express로 서버 만들기

npm에서 애플리케이션을 설정할 때, 시작하는 파일의 이름을 우리는 app.js라고 지정했다. 그 말인즉, 서버 파일은 app.js라는 파일에다가 만들어야 한다는 의미이다.

app.js

const express = require("express");
const app = express();

app.get("/", (req,res)=>{
    res.send("Hello Node");
});

app.listen(3000, () => {
    console.log('서버 실행 중');
});

app.js code 분석

const express = require("express");
const app = express();

우선 express 모듈을 가지고 와 express 변수에 할당해준다.
그리고 express를 실행시켜서 app이라고 하는 이름을 가진 서버를 만들 수가 있다.
이 app이 앞으로 우리가 처리할 대상이 된다.

app.listen(3000, () => {
    console.log('서버 실행 중');
});

리스닝을 3000번 포트에서 진행하고, 서버가 실행이 되면 서버 실행 중이라고 콘솔 창에 표시한다.
http 모듈로 서버를 만들 때와 비슷하나, http 모듈에서는 createServer 함수를 이용해서 서버를 만들었지만, express에서는 express를 실행만 하면 서버가 만들어진다.

간단한 라우트 코드를 추가 해보자.
루트 경로로 요청이 들어올 때, Hello node 라고 표시되도록 하겠다.

app.get("/", (req,res)=>{
    res.send("Hello Node");
});

app 이라는 서버에서 get 방식으로 / 경로에 요청이 들어온다면, Hello node를 출력하는 콜백 함수를 실행하라는 의미이다. 서버 이름 뒤에 요청 방식과 요청 경로를 지정하고 어떤 것을 실행할지는 콜백 함수 형태로 제공한다.
http 모듈에서는 if, else if 등을 활용해 경로와 요청 방식을 일일히 체크해줘야 했지만, express 서버에서는 요청 방식을 함수 이름으로 사용할 수 있다.

이렇게 만든 app 서버를 실행시켜보자. 설치한 nodemon 패키지로 실행 해보자.

PS C:\Users\user\Desktop\doit-node\myContacts> nodemon app
[nodemon] 3.1.0
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node app.js`
서버 실행 중

이렇게 실행되는 것을 확인할 수 있다. 이제 브라우저 창으로 가서 요청 해보자.
루트(/) 경로에서 GET 방식이다.

제대로 라우팅 된 것을 확인할 수 있다.

한가지만 더 보도록 하자.
contacts 라는 경로에서 GET이라는 요청이 왔을 때 Contacts Page라고 표시해보겠다.

app.get("/contacts", (req,res)=>{
    res.send("Contacts Page");
});

작성한 전체 코드에 위 코드를 추가하자. 이러면 서버 코드가 수정이 된 상태이다. nodemon을 사용하지 않았다면 서버를 재시작해야 했을 것이다.

[nodemon] restarting due to changes...
[nodemon] starting `node app.js`
서버 실행 중

수정한 코드를 저장하면, 이렇게 restarting을 nodemon에서 알아서 진행한다.

이렇게 express를 사용하면 서버 만들기, 라우팅 처리 모두 쉬워진다.
또한 nodemon을 사용하면 서버를 재시작하지 않고도 수정된 내용을 즉시 반영할 수 있다.

의문점

nodemon 실행 오류

nodemon을 통해 코드를 실행할 때, windows powershell이 get-ExecutionPolicy로 현재 스크립트 실행 권한을 확인했을 때 Restricted로 되어 있다면 스크립트를 실행할 수 없다는 오류가 발생한다.
windows powershell을 관리자 권한으로 실행 후 Set-ExecutionPolicy RemoteSigned을 통해 RemoteSigned로 바꾸자.
잘 바뀌었는지 확인하려면 get-ExecutionPolicy로 다시 확인하면 된다.
-> 문제 해결

콜백 함수

사실 처음에 콜백 함수를 공부했을 때 이상하게 이해가 되지 않았다. 그 때문에 추가적인 공부를 좀 더 진행했다.

정의 : 함수 안에 매개변수 형태로 들어가는 함수
ex) addEventListener('click', function() {}) // function이 콜백 함수
용도 : 순차적으로 실행하고 싶을 때 씀
ex1) 위 코드 작성 시 "버튼을 클릭했을 때" 코드 실행
ex2) setTimeout(function() { @ }, 1000) // 1초 경과 후 @ 실행
특징
1. 다른 곳에서 만든 함수도 콜백 함수로 넣을 수 있다.
ex) addEventListener('click', 함수명)
2. 콜백 함수에 함수명 작명 가능 (다만, 쓸데 없음)
3. 콜백 함수가 필요한 함수들에만 콜백 함수 사용가능.

0개의 댓글