MERN stack
: JS 생태계에서 인기 있는 프레임워크인 MongoDB, Express, React, Node
Express.js
: Node.js 환경에서 웹 서버 또는 API 서버를 제작하기 위해 사용되는 인기 있는 프레임워크
중요한 에러
: app.use(express.json())로 모든 요청에 대해 json 처리를 해줄 수 있는데 이때
express.json({strict:false})로 넣어주어야 배열, 객체가 아닌 값에 대해서도 json화 시켜준다
const http = require('http')
const server = http.createServer((req, res) => {
//(1) cors
-res.writehead() : header 추가
//(2) req 조작해서 res로 돌려준다
-req로 라우팅 : method, url
-post 요청 시 body payload를 이용 :
let body=[]
request.on('data', (chunk) //buffer의 형태로 data가 나눠져서 온다
=> body.push(chunk)
).on('end', (buffer)
=> body = Buffer.concat(body).onString()//Buffer.concat() 함수
)//이벤트 리스너
//(3) 서버랑 포트랑 연결
}).listen('port#')
npm init
npm install express --save
=> save는 선택
const express = require('express')
const app = express()
const port = 3000
[node 파일이름]
라우팅이란?
URI(또는 경로) 및 특정한 HTTP 요청 메소드(GET, POST 등인) 특정 엔드포인트에 대한 클라이언트 요청에 애플리케이션이 응답하는 방법을 결정하는 것
=> 각 라우트는 하나 이상의 핸들러 함수를 가질 수 있고 이 함수는 라우트가 일치할 때 실행된다
라우트 정의에는 다음과 같은 구조 사용
app.METHOD(PATH, HANDLER)
app : express의 인스턴스
METHOD: HTTP 요청 메소드
PATH : 서버에서의 경로
HANDLER : 라우트가 일치할 때 실행되는 함수
post 요청, /
app.post('/', function(req, res){
res.send('got a post request')
})
put 요청, /user
app.put('/user', function(req, res){
res.send('got a put request at /user')
})
delete 요청, /user
app.delete('/user', function(req, res){
res.send('got a delete request at /user')
})
4-1.라우트 메소드
HTTP 메소드 중 하나로부터 파생되며 express 클래스의 인스턴스에 연결된다
앱 루트에 대한 GET 및 POST 메소드에 대해 정의된 라우트의 예다
app.get('/', function(req, res){
res.send('GET request to the homepage')
})
app.post('/', function(req, res){
res.send('POST request to the homepage')
})
Express는 HTTP 메소드에 해당하는 다음과 같은 라우팅 메소드 지원
(1)get, post, put, head, delete, options, ...
(2)올바르지 않은 JS 변수 이름으로 변환되는 메소드를 라우팅하려면 대괄호 표기법 사용
app['m-search']('/', function(){})
(3)app.all()
: 모든 요청 메소드에 대해 한 경로에서 미들웨어 함수를 로드하는데 사용한다
ex.
app.all('/secret', function(req, res, next){
})
//모든 요청, /secret이라는 패스
4-2.라우트 경로
라우트 경로
: 요청 메소드와의 조합을 통해 요청이 이루어질 수 있는 엔드포인트를 정의한다
형태 : 문자열, 문자열 패턴, 정규식 등
문자열을 사용한 경로
'/ab?cd' : acd, abcd
-> 문자? : 생략 가능
'/ab+cd' : abcd, abbcd, abbbcd
-> 문자+ : 문자 여러 개 가능
'/abcd' : abcd, abxcd, abRABDOMcd, ab123cd
->자리에 아무것도 안와도 되고, x, 숫자, 문자 등 다른 거 다 와도 됨
'/ab(cd)?e' : /abe, abcde
-> cd의 유무
정규식 기반으로 하는 라우트 경로의 예
/a/ : a가 들어간 모든 라우트
/.*fly$/ : 끝이 fly이 모든 라우트
4-3.라우트 핸들러
미들웨어와 비슷하게, 작동하는 여러 콜백 함수를 제공하여 요청을 처리할 수 있다
함수나 함수 배열의 형태 또는 둘을 조합한 형태일 수 있다
하나의 콜백 함수
2개 이상의 콜백 함수는 하나의 라우트를 처리할 수 있다
(next 오브젝트를 반드시 지정해야 함)
-> next를 안 쓰면 첫번째 함수만 실행하나??
-> send로 응답을 전송하지 않으니까 무한 대기 상태로??
하나의 콜백 함수 배열은 하나의 라우트를 처리할 수 있다
next()가 뭘까?
출처: https://kamang-it.tistory.com/624
'indicating the next middleware functino'
미들웨어 함수로 보내지는 것이다
'현재 판단하지 않고 다음 라우터로 넘기겠다'
=> res를 사용해서 결과를 내지 않고 next를 사용해서 판단을 유보시킨다
step1이 우선 실행되고 step2가 뒤에 실행된다
next는 현재에 판단하지 않고 다음 콜백함수로 떠넘긴다
유의할 점: next('route')를 넣으면 라우터 미들웨어 스택의 나머지 미들웨어 함수들을 건너뛴다.
app.METHOD() 또는 router.METHOD()함수를 이용해 로드된 미들웨어 함수에서만 작동한다
에 파라메터를 넣게 되는 순간 무조건 에러
미들웨어와의 차이점: 이러한 콜백은 next('route')를 호출하여 -> 나머지 라우트 콜백을 우회할 수도 있다는 점
이러한 메커니즘을 이용하면 라우트에 대한 사전 조건을 지정한 후, 현재의 라우트를 계속할 이유가 없는 경우에는 제어를 후속 라우트에 전달할 수 있다. ??
4-4. 응답 메소드
다음 표에 표시된 응답 오브젝트에 대한 메소드(res)는 응답을 클라이언트로 전송하고 요청-응답 주기를 종료할 수 있습니다. 라우트 핸들러로부터 다음 메소드 중 어느 하나도 호출되지 않는 경우, 클라이언트 요청은 정지된 채로 방치됩니다.
res.download() 파일이 다운로드되도록 프롬프트합니다.
res.end() 응답 프로세스를 종료합니다.
res.json() JSON 응답을 전송합니다.
res.jsonp() JSONP 지원을 통해 JSON 응답을 전송합니다.
res.redirect() 요청의 경로를 재지정합니다.
res.render() 보기 템플리트를 렌더링합니다.
res.send() 다양한 유형의 응답을 전송합니다.
res.sendFile() 파일을 옥텟 스트림의 형태로 전송합니다.
res.sendStatus() 응답 상태 코드를 설정한 후 해당 코드를 문자열로 표현한 내용을 응답 본문으로서 전송합니다.
4-5. app.route()
라우트 경로에 대하여 체인 가능한 라우트 핸들러를 작성할 수 있다
한 곳으로 경로를 지정하고 모듈식 라우트를 작성해 중복성과 오타가 감소하여 도움이 된다
app.METHOD와의 차이점
: 루트 하나에 대해 여러 method 요청 별로 res를 설정할 수 있다
4-6.express.Router
모듈식 마운팅 가능한 핸들러 작성 가능
Router 인스턴스는 완전한 미들웨어이자 라우팅 시스템
라우터를 모듈로서 작성하고,
var router = express.Router()
라우터 모듈에서 미들웨어 함수를 로드하고
몇몇 라우트를 정의하고
birds.js라는 이름의 라우터 파일
기본 앱의 한 경로에 라우터 모듈을 마운트한다
=> birds 안에 있는 모든 라우터들을 birds모듈로 로드한다음
app.use처럼 라우팅을 해서 birds라는 path 이후의 라우팅용 라우터 핸들러로 연결한다
정리
1) 라우터 파일을 하나 만들어서 안에 app처럼 요청에 따른 path, 미들웨어 설정
2) 다른 파일에서 라우터 모듈을 로드해서 사용
미들웨어 함수란?
요청 오브젝트(req), 응답 오브젝트(res) 그리고 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수 대한 엑세스 권한을 갖는 함수
그럼 미들웨어 함수는 라우트 핸들러 같은건가??
아마 req, res에 접근 가능하고 다음 미들웨어 함수를 next()를 통해 넘길 수 있는 함수인듯
만약 이번 미들웨어 함수에서 응답을 보내지 않고 next()를 보내지 않았다면 아직 응답을 받지 못한 거니까 정지된 채로 방치
미들웨어의 로드 순서는 중요하여 먼저 로드되는 미들웨어 함수가 먼저 실행된다
1)app.use() : 모든 내용에 대해 적용
console.log(req.method, req.url);
next();
next를 안 쓰면 다음 내용으로 넘어가지 않는다
요청이 끝나지 않는다
그러므로 next를 안 쓰면 안된다
const jsonParser = express.json({strict: false})
//JSON.parse됨
응답을 보낼 때도 json형태로 보내야 하는데 이게 안 되어서 문제
그러므로 JSON.stringify를 해서 보내야 한다
방법1)res.send(JSON.stringify(req.body.toLowerCase()))
send는 배열, 객체만 json화를 해주기 때문에 다른 형태면 json으로 보내는 것이 좋다
방법2)res.json(req.body.toLowerCase())의 형태로 보낼 수 있다
send로 보내주면 되는데 json으로는 parameter는 배열이거나 객체일 때만 JSON으로 보낸다
res.send(JSON.stringify())
모든 곳에 적용하고 싶으면 app.use로 사용하면 된다
ex. app.use(jsonParser)
npm install cors
const cors = require('cors')
router를 쓰고 있다
app.use(url , router)
: 가독성을 높인다
: controller, repository, router 등 이렇게 나눠놓는 것이 사용하기에 좋다
flightRouter.js
bookRouter.js
공식문서에서 맨 밑에 express.Router
airportController로 참고
req.query로 객체에 접근할 수 있다
airportsList를 filter해서 사용해야 한다
?뒤는 query
localhost:3000/flight/uuid내용
=> uuid 내용은 req.params 에 잡힌다
Restful API
querys는 필터링
params는 바로
=> 이 둘의 차이를 생각해서 짜야 함
이런 조건들을 충족시키는지 확인함
res.location('/book/${flightuuid}' )
res.status(201).json({flightuuid})
location을 응답에서 실어보내주어야 restful하다 (2-3단계)