반응형
익스프레스 프로젝트 시작하기
서버를 제작하는 과정에서 겪게 되는 불편을 해소하고 편의 기능을 추가한 웹 서버 프레임워크
Express는 http 모듈의 요청과 응답 객체에 추가 기능을 부여했다. 또한, 코드를 분리하게 쉽게 만들어 관리하기 용이하다
- 초기 설정을 위해 package.json 과 app.js를 작성했다
- html 파일을 사용하기 전
- index.html 파일을 만들고 난 후 이다
- res.sendFile 이라는 명령어를 사용해 응답을 지정된 경로에 있는 파일로 보낼 수 있다
자주 사용하는 미들웨어
미들웨어(미들웨어가 익스프레스의 전부라고 해도 과언이 아니라는데 한번 느껴보겠다..)
- 요청과 응답의 중간에 위치하며, 요청과 응답을 조작해 기능을 추가하기도 하고, 나쁜 요청을 거른다
- app.use에 매게변수가 req, res, next인 함수를 넣으면 된다
- 미들웨어는 위에서부터 아래로 순서대로 실행되고, next라는 매게변수는 다음 미들웨어로 넘어가는 함수다
morgan
- morgan 연결 후 localhost:3000에 다시 접속해보면 기존 로그 외에 추가적인 로그를 볼 수 있다.
- 인수로 dev 외에 combined, common, short, tiny 등을 사용할 수 있다.
static
- static 미들웨어는 정적인 파일들을 제공하는 라우터 역할을 한다
- 서버의 폴더 경로와 요청 경로가 다르므로 외부인이 서버의 구조를 쉽게 파악할 수 없다 → 보안에 큰 도움
body-parser
- 요청의 본문에 있는 데이터를 해석해서 req.body 객체로 만들어주는 미들웨어
- 보통 폼 데이터나 AJAX 요청의 데이터를 처리한다.
- 폼 데이터: HTML 폼을 통해 수집된 데이터를 의미합니다.
- AJAX: 페이지를 새로 고치지 않고 서버와 비동기적으로 데이터를 주고 받을 수 있게 해주는 기술
cookie-parser
- 요청에 동봉된 쿠키를 해석해 req.cookies 객체로 만든다
- 옵션은 domain, expires, httpOnly, maxAge, path, secure 등이 있다.
express-session
- 로그인 등의 이유로 세션을 구현하거나 특정 사용자를 위한 데이터를 임시적으로 저장해둘 때 유용하다
- 인수로는 세션에 대한 설정을 받는다
- 일반적인 쿠키 옵션이 모두 제공되어 httpOnly를 true로 성정해 클라이언트에서 쿠키를 확인하지 못하게 하는 등 여러 설정을 할 수 있다.
미들웨어 특성 활용하기
- 미들웨어는 req, res, next를 매개변수로 갖는 함수(에러 처리 미들웨어만 예외적으로 err, req, res, next를 가진다)로서 app.use나 app.get, app.post 등으로 장착한다
- 동시에 여러 개의 미들웨어를 장착할 수도 있으며, 다음 미들웨어로 넘어가려면 next 함수를 호출해야 한다
- next함수에 인수를 넣으면 특수한 동작을 하게 된다.
- route라는 문자열을 넣으면 다음 라우터의 미들웨어로 바로 이동하고, 그 외의 인수를 넣으면 에러 처리 미들웨어로 이동한다.
- 미들웨어 간에 데이터를 전달하는 방법 - res.locals 객체에 데이터를 넣어 요청이 끝날때까지만 데이터를 유지한다. 세션을 사용하면 세션유지하는 동안 데이터도 유지가 된다는 단점이 있기 때문
- 미들웨어를 사용할때 유용한 패턴
- 미들웨어 안에 미들웨어를 넣는 방식
미들웨어 안에 미들웨어를 넣는 방식
app.use(morgan('dev'));
// 또는
app.use((req, res, next) => {
morgan('dev')(req, res, next);
});
app.use((req, res, next) => {
if (process.env.NODE_ENV === 'production') {
morgan('combined')(req, res, next);
} else {
morgan('dev')(req, res, next);
}
});
multer
- 이미지, 동영상 등을 비롯한 여러 가지 파일을 멀티파트 형식으로 업로드할 때 사용하는 미들웨어
- 멀티파트 형식: enctype이 mulipart/form-data인 폼을 통해 업로드하는 데이터의 형식
- 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);
done(null, path.basename(file.originalname, ext) + Date.now() + ext);
},
}),
limits: { fileSize: 5 * 1024 * 1024 },
});
- destination 함수: 어떤 이름으로 저장할지
- req: 요청에 대한 정보, file: 업로드한 파일의 정보, done: 함수
app.post('/upload', upload.single('image'), (req, res) => {
console.log(req.file, req.body);
res.send('ok');
});
- 파일을 하나만 업로드할 시 single 미들웨어를 사용 (이런식으로 업로드한다는 느낌)
app.post('/upload', upload.array('many'), (req, res) => {
console.log(req.files, req.body);
res.send('ok');
});
- 여러 파일을 업로드하는 경우 single -> array, image -> many
- html file 또한 input 태그에 multiple 사용
app.post('/upload', upload.none(), (req, res) => {
console.log(req.body);
res.send('ok');
});
- 파일을 업로드하지 않고 멀티파트 형식으로 업로드 간능
- multer를 수정해 로컬 환경에서 실행시켜보았다
Router 객체로 라우팅 분리하기
- 라우터를 만들때 요청 메소드와 주소별 분기 처리하느라 코드가 복잡함
- 익스프레스를 사용하는 이유 중 하나가 라우팅을 깔끔하게 관리할 수 있다는 점
- app.get 같은 메서드가 라우터 부분임
- routes 폴더를 만들고 index.js, user.js 작성
const indexRouter = require('./routes');
const userRoutes = require('./routes/user');
app.use('/', indexRouter);
app.use('/user', userRoutes);
//index.js
const express = require('express');
const router = express.Router();
// GET / 라우터
router.get('/', (req, res) => {
res.send('Hello, Express');
});
module.exports = router;
//user.js
const express = require('express');
const router = express.Router();
// GET /user 라우터
router.get('/', (req, res) => {
res.send('Hello, User');
});
module.exports = router;
- 라우터 주소에서 자주 쓰이는 패턴을 알아보자
// 라우트 매개변수
// 이 패턴을 사용할 시 일반 라우터보다 뒤에 위치해야한다.
router.get('/user/:id', (req, res) => {
console.log(req.params, req.query);
});
- 자주 사용하는 활용법 하나 더
router.get('/abc', (req, res) => {
res.send('GET /abc');
});
router.post('/abc', (req, res) => {
res.send('POST /abc');
});
// 관련있는 코드끼리 묶여 보기가 좋음
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 객체
- req.app: req 객체를 통해 app 객체에 접근할 수 있습니다. req.app.get('port')와 같은 식으로 사용할 수 있습니다.
- req.body: body-parser 미들웨어가 만드는 요청의 본문을 해석한 객체입니다.
- req.cookies: cookie-parser 미들웨어가 만드는 요청의 쿠키를 해석한 객체입니다.
- req.ip: 요청의 ip 주소가 담겨 있습니다.
- req.params: 라우트 매개변수에 대한 정보가 담긴 객체입니다.
- req.query: 쿼리스트링에 대한 정보가 담긴 객체입니다.
- req.signedCookies: 서명된 쿠키들은 req.cookies 대신 여기에 담겨 있습니다.
- req.get(헤더 이름): 헤더의 값을 가져오고 싶을 때 사용하는 메서드입니다. </aside>
res 객체
- res.app: req.app처럼 res 객체를 통해 app 객체에 접근할 수 있습니다.
- res.cookie(키, 값, 옵션): 쿠키를 설정하는 메서드입니다.
- res.clearCookie(키, 값, 옵션): 쿠키를 제거하는 메서드입니다.
- res.end(): 데이터 없이 응답을 보냅니다.
- res.json(JSON): JSON 형식의 응답을 보냅니다.
- res.locals: 하나의 요청 안에서 미들웨어 간에 데이터를 전달하고 싶을 때 사용하는 객체입니다.
- res.redirect(주소): 리다이렉트할 주소와 함께 응답을 보냅니다.
- res.render(뷰, 데이터): 다음 절에서 다룰 템플릿 엔진을 렌더링해서 응답할 때 사용하는 메서드입니다.
- res.send(데이터): 데이터와 함께 응답을 보냅니다. 데이터는 문자열일 수도, HTML일 수도, 버퍼일 수도, 객체나 배열일 수도 있습니다.
- res.sendFile(경로): 경로에 위치한 파일을 응답합니다.
- res.set(헤더, 값): 응답의 헤더를 설정합니다.
- res.status(코드): 응답 시의 HTTP 상태 코드를 지정합니다.
- req, res 객체의 메서드는 메서드 체이닝을 지원하는 경우가 많다
res
.status(201)
.cookie('test','test')
.redirect('/admin')
템플릿 엔진 사용하기
- HTML은 정적인 언어다. 주어진 기능만 사용할 수 있고, 사용자가 기능을 직접 추가할 수 없다.
- 템플릿 엔진은 js를 사용해 html을 렌더링할 수 있게 함.
- pug와 nunjucks에 대해 알아보자
템플릿 엔진 대신에 리액트, 뷰 쓰면 안되나요?
FE를 리액트나 뷰 등으로 제작한 뒤 노드 서버와 Restful한 방식으로 데이터를 주고받으면 된다.
이 책의 예제는 모두 넌적스로 되어 있지만, 리액트나 뷰를 별도로 공부해서 예제를 리액트나 뷰로 전환해보는 것도 좋은 경험이 될 것이다.
퍼그(제이드)
- HTML 표현
- 퍼그
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
- HTML
<!DOCTYPE html>
<html>
<head>
<title>익스프레스</title>
<link rel="stylesheet" href="/style.css" />
</head>
</html>
- 변수
- HTMl과 다르게 자바스크립트 변수를 템플릿에 렌더링할 수 있다.
- 반복문
- for 대신에 each를 사용해 반복문
- 조건문
- 조건문을 이용해 편리하게 분기 처리 가능
- include
- 다른 퍼그나 html 파일을 넣을 수 있다.
- extends와 block
- 레이아웃을 정하고, 공통되는 레이아웃 부분을 따로 관리할 수 있다
넌적스
- 퍼그의 HTML 문법 변화에 적응하기 힘든 사람에게 유용한 템플릿 엔진이다
- 변수
- res.render 호출 시 보내는 변수를 넌적스가 처리한다
- 반복문
- 넌적스에서는 특수한 문을 {%%}안에 쓴다. 반복문도 이 안에 for in문과 endfor사이에 위치한다.
- index를 사용하고싶다면 loop.index라는 변수를 사용하자
- 조건문
- {% if 변수 %}, {% elif %}, {% else %}, {% endif %}로 이뤄져있다.
- Include
- 다른 html 파일을 넣을 수 있다.
- extends와 block
- 레이아웃을 정하며, 공통되는 레이아웃을 따로 관리할 수 있다.
- 페이지마다 달라지는 부분을 block으로 비워 사용한다.
에러 처리 미들웨어
- 404응답 미들웨어와 에러 처리 미들웨어를 수정해 error.html에 에러 내용을 적어 사용한다
- 에러 처리 미들웨어는 error라는 템플릿 파일을 렌더링한다.
//error.html
app.use((req, res, next) => {
const error = new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
error.status = 404;
next(error);
});
app.use((err, req, res, next) => {
res.locals.message = err.message;
res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
res.status(err.status || 500);
res.render('error');
함께 보면 좋은 자료
- morgan: **https://github.com/expressjs/morgan**
- body-parser: **https://github.com/expressjs/body-parser**
- cookie-parser: **https://github.com/expressjs/cookie-parser**
- static: **https://github.com/expressjs/serve-static**
- express-session: **https://github.com/expressjs/session**
- multer: **https://github.com/expressjs/multer**
- dotenv: **https://github.com/motdotla/dotenv**
반응형
'WINK-(Web & App) > Express.js (Node.js) 스터디' 카테고리의 다른 글
[2024-2 Node.js 스터디] 류상우 #3주차 (0) | 2024.11.04 |
---|---|
[2024-2 Node.js 스터디] 류상우 #2주차 (2) | 2024.10.14 |
[2024-2 Node.js 스터디] 김민재 #2주차 - HTTP 모듈로 서버 만들기 (4) | 2024.10.12 |
[2024-2 Node.js 스터디] 류상우 #1주차 (0) | 2024.10.07 |
[2024-2 Node.js 스터디] 김민재 #1주차 (0) | 2024.10.06 |