06. NodeJS Express

Kim Sang Yeob·2023년 1월 17일
0

NodeJS Book 3th

목록 보기
6/9
post-thumbnail

6.1 익스프레스 프로젝트 시작하기

1) Express 소개

  • http 모듈로 웹 서버를 만들 때 코드가 보기 좋지 않고, 확장성도 떨어짐
    • 프레임워크로 해결
    • 대표적인 것이 Express(익스프레스), Koa(코아), Hapi(하피)
    • 코드 관리도 용이하고 편의성이 많이 높아짐
  • https://npmtrends.com 에서 검색해서 다운

2) package.json 만들기

{
  "name": "learn-express",
  "version": "0.0.1",
  "scripts": {
    "start": "nodemon app"
  },
  "devDependencies": {
    "nodemon": "^2.0.20"
  }, // 개발할 때 자주 사용되는 모듈 nodemon
  "dependencies":{
    "express": "^4.18.2"
  }
}

3) Express 서버 실행

  • 하나의 콜백함수 안에서 send속성 메소드는 한 번만 사용 가능
  • 요청 한 번당 응답도 한 번만 가능
const express = require('express');
const app = express();

// 전역 변수 같은 느낌으로 설정하주는 것
app.set('port', press.env.PORT || 3000);
app.get('/', (req, res) => {
    res.send('hello express');
});
app.post('/', (req, res) => {
    res.send('hello express');
});
app.get('/about', (req, res) => {
    res.send('hello express');
});
// app.listen(3000, ~~) 와 같음
app.listen(app.get('port'), () => {
    console.log('익스프레스 서버 실행');
});

4) Express html 파일 띄우기

const path = require('path');

app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'index.html'));
}); // sendFile 메소드와 path 모듈을 이용해서 html 파일 불러오기

5) Express 와일드카드

  • :(콜론)을 이용해서 중복되는 url을 변수처럼 라우팅 가능
  • 보통 코드의 아래쪽에 배치하여 최후의 수단일 때 라우팅 되도록 함
app.get('/:wildcard', (req, res) => {
    res.send(`hello ${req.params.wildcard}`);
});

6) Express *

  • 모든 get요청에 대해 처리하는 방법
  • * 보다 더 아래에 쓰여진 코드는 사실상 의미가 없는 경우가 되기 때문에, 보편적으로 가장 아래쪽에 쓴다.
app.get('*', (req, res) => {
    res.send(`hello everybody`);
});

7) JSON 응답하기

app.get('/', (req, res) => {
    res.writeHead(200, { 'Content-Type' : 'application/json'});
    req.end(JSON.stringify({ hello: 'zerocho' }));
	// 위 코드를 Express가 아래로 줄여줌
    res.json({ hello: 'zerocho'});
});

6.2 자주 사용하는 미들웨어

1) 미들웨어의 개념

  • 익스프레스는 미들웨어로 구성됨
  • 요청과 응답의 중간에 위치하여 미들웨어
  • app.use(미들웨어)로 장착
  • 위에서 아래로 순서대로 실행됨
  • 미들웨어는 req, res, next가 매개변수인 함수
  • req: 요청, res: 응답 조작 가능
  • next()로 다음 미들웨어로 넘어감
app.use((req, res, next) => {
    console.log('모든 요청에 실행');
    next();
}); // 모든 요청에서 미들웨어 실행
------------------------------------------
app.use('/abc',(req, res, next) => {
    console.log('abc에서만 실행');
    next();
}); // abc로 시작하는 모든 요청에서 미들웨어 실행
------------------------------------------
app.post('/about',(req, res, next) => {
    console.log('abc에서만 실행');
    next();
});
// post 자리에 다른 요청이 들어올 수 있음
// abc로 시작하는 get, post 등 요청에서 미들웨서 실행

2) 에러 미들웨어

  • next(error)를 하면 에러발생시 에러처리 미들웨어가 실행됨
  • err, req, res, next까지 매개변수가 4개
  • 첫 번째 err에는 에러에 대한 정보가 담김
  • res.status 메서드로 HTTP 상태 코드를 지정 가능(기본값 200)
  • 에러 처리 미들웨어를 안 연결해도 Express가 에러를 알아서 처리해주긴 함
  • 특별한 경우가 아니면 가장 아래에 위치함
  • try catch안에 넣기..
app.use((err, req, res, next) => {
    console.error(err);
})

3) morgan

  • 서버로 들어온 요청과 응답을 기록해주는 미들웨어
    • 로그의 자세한 정도 선택 가능(dev, tiny, short, common, combined)
    • 순서대로 HTTP요청 요청주소 상태코드 응답속도 - 응답바이트
    • 개발환경에서는 dev, 배포환경에서는 combined를 보통 사용함
const morgan = require('morgan');

app.use(morgan('dev'));
// dev대신 combined 기입
  • 요청 헤더의 쿠키를 해석해주는 미들웨어
    • parseCookies 함수와 기능 비슷함
    • req.cookies 안에 쿠키들이 들어있음
    • 비밀 키로 쿠키 뒤에 서명을 붙여 내 서버가 만든 쿠키임을 검증할 수 있음
app.use(cookieParser(비밀키));
  • 실제 쿠키 옵션들을 넣을 수 있음
    • expires, domian, httpOnly, maxAge, path, secure, sameSite 등
    • 지울 때는 clearCookie로(expires와 maxAge를 제외한 옵션들이 일치해야 함)
const cookieParser = require('cookie-parser');

res.cookie('name', 'zerocho', {
  expires: new Date(),
  httpOnly: true,
  secure: true,
  path: '/',
});
res.clearCookie('name', 'zerocho', { httpOnly: true, secure: true });

5) express.json & express.urlencoded

  • req.body 안에 정보가 저장되어 있음
  • .json은 클라이언트에서 json파일을 보냈을 때 파싱해줌
  • .urlencoded는 form 데이터를 submit할 때 파싱해줌. extended는 querystring을 어떻게 처리할지 여부인데, true로 하면 qs 모듈을 쓰고 false로 하면 querystring 내장모듈을 사용함
  • form으로 이미지나 파일은 .urlencoded가 처리를 못해서 multer를 사용해야함.
  • qs가 더 강력하기 때문에 보통 true로 함
  • 기본적으로 항상 사용하는 미들웨어
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

6) express.static

  • 정적인 파일들을 제공하는 미들웨어
    • 인수로 정적 파일의 경로를 제공
    • 파일이 있을 때 fs.readFile로 직접 읽을 필요 없음
    • 요청하는 파일이 없으면 알아서 next를 호출해 다음 미들웨어로 넘어감
    • 파일을 발견했다면 다음 미들웨어는 실행되지 않음
app.use('요청경로', express.static('실제경로'));
app.use('/', express.static(path.join(__dirname, 'public')));

7) express-session

  • 세션 쿠키에 대한 설정(secret: 쿠키 암호화, cookie: 세션 쿠키 옵션)
  • 세션 쿠키는 앞에 s%3A가 붙은 후 암호화되어 프론트에 전송됨
  • resave : 요청이 왔을 때 세션에 수정사항이 생기지 않아도 다시 저장할지 여부
  • saveUninitialized: 세션에 저장할 내역이 없더라도 세션을 저장할지
  • req.session.save로 수동 저장도 가능하지만 할 일이 거의 없다
app.use(session({
    resave: false,
    saveUninitialized: false,
    secret: process.env.COOKIE_SECRET,
    cookie: {
        httpOnly: true,
        secure: false,
    },
    name: 'session-cookie',
}));

app.get('/', (req, res, next) => {
    req.session.name = 'zerocho' // 세션 등록
    req.sessionID; // 세션 아이디  확인
    req.session.destroy();  // 세션 모두 제거
});

8) next

  • next를 호출해야 다음 코드로 넘어감
    • next를 주석 처리하면 응답이 전송되지 않음
    • 다음 미들웨어(라우터 미들웨어)로 넘어가기 않기 때문
    • next에 인수로 값을 넣으면 에러 핸들러로 넘어감('route'인 경우 다음 라우터로)

9) 미들웨어 확장하기

  • 미들웨어 안에 미들웨어를 넣는 방법
    • 아래 두 코드는 동일한 역할
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'){
    } else {
    	morgan('dev')(req, res, next);
    }
});

10) 멀티파트 데이터 형식

  • form 태그의 enctype이 multipart/form-data인 경우
    • body-parser로는 요청 본문을 해석할 수 없음
    • multer 패키지 필요
<form action="upload" method="post" enctype="multipart/form-data">
  <input type="file" name="image" />
  <input type="text" name="title" />
  <button type="submit">업로드</button>
</form>

11) multer 설정하기

12) dotenv

  • 최대한 위에 코드 작성하기
  • .env 파일에 시크릿키를 관리할 수 있음
  • process.env.{시크릿이름}을 하면 키 값을 가져옴
const dotenv = require('dotenv');
dotenv.config();
profile
Studying NodeJS...

0개의 댓글