[Node.js] 익스프레스 웹 서버 만들기

hahaha·2021년 10월 10일
0

Node.js

목록 보기
6/10
post-thumbnail

Express

  • 서버 제작에 있어 불편함을 해소하고 편의 기능을 추가한 웹 서버 프레임워크
  • http 모듈의 요청과 응답 객체에 추가 기능들을 부여

시작하기

1. package.json 생성

2. express 모듈 설치

$ npm i express
$ npm i -D nodemon

- nodemon

  • 서버 코드에 수정 사항이 생길 때마다 서버를 자동으로 재시작
  • rs 명령어를 통해 수동 재시작 가능
  • 개발용으로만 사용하는 것을 권장

실행하기

1. app.js 파일 작성

const express = require('express');
const path = require('path);

const app = express();

// 서버가 실행될 포트 설정 (default: 3000)
app.set('port', process.env.PORT || 3000);

// app.get(주소, 라우터)
// 주소에 대한 GET 요청이 올 때 수행할 동작 정의
app.get('/', (req, res) => {
  res.send('Hello, Express);
           
  // HTML 파일로 응답 가능
  res.sendFile(path.join(__dirname, '/index.html'));
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'),'번 포트에서 대기 중');
});

2. 서버 실행

$ npm start

3. 서버 접속

미들웨어

  • 요청과 응답 중간에 위치
  • 라우터와 에러 핸들러 또한 미들웨어의 일종
  • 요청과 응답을 조작하여 기능 추가 / 나쁜 요청 걸러내기 기능 수행

사용하기

app.use(미들웨어);
app.use('주소', 미들웨어);
app.get('주소', 미들웨어);
  • 매개변수가 req, res, next인 함수
  • next: 다음 미들웨어로 넘어가는 함수 (필수)
    - next(): 다음 미들웨어로
    - next('route'): 다음 라우터로
    - next(error): 에러 핸들러로
  • 하나의 라우터에 여러 개의 미들웨어 장착 가능
app.get((req, res, next) => {
  console.log('GET / 요청에서만 실행');
  next();
}, (req, res) => {
  throw new Error('에러 처리 미들웨어로');
});

- 에러처리 미들웨어

  • 매개변수가 err, req, res, next인 함수
    - 모든 매개변수를 사용하지 않도라도 반드시 4개여야 함
  • 에러처리 미들웨어를 직접 연결하지 않아도 기본적으로 익스프레스가 에러처리 하긴 함
  • 일반적으로 가장 아래에 위치
app.use((err, req, res, next) => {
  console.error(err);
  res.status(500).send(err.message);
});

미들웨어 간의 데이터 전달

1. 세선 사용 시, req.session 객체 이용

  • 세션 유지되는 동안 데이터도 계속 유지

2. app.set을 이용한 데이터 저장

  • express에서 전역적으로 사용
  • 요청을 보낸 사용자 개개인의 값을 넣기에 부적절
  • 앱 전체의 설정을 공유할 때 사용

3. req 객체 이용

  • 요청이 끝날 때까지만 데이터 유지
app.use((req, res, next) => {
  req.data = '데이터';
  next();
}, (req, res, next) => {
  console.log(req.data);	// 데이터
  next();
});

dotenv

  • process.env 파일을 관리하기 위한 패키지
  • .env 파일을 읽어서 process.env 파일로 만듬
  • 보안과 설정의 편의를 위해 별도의 파일로 관리

morgan

  • 요청과 응답에 대한 정보를 콘솔에 기록
  • [HTTP 메서드] [주소] [HTTP 상태 코드] [응답 속도] - [응답 바이트]
// req, res, next 미들웨어 내부에 존재
// next 내부적으로 호출

app.use(morgan('dev'));
// GET / 500 7.409 ms - 50
// dev외에 combined, common, short, tiny 등 존재

static

  • 정적인 파일들을 제공하는 라우터 역할
  • 기본적으로 express 객체 내에 존재
  • 해당 파일이 없는 경우, 내부적으로 next() 호출
  • 파일이 있는 경우, 응답으로 파일 보냄(next() 호출 X)
app.use('/', express.static(path.join(__dirname, 'public')));
// 실제 경로에는 public 폴더 지정되어 있으나, 요청 주소에는 포함되지 않음 
// -> 서버 폴더 경로와 요청 경로가 다름 
// -> 보안에 큰 도움

body-parser

  • 요청의 본문에 있는 데이터를 해석해서 req.body 객체 생성
  • 멀티파트(이미지, 동영상, 파일) 데이터는 처리 X -> multer 모듈 이용
  • JSON, URL-encoded 형식 데이터 해석
  • express 4.16.0 부터 내장되어 있음.
    - Raw, Text 형식의 데이터 해석할 경우, 직접 설치 필요
app.use(express.json());

// querystring 모듈을 사용하여 쿼리 스트링 해석 (<> qs 모듈 사용)
app.use(express.urlencoded({ extended: false });
  • 요청에 동봉된 쿠키를 해석해 req.cookies 객체 생성
  • 서명된 쿠키를 통해 해당 쿠키가 내 서버가 만든 쿠키인지 검증
app.use(cookieParser(비밀키));
  • 쿠키 생성: res.cookie(키, 값, 옵션)
  • 쿠키 제거: res.clearCookie

express-session

  • 세션 관리용 미들웨어
  • 사용자별로 req.session 객체 안에 유지
app.use(session({
  resave: false,			// 세션 변동에 따른 재저장 여부
  saveUninitialized: false,		// 변동 사항에 따른 세션 재생성 여부
  secret: process.env.COOKIE_SECRET,	// cookie-parser의 secret과 동일(쿠키 서명)
  cookie: {				// 세션 쿠키
    httpOnly: true,
    secure: false,
  },
  name: 'session-cookie',		// default: connect.sid
})));
  • store 옵션
    - 현재와 같이 메모리에 세션을 저장하면, 서버를 재시작할 때 메모리가 초기화 됨
    - 배포 시, store에 DB를 연결하여 세션 유지하는 것이 좋음
  • express-session에서 서명한 쿠키: s%3A가 앞에 붙음

라우팅 분리

1. routes 폴더 내 라우터 파일 생성

// routes/index.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.send('index.js');
});

module.exports = router;

// routes/user.js
const express = require('express');
const router = express.Router();

router.get('/', (req, res) => {
  res.send('user.js');
});

module.exports = router;

2. app.js에 라우터 연결

// app.js
const indexRouter = require('./routes');	// index.js 생략 가능
const userRouter = require('./routes/user');

app.use('/', indexRouter);
app.use('/user', userRouter);

app.use((req, res, next) => {
  res.status(404).send('Not Found');
});

라우트 매개변수

  • req.params 객체 내부에 존재
  • 일반 라우터보다 뒤에 위치해야 함
router.get('/user/:id', function(req, res) {
  console.log(req.params, req,query);
  // req.params.id로 접근 가능
});
  • ex. /users/123?limit=5&skip=10
    -> { id: '123' } { limit: '5', skip: '10' }

하나의 라우터에 여러 메서드 추가하기

  • router.route 사용
router.route('/abc')
	.get(...)
	.post(...);

템플릿 엔진

  • 자바스크립트를 사용해서 HTML을 렌더링
  • 퍼그(Pug), 넌적스(Numjucks) 등
profile
junior backend-developer 👶💻

0개의 댓글