웹 시스템 개발 #ExpressJS

학교 공부를 복습할 겸 적는 것이기에 내용이 부족할 수 있습니다.

 

부족한 것은 상관 없으나, 잘못된 부분이 발견된다면 지적해주시면 감사하겠습니다.

 

이전 포스팅을 보지 않으셨다면 보고 오시는 것을 추천드립니다.

 

웹 시스템 개발 #NodeJS

학교 공부를 복습할 겸 적는 것이기에 내용이 부족할 수 있습니다. 부족한 것은 상관 없으나, 잘못된 부분이 발견된다면 지적해주시면 감사하겠습니다. Node.js 생성 및 목적 Node.js는 Ryan Dahl이 Joye

wlsdn629.tistory.com


npm (Node Package Manager)

 

npm은 JavaScript 패키지 및 모듈을 설치, 관리, 공유 및 실행하는 것을 담당하는 패키지 관리자입니다.

 

패키지는 JavaScript 코드의 모음으로, 모듈, 라이브러리, 프레임워크, 플러그인 또는 다양한 코드 구성 요소를 번들로 묶은 것이며, 재사용하기 쉽도록 하는데 사용됩니다.

 

npm의 역할

  • 패키지 설치: npm install 패키지-이름 명령어를 사용하여 다른 개발자가 만든 JavaScript 패키지를 쉽게 설치할 수  있습니다.
  • 의존성 관리: 프로젝트의 의존성을 관리하는 역할을 합니다. 개발자는 package.json 파일에 의존성을 지정할 수 있습니다.
  • 스크립트 실행: 개발자는 프로젝트의 package.json 파일에서 스크립트를 정의하고 실행할 수 있습니다. 
  • 패키지 게시: npm을 사용하면 개발자가 자신의 패키지를 공개적으로 또는 개인적으로 게시할 수 있습니다.

 

 


Express란?

 

Express는 Node.js 웹 응용 프로그램을 개발하는 데 사용되는 웹 애플리케이션 프레임워크로서, 웹 및 모바일 애플리케이션을 위한 기능들을 제공합니다.

 

Express에는 다음과 같은 것들이 포함됩니다:

  • 요청 라우팅 (Request Routing): Express는 웹 요청을 처리하고 해당 요청을 어떤 핸들러 함수로 라우팅할 것인지를 정의하는 라우팅 기능을 제공합니다. 
  • 정적 파일 서버 (Static File Server): Express는 정적 파일 (예: 이미지, CSS 파일, JavaScript 파일)을 제공하는 데 사용됩니다. 
  • 뷰 엔진 통합 (View Engine Integration): Express는 다양한 뷰 엔진 (예: Pug, EJS, Handlebars)과의 통합을 지원하여 동적인 웹 페이지를 생성하고 클라이언트에게 제공하는 데 사용됩니다. 

 

설치방법

 

// install Express
$ mkdir myapp
$ cd myapp
$ npm init
$ npm install express

 

설치가 성공적으로 되었다면 다음과 같은 폴더구조가 보입니다.

├── app.js
├── bin
│   └── www
├── package.json
├── public
│   ├── images
│   ├── javascripts 
│   └── stylesheets 
│       └── style.css 
├── routes
│   ├── index.js 
│   └── users.js 
└── views
├── error.pug 
├── index.pug 
└── layout.pug

 

예제

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}!`);
});

 

위 코드는 express로 작성된 코드입니다.

 

const http = require('http');
const server = http.createServer((req, res) => { 
res.end('Hello World\n');
});
server.listen(3000, ‘127.0.0.1’, () => {
console.log(`Server running at http://localhost:3000/`); 
});

 

위 코드는 node로 작성된 코드입니다.

 

차이점을 보면서 알아가시는 것이 좋을 것 같습니다.

 

 

Rounting

라우팅 정의

라우팅(Routing)은 애플리케이션의 엔드포인트(URI)가 클라이언트 '요청에 응답'하는 방식을 나타냅니다. 이것은 URL을 특정 핸들러 함수로 매핑하는 프로세스를 의미합니다.

Express 애플리케이션 객체의 메서드를 사용하여 라우팅을 정의합니다. 예를 들어, GET 요청을 처리하기 위해 app.get()을 사용하고 POST 요청을 처리하기 위해 app.post()를 사용합니다.

 

라우팅 메서드는 HTTP 메서드와 일치하는 콜백 함수(때로는 "핸들러 함수"라고도 함)를 지정합니다. 다른 말로, 애플리케이션은 지정된 라우트(엔드포인트)와 HTTP 메서드에 매치되는 요청을 "대기"하며, 일치하는 요청을 감지하면 지정된 콜백 함수를 호출합니다.

 

다음은 Express에서 라우팅을 정의하는 몇 가지 예시입니다.

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

// GET 요청을 처리하는 라우트
app.get('/', (req, res) => {
  res.send('This is the root page.');
});

// POST 요청을 처리하는 라우트
app.post('/submit', (req, res) => {
  res.send('Submitted successfully.');
});

// 모든 HTTP 메서드를 처리하는 라우트
app.all('/all', (req, res) => {
  res.send('This route handles all HTTP methods.');
});

// 미들웨어를 사용하여 모든 요청을 처리하는 라우트
app.use('/middleware', (req, res, next) => {
  console.log('Middleware function');
  next();
}, (req, res) => {
  res.send('Middleware route.');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000.');
});

 

 

라우팅 콜백 함수

라우팅 메서드는 하나 이상의 콜백 함수를 인수로 가질 수 있습니다. 여러 개의 콜백 함수를 사용할 때는 콜백 함수에 next를 인수로 제공하고, 함수 본문 내에서 next()를 호출하여 제어를 다음 콜백 함수로 전달하는 것이 중요합니다.

 

이러한 기능은 Express에서 미들웨어(Middleware)를 사용하여 처리되며, 미들웨어는 요청과 응답 객체에 대한 처리 단계를 추가하거나 수정할 때 사용됩니다. 

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

// 첫 번째 콜백 함수
app.get('/', (req, res, next) => {
  console.log('First callback function');
  // 다음 콜백 함수로 제어를 전달
  next();
});

// 두 번째 콜백 함수
app.get('/', (req, res) => {
  console.log('Second callback function');
  res.send('Hello World!');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000.');
});

 

라우트 경로 & 파라미터

Route Paths는 요청 메서드와 결합하여 요청을 수행할 수 있는 엔드포인트(Endpoint)를 정의합니다. 라우트 경로는 문자열, 문자열 패턴 또는 정규 표현식일 수 있으며, 클라이언트가 요청을 보낼 때 해당 경로에 일치하는 핸들러 함수를 호출하게 됩니다.

 

Route Parameters는 URL에서 이름이 지정된 URL 세그먼트로, URL의 해당 위치에 지정된 값을 캡처하는 데 사용됩니다. 캡처된 값은 req.params 객체에 저장되며, 라우트 파라미터의 이름은 경로에 지정된 이름과 일치하는 키로 사용됩니다.

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

// 정적 라우트 경로
app.get('/about', (req, res) => {
  res.send('About Page');
});

app.get('/random.text', (req, res) => {
  res.send('Random Text');
});

// 동적 라우트 경로와 파라미터
app.get('/users/:userId/books/:bookId', (req, res) => {
  // req.params를 통해 캡처된 파라미터에 접근
  const userId = req.params.userId;
  const bookId = req.params.bookId;
  res.send(`User ID: ${userId}, Book ID: ${bookId}`);
});

app.listen(3000, () => {
  console.log('Server is running on port 3000.');
});

 

라우트 핸들러

 

라우트 핸들러(Route Handlers)를 사용하여 요청을 처리하는 중에 여러 개의 콜백 함수를 제공할 수 있습니다. 이러한 콜백 함수는 미들웨어(Middleware)처럼 동작하며 요청 처리 중에 특정 작업을 수행할 수 있습니다. 다만, 이러한 콜백 함수는 남은 라우트 콜백을 우회하기 위해 next('route')를 호출할 수 있습니다.

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

app.get('/example/b', (req, res, next) => {
  console.log('The response will be sent by the next function ...');
  next(); // 다음 콜백 함수로 제어를 전달
}, (req, res) => {
  res.send('Hello from B!');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000.');
});

 

 

app.route

 

app.route() 메서드는 Express에서 체인(chain) 형태로 라우트 핸들러를 정의할 수 있게 해주는 메서드입니다. 이를 통해 라우트 경로에 대한 미들웨어 및 핸들러 함수를 더 간결하고 모듈식으로 정의할 수 있습니다. 이 방법을 사용하면 코드의 중복을 줄이고 오타를 방지하는 데 도움이 된다고 합니다.

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

// app.route()를 사용하여 '/example' 경로에 대한 라우트 정의
app.route('/example')
  .get((req, res) => {
    res.send('GET request to /example');
  })
  .post((req, res) => {
    res.send('POST request to /example');
  });

app.listen(3000, () => {
  console.log('Server is running on port 3000.');
});

 

 

express.Router

 

express.Router 클래스를 사용하면 모듈화 및 마운트 가능한 라우트 핸들러를 생성할 수 있습니다. Router 인스턴스는 완전한 미들웨어 및 라우팅 시스템이므로 "미니 앱"으로 불리기도 합니다.

 

라우터를 모듈로 생성하고 미들웨어 함수를 Load하며 몇 가지 라우트를 정의한 다음 라우터 모듈을 주 애플리케이션의 경로에 마운트할 수 있습니다.

// birds.js

const express = require('express');
const router = express.Router();

// 홈 페이지에 대한 핸들러
router.get('/', (req, res) => {
  res.send('홈 페이지');
});

// 정보 페이지에 대한 핸들러
router.get('/info', (req, res) => {
  res.send('정보 페이지');
});

module.exports = router;

 

주 Express 애플리케이션에서 birds.js 라우터 모듈을 사용하도록 설정합니다. /birds 경로에 대한 모든 요청은 birds.js 라우터 모듈로 전달됩니다.

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

// '/birds' 경로에 대한 요청을 'birds.js' 라우터 모듈로 라우팅
const birdsRouter = require('./birds');
app.use('/birds', birdsRouter);

// 서버 시작
const port = 3000;
app.listen(port, () => {
  console.log(`서버가 포트 ${port}에서 실행 중입니다.`);
});

 

이제 브라우저나 API 클라이언트 등에서 다음과 같은 요청을 보낼 수 있습니다.

http://localhost:3000/birds/info와 같이 요청을 보내면 router.get('/info', (req, res) => {...}); 부분이 호출됩니다. 이 부분은 /birds/info 경로에 대한 GET 요청을 처리하도록 정의한 핸들러입니다.

 

즉, /birds 경로로 시작하는 요청은 birds.js 라우터 모듈에 의해 처리되며, 경로에 따라 다른 핸들러 함수가 실행되어 해당 응답이 반환됩니다.

 

 

 

미들웨어란?

 

미들웨어 (Middleware)는 요청과 응답 사이에서 동작하는 중간 소프트웨어 함수입니다. 

 

미들웨어 함수는 다음과 같은 특성을 갖습니다.

  • 미들웨어 함수는 요청 객체(req), 응답 객체(res), 그리고 다음 미들웨어 함수에 대한 액세스 권한을 갖습니다. 
  • 현재의 미들웨어가 요청-응답 주기를 완료하지 않는다면, 반드시 next()를 호출해야 합니다. 이를 통해 제어를 다음 미들웨어로 전달할 수 있습니다.
  • 미들웨어 함수는 Express 애플리케이션의 처리 로직을 여러 단계로 존재할 수 있게 해줍니다.