익스프레스는 최소한의 프레임워크를 제공한다.-> 필요한 것만 추가하면 됨
익스프레스가 하는 일은 단순하다. 익스프레스는 클라이언트(브라우저, 모바일기기, 다른 서버, 데스크탑 애플리케이션 등 HTTP를 사용하는 모든 것)의 HTTP 요청을 받고, HTTP 응답을 반환. 이는 인터넷에 연결된 모든 것들이 하는 기본 패턴이기 때문에 익스프레스는 유용하게 동작한다.
정확히는 웹 애플리케이션 프레임워크의 서버부분. 흔히 말하는 웹 애플리케이션 프레임워크는 리액트, 뷰, 앵귤러 등 단일 페이지 애플리케이션 프레임워크를 생각할 수 있다. 하지만 대부분의 웹 앱들은 다른 서비스와 데이터를 공유하고 통합되어야하는데, 이런 과정은 일반적으로 웹 API, 웹 애플리케이션 프레임워크의 서버사이드 구성요소를 통해서 진행된다.
: 애플리케이션의 페이지를 서버에서 HTML, CSS, 이미지, 멀티미디어 자원, JS 등을 결합 (렌더링)하여 클라이언트에 전송하는 것.
: 사용자 인터페이스를 클라이언트에서 렌더링한다. 즉 일단 브라우저가 초기 HTML을 받고 JS를 이용해 DOM을 동적으로 수정하기 때문에 새 페이지를 표시할 때 서버에 의존하지 않는다.
페이지 전체를 서버에서 보내는지, 아니면 클라이언트에서 동적으로 렌더링 하는지 차이
노드는 자바스크립트를 브라우저에서 독립시켜 서버에서 실행되게 만들고, 자바스크립트로 작성한 프레임워크를 사용할 수 있게 만들었다. 노드와 밀접한 데이터 베이스들이 다수 존재하는데, 이 중 NoSQL 데이베이스라는 새로운 접근법이 생겼다. NoSQL 데이터베이스 중 선도적인 것은 몽고DB
웹사이트 제작을 위해서는 여러가지 기술을 조합해야한다. 이러한 조합을 "스택"이라고 한다.
npm은 노드 패키지를 위한 패키지 매니저를 말한다.
패키지 매니저는 패키지를 설치하고 의존성을 관리하는 역할 수행 (yarn 또한 패키지 매니저)
스캐폴딩(scaffolding), 발판.
대부분의 프로젝트는 뼈대가 되는 보일러플레이트 코드가 필요한데, 이 코드를 매번 작성하지 않고 뼈대(템플릿)을 미리 만들어두고 복붙하여 사용하면 된다.
익스프레스는 프로젝트 시작 시 스캐폴딩을 생성하는 유틸리티를 제공함
express-generator 참고
const express = require('express')
const app = express()
const port = process.env.PORT || 3000
app.get('/', (req, res) => {
res.type('text/plain')
res.send('Meadowlark Travel')
})
app.get('/about', (req, res) => {
res.type('text/plain')
res.send('About Meadowlark Travel')
})
// custom 404 page
app.use((req, res) => {
res.type('text/plain')
res.status(404)
res.send('404 - Not Found')
})
// custom 500 page
app.use((err, req, res, next) => {
console.error(err.message)
res.type('text/plain')
res.status(500)
res.send('500 - Server Error')
})
app.listen(port, () => console.log(
`Express started on http://localhost:${port}; ` +
`press Ctrl-C to terminate.`))
app.use
: 미들웨어 관련 메서드. 위 코드에서는 일족의 폴백 핸들러로 동작한다.app.get
: 라우트 추가 메서드익스프레스에서는 라우트와 미들웨어의 순서가 중요하다!!
만약 404 핸들러를 라우트보다 먼저 작성하면 홈페이지와 어바웃 페이지 동작 없이 무조건 404 페이지로 연결된다.
만약 라우트에 와일드카드를 사용하게 되면 순서 문제가 발생할 수 있다.
app.get('/about*', (req, res) => {
// ...
})
app.get('/about/contact', (req, res) => {
// ...
})
app.get('/about/directions', (req, res) => {
// ...
})
위 코드의 '/about/contact'
, '/about/directions'
는 사용되지 않음
뷰는 사용자가 보는 것을 담당하는 부분. 뷰는 이미지나 CSS 파일 같은 정적 자원과는 다르다. 뷰는 정적일 필요가 없고, HTML 역시 각 요청에 따라 동적으로 변경될 수 있다.
익스프레스는 다양한 뷰 엔진을 제공한다. 그 중에서 핸들바라는 템플릿 프레임워크는 HTML 자체를 변경하지는 않고, 특수 태그를 사용하면 핸들바가 그 태그에 콘텐츠를 삽입하는 방식으로 동작한다.
npm i express-handlebars
설치 후 meadowlark.js 파일 수정하고 사이트에 사용할 템플릿 생성하기
const express = require('express')
const expressHandlebars = require('express-handlebars')
const app = express()
app.engine('handlebars', expressHandlebars({
defaultLayout: 'main', // 기본 레이아웃을 main으로 선언
}))
app.set('view engine', 'handlebars')
app.use(express.static(__dirname + '/public'))
const port = process.env.PORT || 3000
app.get('/', (req, res) => res.render('home'))
app.get('/about', (req, res) => res.render('about'))
// custom 404 page
app.use((req, res) => {
res.status(404)
res.render('404')
})
// custom 500 page
app.use((err, req, res, next) => {
console.error(err.message)
res.status(500)
res.render('500')
})
app.listen(port, () => console.log(
`Express started on http://localhost:${port}; ` +
`press Ctrl-C to terminate.`))
defaultLayout: 'main'
: main 템플릿이 모든 뷰의 레이아웃이 된다.<!doctype html>
<html>
<head>
<title>Meadowlark Travel</title>
</head>
<body>
<header>
<img src="/img/logo.png" alt="Meadowlark Travel Logo">
</header>
{{{body}}}
</body>
</html>
익스프레스는 미들웨어를 사용해 정적 파일과 뷰를 처리한다. 미들웨어를 통해 기능을 모듈화하여 요청을 쉽게 처리할 수 있게 된다.
static
미들웨어static
미들웨어는 하나 이상의 디렉터리를 지정하여 해당 디렉터리에 정적 자원을 보관하고 이를 클라이언트에 전송한다. 이 디렉터리에 이미지, CSS 파일, 클라이언트 사이드 JS 파일을 넣는다.
전송하려는 정적 파일 각각에 파일을 렌더링하고 클라이언트에 반환하는 라우트를 지정한 효과
// 생략
app.get('/', (req, res) => res.render('home'))
const fortunes = [
"Conquer your fears or they will conquer you.",
"Rivers need springs.",
"Do not fear what you don't know.",
"You will have a pleasant surprise.",
"Whenever possible, keep it simple.",
]
app.get('/about', (req, res) => {
const randomFortune = fortunes[Math.floor(Math.random()*fortunes.length)]
// 동적인 정보를 뷰로 전송한다
res.render('about', { fortune: randomFortune })
})
// ...
res.render
메소드에 매개변수로 객체를 넘겨주면 해당 페이지로 데이터를 전송한다.