티스토리 뷰

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


// 1. 모듈 가져오기
const express = require("express");
const path = require("path");

// 2. 앱 설정
const app = express();
app.set("port", process.env.PORT || 3000);

// 3. 라우트 설정
app.get("/", (req, res) => {
  // res.send("Hello, Express");
  res.sendFile(path.join(__dirname, "/index.html"));
});

// 4. 서버 시작
app.listen(app.get("port"), () => {
  console.log(app.get("port"), "번 포트에서 대기 중");
});

 

  1. 모듈 가져오기:
    • express: 익스프레스 프레임워크를 사용하기 위해 가져옵니다.
    • path: 파일 경로를 다루기 위한 Node.js 내장 모듈입니다.
  2. 앱 설정:
    • app.set("port", process.env.PORT || 3000): 서버가 사용할 포트를 설정합니다. 환경 변수 PORT가 설정되어 있지 않으면 기본값으로 3000번 포트를 사용합니다.
  3. 라우트 설정:
    • app.get("/", (req, res) => { ... }): 루트 경로(/)에 GET 요청이 들어오면 index.html 파일을 응답으로 보냅니다.
  4. 서버 시작:
    • app.listen(...): 설정한 포트에서 서버를 시작하고, 콘솔에 메시지를 출력합니다.

 

req, res 객체 살펴보기


익스프레스의 req, res 객체는 http 모듈의 req, res 객체를 확장한 것입니다. 예를 들어 express에서 기존 http 모듈의 res.writeHead, res.write, res.end 메서드를 그대로 사용할 수 잇으면서 express에서 제공하는 res.send나 res.sendFile 같은 메서드도 쓸 수 있습니다.

req

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(헤더 이름)`: 헤더의 값을 가져오고 싶을 때 사용하는 매서드 입니다.

res

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 상태 코드를 지정합니다.

 

 

미들웨어

미들웨어는 애플리케이션의 요청-응답 주기에서 특정 작업을 수행하기 위해 사용되는 함수입니다. 미들웨어는 요청이 서버에 도착하고, 응답이 클라이언트로 전송되기 전에 중간에서 여러 작업을 처리할 수 있습니다. 예를 들어, 요청 로깅, 인증, 데이터 파싱, 세션 관리 등이 미들웨어를 통해 처리됩니다.

미들웨어 특성

  • 순차적 실행: 요청이 들어오면 등록된 순서대로 미들웨어가 실행됩니다. 각 미들웨어는 next() 함수를 호출하여 다음 미들웨어로 제어를 전달합니다.
  • 요청 객체와 응답 객체 접근: 각 미들웨어는 `req`, `res`, `next` 객체에 접근할 수 있어, 요청 데이터 조작이나 응답 수정이 가능합니다.
  • 유연성: 다양한 기능을 가진 미들웨어를 조합하여 사용할 수 있으며, 필요에 따라 커스텀 미들웨어를 작성할 수도 있습니다.

next의 동작

`next()` 함수는 현재 미들웨어의 작업을 마친 후, 다음 미들웨어로 제어를 전달하는 역할을 합니다. `next`에 인수를 전달하면, 해당 인수가 에러로 간주되어 에러 처리 미들웨어로 바로 이동합니다. `next`에 `'route'`라는 문자열을 넣으면 다음 라우터의 미들웨어로 바로 이동하고, 그 외의 인수를 넣는다면 바로 에러 처리 미들웨어로 이동합니다. 이때의 인수는 에러 처리 미들웨어의 `err` 매개변수가 됩니다. 라우터에서 에러가 발생할 때는 에러를 `next(err)`를 통해 에러 처리 미들웨어로 넘깁니다.

에러 처리 미들웨어로 에러 보내기

에러 처리 미들웨어는 애플리케이션에서 발생하는 오류를 중앙에서 관리하고 처리할 수 있게 해줍니다. 익스프레스에서는 에러 처리 미들웨어를 정의하여 오류 응답을 일관성 있게 제공할 수 있습니다.

에러 처리 미들웨어는 `err` 인자를 첫 번째로 받는 특수한 형태의 미들웨어입니다. 라우트 핸들러나 다른 미들웨어에서 `next` 함수를 사용하여 에러를 전달할 수 있습니다.

// 에러 처리 미들웨어
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('서버 오류가 발생했습니다.');
});

app.get('/error', (req, res, next) => {
  const err = new Error('강제로 발생시킨 에러');
  next(err);
});

 

morgan

Morgan은 HTTP 요청 로깅을 위한 미들웨어입니다. 요청이 들어올 때마다 로그를 남겨 개발 및 디버깅에 유용합니다. 인수로 dev 외에 combined, common, short, tiny 등을 넣을 수 있습니다.

const morgan = require("morgan");
app.use(morgan('dev'));

static

static 

미들웨어는 정적인 파일들을 제공하는 라우터 역할을 합니다. 함수의 인수로 정적 파일들이 담겨있는 폴더를 지정하면 됩니다. 요청 경로에 해당하는 파일이 없으면 알아서 내부적으로 next를 호출합니다.

app.use('요청 경로', express.static('실제 경로'));

app.use(express.static(path.join(__dirname, "public")));

body-parser

Body-Parser는 요청 본문을 파싱하여 req.body에 저장해주는 미들웨어입니다. 현재는 express에 내장된 기능으로 대체되었습니다. 폼전송은 URL-encoded 방식을 주로 사용합니다. urlencode 옵션 extended는 false이면 노드의 querystring 모듈을 사용하고 true이면 qs 모듈을 사용해 해석합니다.

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

익스프레스는 JSON과 URL-encoded 형식 외에도 Raw, Text 형식의 데이터를 추가로 해석할 수 있습니다. Raw는 요청의 본문이 버퍼일 때, Text는 텍스트 데이터일 때 해석하는 미들웨어입니다.

app.use(express.raw());
app.use(express.text());

cookie-parser

Cookie-Parser는 요청에 포함된 쿠키를 파싱하여 req.cookies에 저장해주는 미들웨어입니다. 요청에 동봉된 쿠키를 해석해 req.cookies 객체로 만듭니다.

const cookieParser = require("cookie-parser");
app.use(cookieParser());

app.use(cookieParser(비밀 키));

쿠키를 생성/ 제거하려면 res.cookie, res.clearCookie 메서드를 사용해야 합니다.

res.cookie('name','bear',{
	expires: new Date(Date.now() + 900000),
    httpOnly: true,
    secure: true,
})

res.clearCookie('name', 'bear', {httpOnly: true, secure: true});

express-session

Express-Session은 세션 관리를 위한 미들웨어로, 사용자별로 상태를 유지할 수 있게 도와줍니다. 로그인 등의 이유로 세션을 구현하거나 특정 사용자를 위한 데이터를 임시적으로 저장해둘 때 매우 유용합니다. 세션은 사용자별로 req.session 객체 안에 유지됩니다.

app.use(
  session({
    resave: false,
    saveUninitialized: false,
    secret: process.env.COOKIE_SECRET,
    cookie: {
      httpOnly: true,
      secure: false,
    },
    name: "session-cookie",
  })
);

 

  • secret: 세션 암호화를 위한 비밀 키입니다.
  • resave: 세션을 항상 저장할지 여부를 설정합니다. false로 설정하면 변경되지 않은 세션은 저장되지 않습니다.
  • saveUninitialized: 초기화되지 않은 세션을 저장할지 여부를 설정합니다. true로 설정하면 새 세션을 항상 저장합니다.
  • cookie: 세션 쿠키의 설정을 정의합니다. secure: true로 설정하면 HTTPS에서만 쿠키가 전송됩니다.

 

dotenv

Dotenv는 환경 변수를 관리하기 위한 미들웨어로, .env 파일에 설정된 변수를 process.env에 로드합니다. 민감한 정보를 코드에 직접 작성하지 않고, 환경 변수로 관리할 수 있어 보안에 유리합니다. 예를 들어, 데이터베이스 비밀번호나 API 키 등을 .env 파일에 저장합니다. .env 파일은 .gitignore에 추가하여 버전 관리 시스템에 노출되지 않도록 합니다.

require('dotenv').config();

multer

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 },
});

app.post("/upload", upload.single("image"), (req, res) => {
  console.log(req.file);
  res.send("ok");
});

multer 함수의 인수로 설정을 넣습니다. storage 속성에는 destination(어디에), filename(어떤 이름으로) 저장될때의 옵션 값을 설정합니다. file 객체에는 업로드한 파일에 대한 정보가 들어있습니다. done 매개변수는 함수입니다. 첫 번째 인수에는 에러가 있다면 에러를 넣고, 두 번째 인수에는 실제 경로나 파일 이름을 넣어줍니다. req나 file의 데이터를 가공해서 done으로 넘기는 형식입니다. limits 속성에는 업로드에 대한 제한 사항을 설정할 수 있습니다.

  • .single(fieldname): fieldname 인자에 명시된 이름의 단수 파일을 전달 받습니다. 이 파일은 req.file 에 저장됩니다. 이미지 하나는 req.file로 나머지 정보는 req.body에 저장됩니다.
  • .array(fieldname[, maxCount]): fieldname 인자에 명시된 이름의 파일 전부를 배열 형태로 전달 받습니다. 이미지들은 req.files로 나머지 정보는 req.body에 저장됩니다
  • .fields(fields): fields 인자에 명시된 여러 파일을 전달 받습니다. 파일 객체는 배열 형태로 req.files 에 저장됩니다. 이미지들은 req.file로 나머지 정보는 req.body에 저장됩니다.
  •  .none(): 오직 텍스트 필드만 허용합니다. 만일 파일이 업로드 되었을 경우, "LIMIT_UNEXPECTED_FILE" 와 같은 에러 코드가 발생합니다. 이는 upload.fields([]) 와 같은 동작을 합니다. 모든 정보를 req.body에 저장됩니다.

 

Router 객체로 라우팅 분리하기


복잡한 애플리케이션에서는 모든 라우트를 하나의 파일에 작성하는 것은 유지보수가 어려울 수 있습니다. 이를 해결하기 위해 Router 객체를 사용하여 라우팅을 분리할 수 있습니다.

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

// 사용자 목록 조회
router.get('/', (req, res) => {
  res.send('사용자 목록');
});

module.exports = router;
// app.js
const express = require("express");
const path = require("path");
const morgan = require("morgan");
const usersRouter = require('./routes/users'); // 라우터 파일 불러오기

const app = express();
app.set("port", process.env.PORT || 3000);

app.use(morgan("dev"));
app.use(express.static(path.join(__dirname, "public")));
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 라우터 사용
app.use('/users', usersRouter);

app.get("/", (req, res) => {
  res.sendFile(path.join(__dirname, "/index.html"));
});

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

라우트 매개변수 패턴

라우트 매개변수는 동적인 URL 경로를 정의할 때 사용됩니다. 이는 특정 패턴을 사용하여 URL 내에서 변수 부분을 캡처할 수 있게 해줍니다. 익스프레스에서는 콜론(:)을 사용하여 매개변수를 정의하며, 다양한 패턴을 지원합니다.

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

...
// 라우트 매개변수 패턴
// 특정 제품 정보 조회
router.get('/:id', (req, res) => {
  const productId = req.params.id;
  res.send(`제품 정보: ${productId}`);
});

module.exports = router;

/:id는 URL의 해당 위치에 있는 값을 req.params.id로 캡처합니다. 예를 들어, /products/123으로 요청하면 id는 123이 됩니다. :id이면 req.params.id로, :type이면 req.params.type으로 조회할 수 있습니다.

주소에 쿼리스트링을 쓸 때도 잇습니다. 쿼리 스트링의 키-값 정보는 req.qurey 객체 안에 들어있습니다.

 

참고


 

 

Node.js 교과서 : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

 

[개정3판] Node.js 교과서 - 기본부터 프로젝트 실습까지 강의 | 제로초(조현영) - 인프런

제로초(조현영) | 노드가 무엇인지부터, 자바스크립트 최신 문법, 노드의 API, npm, 모듈 시스템, 데이터베이스, 테스팅 등을 배우고 5가지 실전 예제로 프로젝트를 만들어 나갑니다. 클라우드에 서

www.inflearn.com

 

multer/doc/README-ko.md at master · expressjs/multer

Node.js middleware for handling `multipart/form-data`. - expressjs/multer

github.com

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함