미들웨어는 body를 파싱할 때 사용
Express middleware are functions that run during the request/response lifecycle.
내장 JSON 미들웨어를 이용해 request.body를 파싱함.
또한 Express 정적 미들웨어로 CSS, 이미지, javascript와 같은 정적파일도 처리.
미들웨어는 Express 내 모든 것 중 하나의 구성 요소일 뿐.
요청-응답 생명주기 내에서 실행되는 함수.
즉, Express에 요청이 전달되는 순간부터 코드가 처리를 완료하고 응답을 내보낼 때 까지 실행.
MIDDLEWARE
Mogran
<index.js>
const express = require('express');
const app = express();
const morgan = require('morgan');
morgan('tiny')
app.use(
morgan('tiny'))
app.get('/', (req,res)=> {
res.send('home page')
})
app.get('/dogs', (req,res)=> {
console.log('WOOFFFF!!!')
})
app.listen(3000, () => {
console.log('App is running on localhost:3000')
})
localhost:3000/dogs 로 진입시 미들웨어 실행.
위 app.use 중 어떠한 라우트핸들러들의 주기도 종료되거나 매칭되지 않을 때 가장 아래에 존재하는 app.use는 어떤 요청에도 매칭이되니 '찾을수없음'이 뜨게됨.
쿼리 비밀번호 설정
password 쿼리 제대로 입력시 /dogs 라우트 핸들러 발동.
password 쿼리가 입력되지 않았을 때 오류발생.
app.use 대신 함수로 설정 (콜백함수로 사용하기 위함)
/secret 경로에만 적용되는 verifyPassword 콜백함수 등록
npm i ejs.mate
<app.js>
//ejs.mate 사용하겠다고 알리기.
const ejsMate = require('ejs-mate')
app.engine('ejs', ejsMate)
campgrounds 폴더에 있는 ejs 파일에 일괄적으로 적용시킬 수 있는 layouts(boilerplate(상용구)파일 생성))
campgrounds폴더에 있는 모든 ejs 파일에 일괄적으로 boilerplate.js 파일 적용시키기.
공통적으로 적용되는 부분들을 한 파일에 모아 언제든지 가져다 쓸 수 있게 만들기.
<navbar.ejs>
<nav class="navbar sticky-top navbar-expand-lg navbar-dark bg-dark">
<div class="container-fluid">
<a class="navbar-brand" href="#">YelpCamp</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNavAltMarkup"
aria-controls="navbarNavAltMarkup"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav">
<a class="nav-link" href="/">Home</a>
<a class="nav-link" href="/campgrounds">Campgrounds</a>
<a class="nav-link" href="/campgrounds/new">New Campground</a>
</div>
</div>
</div>
</nav>
<footer.ejs>
<!-- py-3 : padding을 y축방향(상단)으로 주는것-->
<footer class="footer bg-dark py-3 mt-auto">
<div class="container">
<!-- text-muted: 텍스트 약간 밝고 부드럽게 만들기-->
<!-- © : 저작권 문양 넣기-->
<span class="text-muted">© YelpCamp2022 </span>
</div>
</footer>
////
<boilerplate.ejs>
<!-- d-flex: display flex, flex-column: body의 방향성이 세로로 길게 향하게 그래야 footer가 하단에 깔림 -->
<!-- bootstrap 을 활용중이므로 css 설정 가능.-->
<!-- body가 flexbox이어서 상단부터 하단까지 위치한 열이다.
line에는 가로축을 따라 움직이는 self가 있어 모든게 가로축상에 놓여짐. 또 item이라는것도 있어 모든게 왼쪽에서 오른쪽으로
정렬됨. 따라서 justify-content 사용시 모든 항목들에게 영향을 끼치게됨. 그러나
footer 처럼 메인항목 하나만 움직이게 만들어주고 싶은거기 때문에
상단여백(mt-auto), 좌측여백(ml-auto)를 사용.-->
<body class="d-flex flex-column vh-100">
<%- include('../partials/navbar')%>
<main class="container mt-5">
<%- body %>
</main>
<%- include('../partials/footer')%>
Unplash Source (무료로 사용가능한 고화질 이미지)
1) models 폴더 내 campground.js 파일에 image 정보 추가
const CampgroundSchema = new Schema({
title: String,
image: String,
price: Number,
description: String,
location: String
});
2) seeds 폴더 내 index.js 파일에 Campground 모델에 정보 추가
const seedDB = async() => {
//기존의 캠핑장은 삭제.
await Campground.deleteMany({});
//랜덤으로 캠핑장 50개 리스트 만들기.
for(let i=0; i<50; i++) {
const random1000 = Math.floor(Math.random() * 1000);
const price =Math.floor(Math.randon() * 20) + 10;
// 캠프 객체들 생성하기.
const camp = new Campground({
location : `${cities[random1000].city}`,
state : `${cities[random1000].state}`,
//' 아름다운 캐년'처럼 형용사 + 명사 조합
title: `${sample(descriptors)} ${sample(places)}`,
image: 'https://source.unsplash.com/collection/483251',
description: 'Lorem ipsum, dolor sit amet consectetur adipisicing elit. Sint cum eos sed saepe, totam quo eaque maiores voluptatem mollitia aliquid? Ea consequatur cum repudiandae, totam pariatur voluptatem quia nesciunt ipsam!',
price
})
//50개 캠핑장 저장.
await camp.save();
3) campgrounds 폴더 내 show.ejs 파일에 img,description 추가
<show.ejs>
<% layout('layouts/boilerplate')%>
<h1><%=campground.title%></h1>
<h2><%=campground.location%></h2>
<img src="<%=campground.image%>" alt="">
<p><%=campground.description%></p>
<p>
<a href="/campgrounds">All Campgrounds</a>
</p>
<p>
<form action="/campgrounds/<%=campground._id%>?_method=DELETE" method="POST">
<button>Delete</button>
</form>
</p>
<footer>
<a href="/campgrounds/<%=campground._id%>/edit">Edit Campground</a>
</footer>
/campgrounds/index
<index.ejs>
<% layout('layouts/boilerplate')%>
<h1>All Campgrounds</h1>
<a href="/campgrounds/new">Add Campground</a>
<ul>
<% for (let campground of campgrounds){%>
<li>
<div class="card" mb-3>
<div class="row">
<!-- img 삽입 1/3 차지-->
<div class="col-md-4">
<img class="img-fluid" alt="" src="<%=campground.image%>" />
</div>
<!-- 캠핑장에 대한 제목과 설명 부분 2/3 차지-->
<div class="col-md-8">
<div class="card-body">
<h5 class="title"><%=campground.title%></h5>
<p class="card-text"><%=campground.description%></p>
<p class="card-text">
<samll class="text-muted"><%=campground.location%></samll>
</p>
<a class="btn btn-primary" href="/campgrounds/<%=campground._id%>"
>View <%=campground.title%></a
>
</div>
</div>
</div>
</div>
</li>
<% }%>
</ul>
new.ejs
<% layout('layouts/boilerplate')%>
<div class="row">
<h1 class="text-center">New Campground</h1>
<!-- 열의 절반을 차지하되 왼쪽으로 쏠리지 않고 가운데로 오게끔 3만큼 ㅇffset 시키는것.-->
<div class="col-6 offset-3">
<form action="/campgrounds" method="POST">
<!-- mb-3 : css 파일을 따로 만드는것보다 부트스트랩 클래스를 이용하는것이 더 효율적-->
<div class="mb-3">
<label class="form-label" for="title">Title</label>
<!-- campground[title]처럼 중괄호사이에 이름이나 위치등을 넣으면 데이터가 POST 요쳥을 해서
Express 앱을 지나 서버로 갈 때 <body>에 포함된게 campground라고 정렬됨.
콘텐츠를 그룹화 할 수 있는 좋은 방법.-->
<input
class="form-control"
type="text"
id="title"
name="campground[title]"
/>
</div>
<div class="mb-3">
<label class="form-label" for="location">Location</label>
<input
class="form-control"
type="text"
id="location"
name="campground[location]]"
/>
</div>
<div class="mb-3">
<label class="form-label" for="image">Image URL</label>
<!-- campground[title]처럼 중괄호사이에 이름이나 위치등을 넣으면 데이터가 POST 요쳥을 해서
Express 앱을 지나 서버로 갈 때 <body>에 포함된게 campground라고 정렬됨.
콘텐츠를 그룹화 할 수 있는 좋은 방법.-->
<input
class="form-control"
type="text"
id="image"
name="campground[image]"
/>
</div>
<div class="mb-3">
<label class="form-label" for="price">Campground Price</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input
type="text"
class="form-control"
aria-label="price"
id="price"
placeholder="0"
name="campground[price]"
/>
<span class="input-group-text">.00</span>
</div>
</div>
<div class="mb-3">
<label class="form-label" for="description">Description</label>
<!-- campground[title]처럼 중괄호사이에 이름이나 위치등을 넣으면 데이터가 POST 요쳥을 해서
Express 앱을 지나 서버로 갈 때 <body>에 포함된게 campground라고 정렬됨.
콘텐츠를 그룹화 할 수 있는 좋은 방법.-->
<textarea
class="form-control"
type="text"
id="description"
name="campground[description]"
>
</textarea>
</div>
<div class="div mb-3">
<button class="btn btn-primary">Submit</button>
</div>
</form>
<a href="/campgrounds">All Campgrounds</a>
</div>
</div>
show.ejs
<% layout('layouts/boilerplate')%>
<div class="row">
<h1 class="text-center">Edit Campground</h1>
<!-- 열의 절반을 차지하되 왼쪽으로 쏠리지 않고 가운데로 오게끔 3만큼 ㅇffset 시키는것.-->
<div class="col-6 offset-3">
<form action="/campgrounds/<%=campground._id%>?_method=PUT" method="POST">
<!-- mb-3 : css 파일을 따로 만드는것보다 부트스트랩 클래스를 이용하는것이 더 효율적-->
<div class="mb-3">
<label class="form-label" for="title">Title</label>
<!-- campground[title]처럼 중괄호사이에 이름이나 위치등을 넣으면 데이터가 POST 요쳥을 해서
Express 앱을 지나 서버로 갈 때 <body>에 포함된게 campground라고 정렬됨.
콘텐츠를 그룹화 할 수 있는 좋은 방법.-->
<input
class="form-control"
type="text"
id="title"
name="campground[title]"
value="<%=campground.title %>"
/>
</div>
<div class="mb-3">
<label class="form-label" for="location">Location</label>
<input
class="form-control"
type="text"
id="location"
name="campground[location]]"
value="<%=
campground.location%>"
/>
</div>
<div class="mb-3">
<label class="form-label" for="image">Image URL</label>
<!-- campground[title]처럼 중괄호사이에 이름이나 위치등을 넣으면 데이터가 POST 요쳥을 해서
Express 앱을 지나 서버로 갈 때 <body>에 포함된게 campground라고 정렬됨.
콘텐츠를 그룹화 할 수 있는 좋은 방법.-->
<input
class="form-control"
type="text"
id="image"
name="campground[image]"
value="<%=
campground.image%>"
/>
</div>
<div class="mb-3">
<label class="form-label" for="price">Campground Price</label>
<div class="input-group">
<span class="input-group-text">$</span>
<input
type="text"
class="form-control"
aria-label="price"
id="price"
placeholder="0"
name="campground[price]"
value="<%=campground.pirce%>"
/>
<span class="input-group-text">.00</span>
</div>
</div>
<div class="mb-3">
<label class="form-label" for="description">Description</label>
<!-- campground[title]처럼 중괄호사이에 이름이나 위치등을 넣으면 데이터가 POST 요쳥을 해서
Express 앱을 지나 서버로 갈 때 <body>에 포함된게 campground라고 정렬됨.
콘텐츠를 그룹화 할 수 있는 좋은 방법.-->
<textarea
class="form-control"
type="text"
id="description"
name="campground[description]"
>
<%=campground.description%>
</textarea>
</div>
<div class="div mb-3">
<button class="btn btn-primary">Submit</button>
</div>
</form>
<a href="/campgrounds/<%=campground._id%>">Back to Campgrounds</a>
</div>
</div>
show.ejs
<% layout('layouts/boilerplate')%>
<div class="row">
<div class="col-6 offset-3">
<div class="card mb-3">
<img src="<%=campground.image%>" class="card-img-top" alt="..." />
<div class="card-body">
<h5 class="card-title"><%=campground.title%></h5>
<p class="card-text"><%=campground.description%></p>
</div>
<ul class="list-group list-group-flush">
<li class="list-group-item text-muted"><%=campground.location%></li>
<li class="list-group-item">$<%= campground.price%>/night</li>
</ul>
<div class="card-body">
<a
class="card-link btn btn-primary"
href="/campgrounds/<%=campground._id%>/edit"
>Edit</a
>
<form
class="d-inline"
action="/campgrounds/<%=campground._id%>?_method=DELETE"
method="POST"
>
<button class="btn btn-danger">Delete</button>
</form>
</div>
</div>
</div>
</div>