위 사이트에 기재된 API 문서를 참고하여 Express 웹 어플리케이션을 만들 수 있습니다.
나만의 웹 서버를 만들어봅시다.
import express from "express";
// 바벨을 세팅하지 않았다면, const express = require("express") 라고 작성!
const app = express();
// express app 만들기 -> 서버!
const PORT = 4000;
// 포트 넘버 지정
const handleHome = (req, res) => {
return res.send("This is Home.");
}
// req 와 res 는 함수 호출 시 자동으로 보내지는 매개변수
// 요청에 대해 응답 반환
// res.send("content") => 요청에 대한 응답으로 메시지를 보냄
app.get('/', handleHome);
// 브라우저가 루트 페이지로 접속하며 루트 페이지에 대해 get 요청을 할때 라우팅
// get 요청에 대한 처리 콜백함수 handleHome
app.listen(PORT)
// 포트 번호로 연결
express
를 얻어온 후 실행하면 app
이 만들어집니다.
만들어진 app
은 클라이언트에게 서비스를 제공하는 서버라고 볼 수 있습니다.
listen()
메소드로 app
에 포트 번호를 넘겨주면, 서버가 클라이언트와 통신하는데 해당 포트를 사용합니다.
우리 서버는 내 컴퓨터 localhost 의 4000번 포트를 통해 통신합니다.
우리는 이에 접속하기 위해 http://localhost:4000 이라는 주소를 브라우저에 넘깁니다.
브라우저 : localhost의 4000번 포트의 서버 프로그램과 통신하는군요?
이렇게 됩니다.
우리가 접속을 요청하면, 브라우저는 접속하려는 페이지 정보를 받아오기 위해 서버에게 요청을 보냅니다
이 때, 브라우저가 보내는 요청이 GET
입니다.
http://localhost:4000 는 사실 http://localhost:4000/ 이고, "/"
(루트) 페이지이죠.
브라우저는 "/" 에 해당하는 정보를 서버에게 받아와서 사용자에게 보여줍니다.
브라우저가 보낸 GET
요청에 대해, 서버가 응답을 해줘야 우리가 결과를 볼 수 있습니다.
서버가 GET
요청에 응답하지 않는다면 브라우저는 계속 대기하다가 응답을 못 받았다고 오류 메시지를 띄우겠죠?
get()
메소드는 브라우저가 페이지에 대해 GET
요청을 했을 때, 이에 대한 응답을 처리합니다.
const handleLogin = (req, res) => {
return res.send("Login Page");
}
// req, res 변수를 받아 요청에 응답
app.get("/login", handleLogin);
// http://localhost:4000/login 페이지 요청에 대한 처리를 handleLogin 에서 처리
// handleLogin 은 /login 에 대한 controller
경로에 대한 GET
요청을 컨트롤러
에 맡깁니다.
컨트롤러(콜백함수) 에서는 요청과 응답에 대한 두 변수를 자동으로 받아오고,
요청에 응답하면 브라우저가 GET
에 대한 결과를 얻을 수 있습니다.
미들웨어는 브라우저가 요청을 한 후 서버가 응답하기까지의 절차에서,
요청과 응답 사이에 존재하는 소프트웨어
를 의미합니다. (middle software)
const myMiddleware = (req, res, next) => {
console.log("This is Middleware.");
next(); // 다음 함수를 실행
}
const handleHome = (req, res, next) => {
return res.send("This is Home.");
}
app.get('/', myMiddleware, handleHome);
// get 으로 요청을 보내고
// handleHome 에서 응답을 하기 전에
// myMiddleware 를 거치고 있음
함수가 자동으로 받는 매개변수는 req, res, next
가 있습니다.
req 는 요청에 대한 object, res 는 응답에 대한 object, 그리고 next 는 다음에 존재하는 함수 변수이죠.
next 에 해당하는 함수는 myMiddleware 의 경우 handleHome 입니다.
handleHome 의 경우 get() 안에 제일 마지막에 있으므로 next 에 해당하는 함수가 없습니다.
따라서 handleHome 은 마지막 차례에 오는, finalware
라고 할 수 있습니다.
return 으로 응답을 하며 연결을 종료하는, 마지막으로 호출되는 함수이니까요.
즉, 요청과 응답 사이에 있다면 어떤 controller 든지 미들웨어가 될 수 있습니다.
const myMiddleware = (req, res, next) => {
console.log("This is Middleware.");
next();
}
const handleHome = (req, res) => {
return res.send("This is Home.");
}
// finalware 이므로 next 가 없어도 됨!
app.get('/', myMiddleware, handleHome);
handleHome 은 컨트롤러로써 마지막에 호출되므로 next 를 받지 않아도 됩니다.
const myMiddleware = (req, res, next) => {
console.log("This is Middleware.");
return res.send("This is END.");
// 미들웨어에서 먼저 응답을 끝내버리면...?
next(); // next 함수는 실행되지 않음!
}
const handleHome = (req, res) => {
return res.send("This is Home.");
}
app.get('/', myMiddleware, handleHome);
미들웨어가 먼저 응답을 return 하면 get() 이 종료되어 next 함수도 실행되지 않게 됩니다.
지정된 경로에 미들웨어가 적용되게 하고 싶을 때 사용합니다.
app.use(path, callback)
이와 같은 형태로, 요청한 URL
경로의 루트가 path
와 일치할 때 미들웨어가 적용됩니다.
path 의 기본은 "/"
루트 경로입니다.
루트는 모든 경로의 시작점으로, 경로들은 루트에서 뻗어나온다고 볼 수 있습니다.
따라서 path 를 따로 지정하지 않고 기본 세팅대로 "/" 가 적용
되게 하면,
모든 라우트에 미들웨어가 적용
됩니다.
app.use(myMiddleware);
// 맨 위에 use() 위치
app.get("/", handleHome);
app.get("/login", handleLogIn);
// "/" 와 "/login" 의 라우터 모두에 myMiddleware 미들웨어 적용
app.use() 를 최상단에 두면 이하의 모든 get() 의 경로에 미들웨어가 적용됩니다.
app.get("/", handleHome);
// 미들웨어 적용되지 않음
app.use(myMiddleware);
// 중간에 use() 위치
app.get("/login", handleLogIn);
// 미들웨어 적용
use() 이전에 작성된 get() 의 경로에는 미들웨어가 적용되지 않습니다.
app.use(myMiddleware, secondMiddleware);
// 미들웨어 여러개 사용
app.get("/", handleHome);
app.get("/login", handleLogIn);
여러 개의 미들웨어가 적용되게 할 수도 있습니다.
직접 작성하지 않아도, 누가 이미 만들어놓은 미들웨어를 가져다 사용할 수도 있습니다.
morgan 을 사용해봅시다.
npm i morgan
으로 morgan을 설치하고
import morgan from "morgan";
// 바벨 적용을 안했다면 const morgan = require("morgan");
// morgan 가져오기
const logger = morgan("dev");
// morgan(option) 이 옵션에 맞는 함수를 반환해줌
// logger 에는 반환된 함수가 들어감
app.use(logger);
// 미들웨어 적용!
morgan 을 가져와 morgan(option) 을 해주면 옵션에 맞는 함수를 반환해줍니다.