6장 익스프레스
6.1 익스프레스 프로젝트 시작하기
1. http 모듈로 웹 서버를 만들 때 코드가 보기 좋지 않고, 확장성도 떨어짐
- 프레임워크로 해결
- 데표적인 것이 Express, koa, hapi
- 코드 관리도 용이하고 편의성이 많이 높아짐
- npmtrends에서 다운로드수 많은 것 이 안전, 업데이트 날짜로 최근에 활동있는 코드, git허브에서도 최근활동 있는 코드
2. package.json 만들기
- 직접 만들거나 npm init 명령어 생성
- nodemone이 소스 코드 변경 시 서버를 재시작해줌
3. app.js 작성하기
- 서버 구동의 핵심이 되는 파일
- app.set('port' 포트)로 서버가 실행될 포트 지정
- app.get('주소', 라우터)로 GET 요청이 올 때 어떤 동작을 할지 지정
- app.listen('포트', 콜백)으로 몇 번 포트에서 서버를 실행할지 지정
const express = require('express');
const app = espress();
app.get('/', (req, res) => {
res.send('hello express');
});
app.listen(3000, () => {
console.log('익스프레스 서버 실행');
연습
powershell로 하지말긔 command prompt로 바꿔서 테스트하기
nodemon 통해서 하면 자동으로 업데이트해줌. (npm i -D nodemon)
const express = require('express');
const path = require('path');
const app = express();
app.set('port', process.env.PORT || 3000);
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.get('/', (req, res) => {
res.send('hello, Express');
});
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기중');
});
require 은 외부 패키지 가져오는것.
라우터들에 공통적으로 넣고싶은 내용이 있으면 미들웨어를 사용하자
app.use(req, res,next) => {
console.log('모두 요청에 실행하고싶어요');
next();
});
미들 웨어에 next를 넣어주지 않으면 미들웨어에서 실행이 멈춘다.
익스프레스는 위에서 아래로 차례로 실행되서 그렇다.
와일드 카드라는것도 있다 (정확히는 라우트 매개변수 req.params)
app.get('/:category/:name', (req, res) => {
res.send('hello ${req.params.name}');
});
위 처럼 하면 name에 들어가는것이 params.name에 들어간다.
와일드 카드는 대부분 다른 미들웨어, 라우터들보다 밑에 넣는다
app.get('*', (req, res) => {
});
*는 알다시피 모든 이름이다 이게 제일 밑에 와야한다.
에러 발생
에러 처리 또한 중요하다.
app.use((req, res, next) => {
console.log('실행');
next();
}, (req, res, next) => {
throw new Error('에러가 났어요');
});
익스프레스는 에러가나면 알아서 처리하고 에러 정보를 보여준다. 하지만 대부분 에러처리는 따로 해줘야한다.
에러 미들웨어는 라우터들 밑에 써줘야한다.에러 미들웨어 만들떈 next까지 4개의 매개변수 다 넣어야한다
에러처리는 저렇게 throw new Error 처럼 대놓고 하지 않고
try{
} catch(error){
next(error);
}같이 처리 next에 인수가 있으면 그 인수 라우터로 이동. error므로 에러 미들웨어로 이동
app.use((req, res, next) => {
res.status(404).send('에러 미들웨어는 아지고 404 처리미들웨어지렁');
})
app.use((err, req, res, next) => {
cponsole.error(err);
res.send('에러났지롱, 근데 안알려줄거지롱');
})
에러 표시도 status(숫자)처럼 바꿀수있다. 해커들에게 힌트가 될수 있어서 그대로 보여주지않고 바꿔서 보여준다. 대부분 200번대 4,500번대는 조심해서 쓰자. 400번대는 404로 퉁치기도 한다.
라우터에서 send 류( ex send, sendfile, json 등)이 두번이상 나오면 에러다. 응답은 한번만 쓸 수 있음.
res.json 쓴다고 return 되는것이 아니다. return은 다로 해줘야한다.
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ hello: 'taehee'}));
//위랑 아래랑 같다. 위에 https, 아래는 express
res.json({ hello: 'taehee'});
next('route')를 하면 같은 라우터안에서 찾지않고 다음 라우터 부터 찾는다. next()는 같은 라우터안에서 부터 찾는다. 그차이.
morgan을 npm 통해서 다운받고
app.use(morgan('dev'));
를 하면 터미널에 정보를 받을수 있다.
app.use(morgan('combined'));
를 쓰면 더 자세한정보를 받을 수 있다. 이건 배포할떄 많이쓴다.
cookie-paser을 npm 통해서 다운받으면 쿠키를 쉽게 사용 가능.
const cookieParser = require('cookie-parser');
const app = express();
app.set('port', process.env.PORT || 3000);
app.use(cookieParser());
app.get('/', (req, res, next) => {
req.cookies
res.cookie('name', encodeURIComponent('name'),{
expires: new Data(),
httpOnly: true,
path: '/',
})
})
appuse(cookieParser('어쩌구저쩌구'));
app.get('/', (req, res, next) => {
req.signedCookies;
~~~~
}
위처럼 하면 암호화
바디파서는 express안에 포함되어서
app.use(express.json()); //form 파싱
app.use(express.urlencoded({ extended: true }));//true면 qs, false면 querystring, true 써라
req.body~
와 같이 사용가능
정작 파일 은 static
app.use('요청 경로', express.static('실제 경로'));
localhost:3000/zerocho.html ch6/public-3030/zerocho.html
localhost:3000/zerocho.css ch6/public-3030/zerocho.css
app.use('/', express.static(__dirname, 'public'));
이렇게 하면 보안적으로 좋다. 저 미들웨어 쓸떄는 순서도 중요하다 static 이 실행되면 뒤에 미들웨어는 실행이 안되므로 위치가 중요하다. 모건 뒤에쯤이 좋다. 쿠키랑 세션이 위로 가는 경우는 로그인하는 경우에는 쓰기도한다.
express-session
app.use(session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
name: 'session-cookie', //기본값은 connect.sid
}));
요청마다 개인의 저장공간을 준다.
1.5 버전부턴 쿠키파서와 순서가 상관없어졌지만 보통 뒤에 놓는다.
express-session은 인수로 세션에 대한 설정을 받는다.
resave는 요청이 올 떄 세션에 수정 사항이 생기지 않더라도 세션을 다시 ㅅ저장할지 설정하는 것이고,
saveUninitialized는 세션에 저장할 내역이 없더라도 처음부터 세션을 생성할지 설정하는것입니다. 현재는 둘다 필요없으니 false
express-session은 세션 관리시 클라이언트에 쿠키를 보냅니다. 4.3절에서 배운 세션쿠키가 이것입니다. 안전하게 쿠키를 전송하려면 쿠리에 서명을 추가해야하고, 쿠키를 서명하는데 secret의 값이 필요합니다. cookie-parser의 secret과 같게 설정하는 것이 좋습니다. 세션 쿠키의 이름은 name옵션으로 설정합니다. 기본값은 connect.sid입니다.
cookie옵션은 세션 쿠키에 대한 설정입니다. maxAge, domain, path, expires, sameSite, httpOnly, secure등 일반적인 쿠키 옵션이 모두 제공 됩니다.
현재 httpOnly, 를 true로 설정해 클라이언트서 쿠키를확인하지 못하도록 했고, secure는 false로 해서 http가 아닌 환경에서도 사용할수있게 했습니다. 배포시 https를 적용하고 secure도 true로 설정하는것이 좋습니다.
store이라는 옵션도 있습니다. 현재는 메모리에 세션을 저장하도록 되어 있습니다. 문제는 서버가 재시작하면 메모리가 초기화되어 세션이 모두 사라진다는 것입니다. 따라서 배포 시에는 store에 데이터베이스를 연결하여 세션을 유지하는 것이 좋습니다. 보통 레디스가 자주 쓰입니다. 레디스는 15,1,8절에서 배웁니다.
req.session.name = 'zerocho';//세션 등록
req.sessionID; //세션 아이디 확인
req.session.destroy(); // 세션 모두 제거
express-session으로 만들어진 req.session 객체에 값을 대입하거나 삭제하여 세션을 변경할 수 있습니다. 나중에 세션을 한 번에 삭제하려면 req.session.destroy 메서드를 호출합니다. 현재 세션의 아이디는 req.sessionID로 확인할 수 있습니다. 세션을 강제로 저장하기 위해 req.session.save 메서드가 존재하지만, 일반적으로 요처이 끝날 때 자동으로 호출되므로 직접 호출할일은 거의 없습니다.
요청 1번에 1회성으로 라우터간에 데이터를 공유 하고 싶으면 req.data에 저장하라. req들은 같은 req고 모든 요청이 끝나면 req.data는 정리된다.
나 한정으로 그 data를 유지시키고 싶으면 req.session에 저장하라
로그인한 사람에게만 static을 실행시키고 싶으면
(미들웨어 확장법)
app.use('/', (req, res, next) => {
if(req.session.id) {
express.static(__dirname, 'public')(req, res, next)
} else {
next();
}
});
미들웨어 특성 활용하기
미들웨어를 직접 만들어보기도 했고, 다른사람이 만든 미들웨어 패키지를 설치해 장착해보기도 했다. 총정리 해보자
app.use((req, res, next) => {
console.log('모든 요청에 다 실행됩니다.');
next();
});
미들 웨어는 req, res, next를 매개변수로 가지는 함수로써, app.use나 ap.get, app.post등으로 장착합니다. 특ㄹ정한 주소의 요청에만 미들웨어가 실행되게 하려면 첫번째 인수로 주소를 넣으면 됩니다.
app.use(
morgan('dev'),
express.static('/', path.join(__dirname, 'public')),
express.urlencoded({ extended: false }),
cookieParser(process.env.COOKIE_SECRET),
);
위와 같이 동시에 여려 개의 미들에어를 장착할 수도 있스며, 다음 미들웨어로 넘기려면 next함수를 호출해야합니다. 위 미들웨어들은 내부적으로 next를 호출하고 있으므로 연달아 쓸 수 있습니다.
next를 호출하지 않는 미들웨어는 res.send나 res.sendFIle등의 메서드로 응답을 보내야합니다. express.static과 같은 미들웨어는 정적파일을 제공할때 next대신 res.sendFile메서드로 응답을 보냅니다. 따라서 정적 파일을 제공하는 경우 express.json, express.ur;encode, cookieParser 미들웨어는 실행되지 않습니다. 미들웨어 장착 순서에 따라 어떤 미들웨어는 실행되지 않을 수도 있다는 것을 기억해 둡시다.
만약 nexgt도 호출하지 않고 응답도 보내지 않으면 클라이언트는 응답을 받지 못해 계속 기다립니다.
next() 다음 미들웨어로
next('route') 다음 라우터로
next(error) 에러 행들러로
multer
이번에는 사용하는 방법이 다소 어려운 미들웨어를 알아보겠습니다. 이미지, 동영상 등을 비롯한 여러가지 파일들을 멀티파트 형식으로 업로드 할 때 사용하는 미들웨어 입니다. 멀티파트 형식이란 다음과 같이 enctype이 multipart/form-data인 폼을 통해 업로드하는 데이타 형식을 의미합니다.
다음과 같은 multipart.html이 있다면 멀티파트 형식으로 데이터를 업로드 할 수 있습니다. 아직서버 쪽 라우터를 만둘지 않았으므로 예제가 실행되지는 않습니다.
multipart.html
<form action="/upload" method="post" enctype="multipart/form-data>
<input type="file" name="image" />
<input type="text" name="title" />
<button type="submit">업로드</button>
</form>
멀티파트 형식으로 업로드하는 데이터는 개발자 도구 Network 탭에서 보인다. 이미지 하나를 선태갛고 title 인풋에 제목이라고 적어서 업로드하면 데이터가 전송됩니다
이러한 폼을 통해 업도르하는 파일은 body-parser로는 처리할 수 없고 직접 파싱하기도 어려우므로 multer라는 미들웨어를 따로 사용하면 편리합니다.
multer에는 여러 미들웨어가 들어있습니다.
const multer = require('multer');
const upload = multer({
storage: multer.diskStorage({
destination(req, file, done) {
done(null, 'uploads/');
},
filename(req, file, done) {
const ext = path.extname(file.originalname);
doen(null, path.basename(file.originalname, ext) + date.now() + ext);
},
}),
limits: { fileSize: 5 * 1024 * 1024 },
});
multer 함수의 인자로 설정을 넣습니다. storage 속성에는 어디에(destination) 어던 이름으로(filename) 저장할지 넣습니다.
destination과 filename 함수의 req 매개변수는 요청에 대한 정보가, file 객체에는 업로드한 파일에 대한 정보가 있습니다. done 매개변수는 함수입니다.
첫 번째 인수에는 에러가 있다면 에러를 넣고, 두 번째 인수에는 실제 경로나 파일 이름을 넣어주면됩니다. req나 file의 데이터를 가공해서 done으로 넘기는 형식입니다
현재 설정으로는 uploads라는 폴더에 [파일명 + 현재시간.확장자] 파일명으로 업로드하고 있습니다. 현재시간을 넣어주는 이유는 업로드하는 파일명이 겹치는 것을 막기 위함입니다.
limits 속성에는 업로드에 대한 제산 사항을 설정할 수 있습니다. 파일 사이즈는 5mb로 제한해 두었습니다
다만 위 설정을 실제로 활용하기 위해서는 서버에 uploads 폴도가 꼭 존재해야합니다. 없다면 직접 만들어주거나 다음과 같이 fs모듈을 사용해서 서버를 시작할 때 생성합니다.
const fs = require('fs');
try{
fs.readdirSync('uploads');
} catch (error) {
console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.');
fs.mkdirSync('uploads');
}
설정이 끝나면 upload 변수가 생기는데, 여기서 다양한 종류의 미들웨어가 들어 있씁니다. 먼저 파일 하나만 업로드 하는 경우 (multipart.html 과 같은경우) 에는 single 미드웨어를 사용합니다.
app.post('/upload', upload.single('image'), (req, res)_=> {
console.log(req.file, req.body);
res.send('ok');
}):
single 미들웨어를 라우터 미들웨어 앞에 넣어두면, multer설정에 다라 파일 업로드 후 req.file객체가 생성됩니다. 인수는 input 태그의 name이나 폼 데이터의 키와 일치하게 넣으면 됩니다.
업로드 성공시 결과는 req.file 객체 안에 들어있습니다. req.body에는 파일이 아닌 데이터인 title이 들어 있습니다.
여려 파일을 업로드 하는 경우 HTML의 input 태그에는 multiple을 쓰면됩니다.
미들웨어는 single대신 array로 교체합니다.
app.post('/upload', upload.array('many'), (req, res) => {
console.log(req.files, req.body);
res.sned('ok');
});
업로드 결과도 req.file 대신 req files 배열에 들어 있습니다.
파일을 여러개로 업로드 하지만 input 태그나 폼 데이터의 키가 다른경우에는 fileds 미들에어를 사용합니다.
fields 미들웨어의 인수로 input 태그의 name을 각각 적습니다.
app.post('/upload',
uload.fields([{ name: 'image1' }, {name: 'image2' }]),
(req, res) => {
console.log(req.files, req.body);
req.send('ok');
},
);
업로드 결과도 req.files.image1, req.files.image2에 각각 들어있습니다.
특수한 경우지만 파일을 업로드 하지 않고도 멀티파트 형식으로 업로드 하는 경우가 있습니다
이럴땐 none 미들웨어를 사용합니다
app.post('/upload', upload.non(), (req, res) => {
console.log(req.body);
res.send('ok');
});
파일을 업로드 하지 않으므로 body만 존재합니다.
Router객체로 라우팅 분리하기
4.2절에서 라우터를 만들 때는 요천 메서드와 주소별로 분기처리에 코드가 매우 복잡했습니다.
익스프레스에서는 라우터를 분리할 수 있는 방법을 제공합니다.
routes/index.js
const router = express.Router();
//GET/라우터
router.get('/', (req, res) => {
res.sned('Hello, Express');
});
module.exports = router;
routes/user.js
const express = require('express');
const router = express.Router();
//GET/라우터
router.get('/', (req, res) => {
res.sned('Hello, user');
});
module.exports = router;
만들었던 index.jx와 user.js를 app.use를 통해 app.js에서 연결합니다. 또한, 에러 처리 미들웨어 위에 404 상태 코드를 응답하는 미ㅡㄷㄹ웨어를 하나 추가합니다
app.js
...
const path = reqiore('path');
dotenv.config();
const indexRouter = require('./routes');
const userRouter = require('./routes/user');
...
name: 'session-cookie';
}));
app.use('/', indexRouter);
app.use('/user'm userRouter);
app.use((req, res, next) => {
res.status(404).send('Not Found');
});
app.use((err, req, res, next) =>{
...
./routes/index.js는 ./routes로 생략 가능.
app.use를 통해 indexRouter은 / 와 /가 합쳐서 GET/라우터가 되고
userRouter은 use의 /user와 get의 /가 합져 GET/user가 되었다.
next를 사용하면 다음 라우터로 넘어ㄴ다고 했다. 바로 next('router'이며 라우터에 연결된 나머지 미들웨어들을 건너뛰고 싶을때 사용합니다.
router.get('/', function(req, res, next) {
next('route');
}, function(req, res, next) {
console.log('실행되지 않습니다.');
next();
}, function(req, res, next) {
console.log('실행되지 않습니다.');
next();
});
router.get('/', function(req, res) {
console.log('실행됩니다.');
res.send('hello, express');
});
위 주소처럼 같은 주소의 라우터를 여러개 만들어도 됩니다. 라우터가 몇개든 next()를 호출하면 다음 미들웨어가 실행됩니다.
tip. 라우터 주소에는 정수표현식을 비롯한 특수 패턴을 사용할 수 있습니다. 라우트 매개변수라고 불리는 패턴입니다.
router.get('/user/:id', funciton(req, res) {
console.log(req.params, req.query);
});
주소에 :id는 이부분에 다른 값을 넣을 수 있습니다. /user/123등의 요청도 이 라우터가 처리하게 됩니다
이 방식의 장점은 :id에 해당하는 1이나 123을 조회할 수 있다는 점이며, req.params 객체 안에 들어있습니다.
:id면 req.params.id, :type이면 req.params.type 으로 조회할 수 있습니다.
단, 이패턴을 사용할 때 주의 해야할 점은 일반 라우터 보다 뒤에 위치해야 한다는 것입니다.
router.get('/abs', (req, res) => {
res.send('GET/abd');
});
router.post('/abs', (req, res) => {
res.send('post/abd');
});
위 라우터들을
router.route('/abc')
.get((req, res) => {
res.send('GET/abc');
})
.post((req,res) => {
res.send('POST/abc');
});
로 묶음 가능
REQ, RES 객체 살펴보기
익스프레스의 req, res객체는 http 모듈의 req, res 객체를 확장한 것입니다.
- req.app : req 객체를 통해 app 객체에 접근할 수 있습니다. req.app.get('port') 같은 식으로사용할 수 있습니다.
- req.body : body-parser 미들웨어가 만드는 요청의 본문을 해석한 객체입니다.
- req.cookies : cookie-parser 미들웨어가 만드느 요청의 쿠키를 해석하는 객체입니다.
- req.ip : 요청의 ip 주소가 담겨 있습니다.
- req.parms : 라우트 매개변수에 대한 정보가 담긴 객체입니다.
- req.query : 퀴리스트링에 대한 정보가 담긴 객체입니다.
- req.signedCookies : 서명된 쿠키들은 req.cookies대신 여기에 담겨 있습니다.
- req.get(헤더 이름): 헤더의 값을 가져오고 싶을 떄 사용하는 메서드입니다.
- res.app : req.app처럼 res 객체를 통해 app 객체에 접근할 수 있습니다.
- res.cookie(키, 값, 옵션) : 쿠키를 설정하는 메서드입니다.
- res.clear(키, 값, 옵션) : 쿠키를 제거하는 메서드입니다.
- res.end() : 데이터 없이 응답을 보냅니다.
- res.json(JSON) : JSON 형식의 응답을 보냅니다.
- res.redirect(주소) : 리다이렉트할 주소와 함께 응답을 보냅니다.
- res.render(뷰, 데이터) : 다음 절에서 다룰 템플릿 엔진을 렌더링해서 응답할 대 사용하는 메서드입니다.
- res.send(데이터) : 데이터와 함꼐 응답을 보냅니다. 데이터는 문자열일수도 있고 HTML일 수도 있으며, 버퍼일 수도 있고 객체나 배열일수도 있습니다.
- res.sendFile(경로) : 경로에 위치한 파일을 응답합니다.
- res.set(헤더, 값) : 응담의 헤더를 설정합니다.
- res.status(코드) : 응답 시의 HTTP 상태 코드를 지정합니다.
메서드 체이닝
res
.status(201)
.cookie('test', 'test')
.redirect('/admin');
템플릿 엔진 사용하기
템플린 엔진은 자바스크립트를 사용하여 HTML을 렌더링할 수 있게 해줍니다. 따라서 기존 HTML 문법과 조금 달라지고 자바스크립트 문법이 들어가기도 합니다.
퍼그(제이드)
예전 이름인 제이드로 더 유명한 퍼그는 꾸준한 인기를 얻고 있습니다. 단, HTML과는 문법이 많이 달라 호불호가 갈립니다.
npm i pug로 설치합니다.
익스프레스와 연결하려면 app.js에 다음 부분이 들어 있어야 합니다.
app.js
...
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(morgan('dev'));
...
views는 템플릿 파일들이 위치한 폴더를 지정하는 것입니다. res.render 메서드가 이 폴더 기준으로 템플릿 엔진을 찾아서 렌더링 합니다.
res.render('index')라면 views/index.pug를 랜더링 합니다. res.render('admin/main') 이라면 views/admin/main.pug 를 렌더링합니다.
html 표현
기존 HTML과 다르게 화살괄화 <>가 없습니다. 탭 또는 스페이스로만 태그의 부모 자식 관계를 규명합니다. 탭 한 번, 스페이스 두번 또는 스페이스 네번 모두 상관없습니다.
모든 파일에 동일한 종류의 들여쓰기를 적용하면 됩니다. 자식 태그는 부모 태그보다 들여쓰기 되어 있어야 합니다. 들여쓰기에 오류가 있으면 제대로 렌더링 되지 않습니다.
doctype html은 과 같습니다. html, head,tile 태그에서 자식 태그일수록 한단계씩 더 들여쓰기 되어 있는 모습을 볼 수 있습니다. title = title 부분은 6.5.1.2. 절에서 다룹니다.
괄호가 없으면 태그 속성도 조금 다르게 표현합니다. 태그명 뒤에 소괄호로 묶어 젂습니다.
변수
HTML 과 다르게 자바스크럽트 변수를 템플릿에 렌더링할 수 있습니다. res.render 호출 시 보내는 변수를 퍼그가 처리합니다. routes/index.js의 코드를 보면 다음 부분이 있습니다.
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
res.render(템플릿, 변수 객체)는 익스프레스가 res 객체에 추가한 템플릿 렌더링을 위한 메서드입니다.
index.pug를 HTML로 렌더링하면서 { title: 'Express' } 라는 객체를 변수로 집어넣습니다. layout.pug와 index.pug의 title 부분이 모두 Express로 치환됩니다. 즉 HTML에도 변수를 사용할 수 있게 된 셈입니다.
res.render 메서드에 두번째 인수로 변수 객체를 넣는 대신, res.locals 객체를 사용해서 변수를 넣을 수도 있습니다.
router.get('/', function(req, res, next) {
res.local.title = 'Express';
res.render('index');
});
위와 같이 하면 템플릿 엔진이 res.locals 객체를 읽어서 변수를 집어 넣습니다. 이 방식의 장점은 현재 라우터뿐만 아니라 다른 미들웨어에서도 res.local 객체에 접근할 수 있다는 것입니다.
따라서 다른 미들웨어에서 템플릿 엔진용 변수를 미리 넣을수 이습니다.
서버로부터 받은 변수는 다양한 방식으로 퍼그에서 사용할 수 있습니다. 변수를 텍스트로 사용하고 싶다면 태그 위에 =을 붙인 후 변수를 입력합니다. 속성에도 =을 붙인 후 변수를 사용할 수 있습니다. 텍스트 중간에 변수를 넣으려면 #{변수}를 사용하면됩니다.
그러면 변가 그자리에 들어갑니다. #{}의 내부와 = 기호 뒷부분은 자바스크립트로 해석하므로 input 태그의 경우처럼 자라스크립트 구문을 써도 됩니다.
서버에서 데이터를 클라이언트로 내려보낼 때 #{}와 = 을 매우 빈번하게 사용합니다.
내부에 직접 변수를 선언할 수도 있습니다. 빼기(-)를 먼저 입력하면 뒤에 자바스크립트 구문을 작성할 수 있습니다. 여기에 변수를 선연하면 다음 줄부터 해당 변수를 사용 할 수 있습니다.
퍼그는 기본적으로 변수의 특수 문자를 HTML 엔티티로 이스케이프(문법과 관련없는 문자로 바꾸는 행위) 합니다. 이스케이프를 원하지 않는다면 = 대신 !=을 사용하면 됩니다.
반복문
HTML과 다르게 반복문도 사용할 수 있으며, 반복 가능한 변수인 경우에만 해당됩니다. each, for
조건문
조건문으로 편리하게 분기 처리할 수 있습니다. if, else if, else 를 사용할 수 있습니다.
include
다른 퍼그나 HTML 파일을 넣을 수 있습니다.
헤더나 푸터, 내비게이션 처럼 웹 제작 시 공통되는 부분을 따로 관리할 수 있어 매 페이지마다 동일한 HTML을 넣어야하는 번거러움을 없앱니다.
include 파일경로 로 사용
extends와 block
레이아웃을 정할 수 있습니다. 공통된 레이아웃 부분을 따로 관리할 수 있어 좋습니다. include와 함께 사용되곤 합니다.
레이아웃이 될 파일에는 공통된 마크업을 넣되, 페이지마다 달라지는 부분을 block으로 비워둡니다. block은 여러개 만들어도 됩니다.
block [블록명]으로 선언합니다.
block 이 되는 파일에서는 extends 키워드로 레이아웃 파일을 지정하고 block 부분을 넣습니다. block 선언보다 한 단계 더 들여쓰기 되어 있어야 합니다. 나중에 익스프레스에서 res.render('body')를 사용해 하나의 HTML로 합쳐 렌더링 할 수 있습니다
퍼그확장자는 생략 가능, block부분은 서로 합칩니다.
넌적스
넌적스는 퍼그의 HTML 문법 변화에 적응하기 힘든 분에 적합한 템플릿 엔진이며, 파이어폭스를 만든 모질라에서 만들었습니다. hTML문법 그대로 사용하되 추가로 자바스크립트 문법을 사용할 수 있고, 파이썬 템플릿 엔진인 twig와 문법이 상당히 유사합니다.
Author And Source
이 문제에 관하여(6장 익스프레스), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@neu5563/6장-익스프레스저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)