framework (공통적인 일은 프레임워크가 제작해줌 : 반제품)
Express : NodeJS에서 가장 보편적으로 사용되는 프레임워크
npm install express --save : express 설치 (node-modules 안에 express가 추가됨)
const express = require('express') const app = express() const port = 3000
app.get('/', (req, res) => { res.send('Hello World!') })
app.listen(port, () => { console.log(Example app listening on port ${port}) })
-> 간단하게 서버 실행
response.writeHead(200); response.end(html);
→ response.send(html);
로 한번에 처리
→ response.redirect('넘어갈 path');
시멘틱 URL-> 주소에 쿼리스트링을 보통 숨김(/page/HTML) 여기서 가져옴
/page를 패스로 설정, /HTML을 콜백함수 안에서 가지고옴
app.get('/page/:pageId', function(request, response){ response.send(request.params); });
패스 : /page/:pageId
-> /page/1 로 주소를 검색할 때 request.params = {pageId : 1}; 로 받아올 수 있음
-> 쿼리 스트링이 아닌 패스방식을 통해서 주소 전달하는 라우팅 기법
third party middleware (남들이 만든 미들 웨어)
그 중에서 body-parser 사용해보기
기존에는 바디 변수를 정의하고, 데이터가 도착할 때 마다 바디 변수에 추가하여 데이터가 없다는 이벤트가 발생했을 때, 그 바디 변수를 담아주는 형식으로 처리했음 이걸 바디파서를 이용하여 문제를 해결하게 됨
바디파서 설치
npm install body-parser —save
바디파서 모듈 로드
var bodyParser = require('body-parser');
// form데이터는 이렇게 처리
app.use(bodyParser.urlencoded({ extended: false }));
// json으로 처리할 땐 이렇게 처리
app.use(bodyparser.json())
// bodyParser 사용 (폼 데이터 형식 처리)
// bodyParser가 만들어내는 미들웨어를 표현하는 표현식
// 1. 사용자가 요청할 때 마다 바디파서 미들웨어가 실행 됨
// 2. post 데이터를 내부적으로 분석해서 가져온 다음에 콜백을 호출하도록 약속
// 3. 콜백의 request.body 프로퍼티를 만들어줌
// form데이터는 이렇게 처리
app.use(bodyParser.urlencoded({ extended: false }));
// json으로 처리할 땐
// app.use(bodyparser.json())
// 전체 app에서 readdir 기능이 공통적으로 사용이 된다! (글 목록을 표현해주는 기능)
// 이 기능을 미들웨어로서 처리!
// 모든 코드에서 (모든 라우트에서) request.list를 통해 filelist에 접근 가능하다!
// 하지만 post상황에선 굳이 filelist를 불러올 필요가 없음
// app.use -> app.get으로 바꾸고, get 방식으로 들어오는 모든 요청에 readdir을 받아올 수 있도록 해줌
// 결론 : function(){} 이게 readdir기능을 하는 미들웨어이다. 이것 처럼 express에서는 모든 라우터의 콜백함수는 전부 미들웨어 기능을 하는 것
app.get('*', function(request, response, next){
fs.readdir('./data', function(error, filelist){
request.list = filelist;
// next() 엔 그 다음에 호출되어야 할 미들웨어가 담겨있음
next();
});
})
npm install compression --save
app.use(compression());
// 전체 app에서 readdir 기능이 공통적으로 사용이 된다! (글 목록을 표현해주는 기능)
// 이 기능을 미들웨어로서 처리!
// 모든 코드에서 (모든 라우트에서) request.list를 통해 filelist에 접근 가능하다!
// 하지만 post상황에선 굳이 filelist를 불러올 필요가 없음
// app.use -> app.get으로 바꾸고, get 방식으로 들어오는 모든 요청에 readdir을 받아올 수 있도록 해줌
// 결론 : function(){} 이게 readdir기능을 하는 미들웨어이다. 이것 처럼 express에서는 모든 라우터의 콜백함수는 전부 미들웨어 기능을 하는 것
app.get('*', function(request, response, next){
fs.readdir('./data', function(error, filelist){
request.list = filelist;
// next() 엔 그 다음에 호출되어야 할 미들웨어가 담겨있음
next();
});
});
app.get('/', function(request, response){
var title = 'Welcome';
var description = 'Hello, Node.js';
// 여기서 request.list로 filelist를 대신하여 사용
var list = template.list(request.list);
var html = template.HTML(title, list,
`<h2>${title}</h2>${description}`,
`<a href="/create">create</a>`
);
response.send(html);
});
애플리케이션 레벨의 미들웨어
const express = require('express')
const app = express()
// req, res 변수를 받고 next를 통해 다음 미들웨어를 실행할지 안할지를 이전 미들웨어가 결정하도록 한다.
app.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
// 특정 경로만 미들웨어가 동작하도록 할 수 있음
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
// get 방식인 경우에만 동작하도록 할 수 있음
app.get('/user/:id', (req, res, next) => {
res.send('USER')
})
// 여러개의 함수를 미들웨어로 등록할 수 있음
app.use('/user/:id', (req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
}, (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
// 똑같은 패스를 가진 라우트의 경우 next가 실행되면 다음 미들웨어 호출
// next 가 없으면 하나의 미들웨어만 실행되고 끝남
app.get('/user/:id', (req, res, next) => {
console.log('ID:', req.params.id)
next()
}, (req, res, next) => {
res.send('User Info')
})
// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req, res, next) => {
res.send(req.params.id)
})
// 조건문을 통해 다음 미들웨어가 실행될지 안될지를 정할 수 도 있음
app.get('/user/:id', (req, res, next) => {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, (req, res, next) => {
// send a regular response
res.send('regular')
})
// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res, next) => {
res.send('special')
})
app.use(express.static('public')); // static 파일 찾아오는 모듈
이제 주소에 localhost:3000/images/hello.jpg 로 검색하면 해당 파일을 볼 수 있음 (images/hello.jpg는 파일의 경로)
원하는 이미지를 <img src = "images/hello.jpg">
로 url을 통해서 접근할 수 있다.
app.get('/page/:pageId', function(request, response, next){
var filteredId = path.parse(request.params.pageId).base;
fs.readFile(`./data/${filteredId}`, 'utf8', function(err, description){
if(err){ // 만약 에러가 있다면 다음 미들웨어로 에러를 나타내주기
next(err); // 이 때 맨 밑에 설정한 500에러에서 발생하는 미들웨어가 실행됨
} else{ // 에러가 없다면 원래 짜놓은 코드실행
var title = request.params.pageId;
var sanitizedTitle = sanitizeHtml(title);
var sanitizedDescription = sanitizeHtml(description, {
allowedTags:['h1']
});
var list = template.list(request.list);
var html = template.HTML(sanitizedTitle, list,
`<h2>${sanitizedTitle}</h2>${sanitizedDescription}`,
` <a href="/create">create</a>
<a href="/update/${sanitizedTitle}">update</a>
<form action="/delete_process" method="post">
<input type="hidden" name="id" value="${sanitizedTitle}">
<input type="submit" value="delete">
</form>`
);
response.send(html);
}
});
});
404 에러처리
app.use((req, res, next) => {
res.status(404).send("Sorry can't find that!")
})
500 에러 처리 핸들링
// 에러를 핸들링 하기위한 미들웨어
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})
라우터 페이지
const express = require('express');
const router = express.Router();
// 필요한 모듈들 main에서 가져와서 추가해주기
// template과 같이 경로가 들어간 모듈은 경로 다시 수정해서 잡아주기
// main 페이지에서 app.use('/topic') 으로 경로를 잡아줬기 때문에
// 라우터에선 앞에 topic을 빼줘야한다(안그러면 /topic/topic/create로가야함)
router.get('/create', (req, res)=>{
...
})
router.post()
// router export시켜서 메인에서 써먹을 수 있도록
model.exports = router;
main 페이지
const express = require('express')
const app = express()
// 라우터에서만 쓰이는 모듈은 삭제해주기
const indexRouter = require('./routes/index');
// topic 파일 모듈로 로드
const topicRouter = require('./routes/topic');
// /topic라고 시작하는 주소들에게 topicRouter라는 미들웨어를 적용하겠다는 뜻
app.use('/', indexRounter);
app.use('/topic', topicRouter);
const helmet = require('helmet');
app.use(helmet());