Node.js/Express

Express 공식 문서 보고 배운 내용 정리

2022. 8. 20. 19:48
목차
  1.  
  2. Express 시작하기
  3. Express 안내서
728x90
여담으로
Express를 사용하게 된 계기:
토스페이먼츠의 결제창을 열고 결제를 완료 한 뒤, 승인하는 과정에서 successUrl과 failUrl이 중간 단계에 필요했다.
Client가 Nuxt 프로젝트로 이루어져 있기 때문에 Url을 3000번 포트로 설정했고, 결제 승인 API 호출을 이 단계에서 해야했기 때문에 3000번과 결제 승인 API 사이에 미들웨어가 필요하여 Express를 사용하게 되었다.
토스페이먼츠 기술지원 디스코드

기술지원 디스코드에서 내가 올린 질문은 아니지만 다른 분이 같은 질문을 하신 것에 대한 답변을 보고 참고하였다.

 

Express 시작하기

Node.js를 위한 웹 애플리케이션 프레임워크. 웹 애플리케이션, API 개발을 위해 설계되었다.

설치

Node.js가 이미 설치되어있다고 가정한 상태에서 다음의 명령어를 입력한다.

mkdir myapp
cd myapp
npm init
npm install express --save
npm install express

Hello world 예제

myapp 디렉토리에 app.js라는 이름의 파일을 작성한 후 다음과 같이 추가한다.

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

node app.js로 실행하면 http://localhost:3000/을 통해 결과를 확인할 수 있다.

Express 애플리케이션 생성

npm install express-generator -g

를 통해 생성할 수 있다고 한다. (Nuxt로 진행 예정이라 생략)

기본 라우팅

라우팅은 URI 및 특정한 HTTP 요청 메소드(GET, POST 등)인 특정 엔드포인트에 대한 클라이언트 요청에 애플리케이션이 응답하는 방법을 결정하는 것

각 라우트는 하나 이상의 핸들러 함수를 가질 수 있으며, 이러한 함수는 라우트가 일치할 때 실행된다.

라우트는 다음과 같은 구조이다.

app.METHOD(PATH, HANDLER)

app은 express의 인스턴스이다.

METHOD는 HTTP 요청 메소드 이다.

PATH는 서버에서의 경로이다.

HANDLER는 라우트가 일치할 때 실행되는 함수이다.

 

예)

app.get('/', function (req, res) {
    res.send('Hello World!');
});
app.post('/', function (req, res) {
	res.send('Got a POST request');
});
app.put('/user', function (req, res) {
    res.send('Got a PUT request at /usser');
});
app.delete('/user', function (req, res) {
    res.send('Got a DELETE request at /user');
});

Express 안내서

라우트 메소드

라우트 메소드는 HTTP 메소드 중 하나로부터 파생되며, express 클래스의 인스턴스에 연결된다.

Express는 HTTP 메소드에 해당하는 다음과 같은 라우팅 메소드를 지원한다. get, post, put, head, delete, options, trace, copy, lock, mkcol, move, purge, profind, proppatch, unlock, report, mkactivity, checkout, merge, m-search, notify, subscribe, unsubscribe, patch, search 및 connect.

 

특수한 라우팅 메소드인 app.all()은 어떠한 HTTP 메소드로부터도 파생되지 않는다. 이 메소드는 모든 요청 메소드에 대해 한 경로에서 미들웨어 함수를 로드하는데 사용된다.

다음 예에서는, GET, POST, PUT 또는 DELETE 메소드를 사용하는 경우, 또는 http 모듈에서 지원되는 기타 모든 HTTP 요청 메소드를 사용하는 경우 등의 "/secret"에 대한 요청을 위하여 핸들러가 실행된다.

app.all('/secret', function (req, res, next) {
    console.log('Accessing the secret section...');
    next();
});

라우트 경로

라우트 경로는, 요청 메소드와의 조합을 통해 요청이 이루어질 수 있는 엔드포인트를 정의한다.

라우트 경로는 문자열, 문자열 패턴 또는 정규식일 수 있다.

 

문자열 기반으로하는 라우트 경로 예시)

app.get('/', function (req, res) {
	res.send('root');
});
app.get('/about', function (req, res) {
    res.send('about');
});
app.get('/random.text', function (req, res) {
    res.send('random.text');
});

문자열 패턴을 기반으로 하는 라우트 경로의 예시)

 

acd 또는 abcd와 일치한다.

app.get('/ab?cd', function (req, res) {
    res.send('ab?cd');
});

abcd, abbcd 또는 abbbcd등과 일치한다.

app.get('ab+cd', function (req, res) {
    res.send('ab+cd');
});

abcd, abxcd, abRABDOMcd 또는 ab123cd 등과 일치한다.

app.get('/ab*cd', function (req, res) {
    res.send('ab*cd');
});

abe 또는 abcde와 일치한다.

app.get('/ab(ce)?e', function (req, res) {
    res.send('ab(cd)?e');
});

정규식을 기반으로 하는 라우트 경로의 예시)

"a"가 포함된 모든 항목과 일치한다.

app.get(/a/, function (req, res) {
    res.send('/a/');
})

butterfly 및 dragonfly와 일치한다.

app.get(/.*fly$/, function (req, res) {
    res.send('/.*fly$/');
});

라우트 핸들러

미들웨어와 비슷하게 작동하는 여러 콜백 함수를 제공하여 요청을 처리할 수 있다. 차이점은 콜백 next('route')를 호출하여 나머지 라우트 콜백을 우회할 수도 있다. 이러한 매커니즘을 이용하면 라우트에 대한 사전 조건을 지정한 후, 현재의 라우트를 계속할 이유가 없는 경우에는 제어를 후속 라우트에 전달할 수 있다.

라우트 핸들러는 함수나 함수 배열의 형태 또는 둘을 조합한 형태일 수 있다.

app.get('/example/a', function (req, res) {
    res.send('Hello from A!');
});

2개 이상의 콜백 함수는 하나의 라우트를 처리할 수 있다. (next 오브젝트를 반드시 지정해야 함)

app.get('/example/b', function (req, res, next) {
    console.log('the response will be sent by the next function ...');
    next();
}, function (req, res) {
    res.send('Hello from B!');
});

하나의 콜백 함수 배열은 하나의 라우트를 처리할 수 있다.

var cb0 = function (req, res, next) {
    console.log('CB0');
    next();
}

var cb1 = function (req, res, next) {
    console.log('CB1');
    next();
}

var cb2 = function (req, res, next) {
    req.send('Hello from C!');
}

app.get('/example/c', [cb0, cb1, cb2]);

응답 메소드

응답 오브젝트에 대한 메소드(res)는 응답을 클라이언트로 전송하고 요청-응답 주기를 종료할 수 있다. 라우트 핸들러로부터 다음 메소드 중 어느 하나도 호출되지 않는 경우, 클라이언트 요청은 정지된 채로 방치된다.

메소드 설명
res.download() 파일이 다운로드 되도록 프롬프트
res.end() 응답 프로세스 종료
res.json() JSON 응답을 전송
res.jsonp() JSONP 지원을 통해 JSON 응답을 전송
res.redirect() 요청의 경로를 재지정
res.render() 보기 템플릿 렌더링
res.send() 다양한 유형의 응답을 전송
res.sendFile() 파일을 옥텟 스트림의 형태로 전송
res.sendStatus() 응답 상태코드를 설정한 후, 해당 코드를 문자열로 표현한 내용을 응답 본문으로서 전송

app.route()

app.route()를 이용하면 라우트 경로에 대하여 체인 가능한 라우트 핸들러를 작성할 수 있다. 경로는 한 곳에 지정되어 있으므로, 모듈식 라우트를 작성하면 중복성과 오타가 감소하여 도움이 된다.

app.route()를 사용하여 정의된 체인 라우트 핸들러의 예는 다음과 같다.

app.route('/book')
    .get(function (req, res) {
        res.send('Get a random book');
    })
    .post(function (req, res) {
        res.send('Add a book');
    })
    .put(function (req, res) {
        res.send('Update the book');
    });

express.Router

express.Router 클래스를 사용하면 모듈식 마운팅 가능한 핸들러를 작성할 수 있다. Router 인스턴스는 완전한 미들웨어이자 라우팅 시스템이며, 따라서 미니 앱이라고 불리는 경우가 많다.

라우터를 모듈로서 작성하고, 라우터 모듈에서 미들웨어 함수를 로드하고, 몇몇 라우트를 정의하고, 기본 앱의 한 경로에 라우터 모듈을 마운트 한다.

예시)

birds.js

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

router.use(function timeLog(req, res, next) {
    console.log('Time: ', Date.now());
    next();
});

router.get('/', function(req, res) {
    res.send('Birds home page');
});

router.get('/about', function(req, res) {
    res.send('About birds');
});

module.exports = router;
var birds = require('./birds');

app.use('/birds', birds);

Express 앱에서 사용하기 위한 미들웨어 작성

미들웨어 함수는 요청 오브젝트(req), 응답 오브젝트(res), 그리고 애플리케이션의 요청-응답 주기 중 그 다음의 미들웨어 함수에 대한 권한을 갖는 함수이다. 그 다음의 미들웨어 함수는 일반적으로 next라는 이름의 변수로 표시된다.

미들웨어 함수는 다음과 같은 태스크를 수행할 수 있다.

  • 모든 코드를 실행
  • 요청 및 응답 오브젝트에 대한 변경을 실행
  • 요청-응답 주기를 종료
  • 스택 내의 그 다음 미들웨어를 호출

현재의 미들웨어 함수가 요청-응답 주기를 종료하지 않는 경우에는 next()를 호출하여 그 다음 미들웨어 함수에 제어를 전달해야 한다. 그렇지 않으면 해당 요청은 정지된 상태로 방치된다.

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

app.get('/', function (req, res, next) {
    res.send('Hello World');
});

app.listen
  • get: 미들웨어 함수가 적용되는 HTTP 메소드
  • '/': 미들웨어 함수가 적용되는 경로(라우트)
  • function: 미들웨어 함수
  • req: 미들웨어 함수에 대한 HTTP 요청 인수(일반적으로 "req"라 불림)
  • res: 미들웨어 함수에 대한 HTTP 응답 인수(일반적으로 "res"라 불림)
  • next: 미들웨어 함수에 대한 콜백 인수(일반적으로 "next"라 불린다.)

미들웨어 함수를 로드하려면 미들웨어 함수를 지정하여 app.use()를 호출한다. 루트경로('/')로 라우팅하기 전에 myLogger미들웨어 함수를 로드한다.

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

var myLogger = function (req, res, next) {
    console.log('LOGGED');
    next();
};

app.use(myLogger);

app.get('/', function (req, res) {
    res.send('Hello World!');
});

app.listen(3000);

미들웨어의 로드 순서는 중요하다. 먼저 로드되는 미들웨어 함수가 먼저 실행되고 루트 경로에 대한 라우팅 이후에 myLogger가 로드되면, 루트 경로의 라우트 핸들러가 요청-응답 주기를 종료하므로 요청은 절대로 myLogger에 도달하지 못한다.

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

var requestTime = function (req, res, next) {
    req.requestTime = Date.now();
    next();
};

app.use(requestTime);

app.get('/', function (req, res) {
    var responseText = 'Hello World!';
    responseText += 'Requested at: ' + req.requestTime + '';
    res.send(responseText);
}

app.listen(3000);​

 

 

사용자는 req, res, 스택 내의 그 다음 미들웨어 함수, 그리고 모든 Node.js API에 대한 액세스 권한을 가지고 있다.

미들웨어 사용

Express 애플리케이션은 다음과 같은 유형의 미들웨어를 사용할 수 있다.

  • 애플리케이션 레벨 미들웨어
  • 라우터 레벨 미들웨어
  • 오류 처리 미들웨어
  • 기본 제공 미들웨어
  • third party 미들웨어

애플리케이션 레벨 미들웨어

마운트 경로가 없는 미들웨어 함수, 앱이 요청을 수신할 때마다 실행된다.

var app = express();

app.use(function (req, res, next) {
    console.log('Time: ', Date.now());
    next();
});

/user/:id 경로에 대한 모든 유형의 HTTP 요청에 대해 실행된다.

app.use('/user/:id', function (req, res, next) {
    console.log('Request Type:', req.method);
});

use 대신 get이 쓰이면 GET요청으로 들어온 것에 대한 url을 처리한다.

 

하나의 마운트 경로를 통해 일련의 미들웨어 함수를 하나의 마운트 위치에 로드하는 예)

app.use('/user/:id', function (req, res, next) {
    console.log('Request URL: ', req.originalURL);
    next();
}, function (req, res, next) {
    console.log('Request Type: ', req.method);
    next();
});

라우터 핸들러를 이용하면 하나의 경로에 대해 여러 라우트를 정의할 수 있다. 

app.get('/user/:id', function (req, res, next) {
    if (req.params.id == 0) next('route');
    else next();
}, function (req, res, next) {
    res.render('regular');
});

app.get('/user/:id', function (req, res, next) {
    res.render('special');
});

라우터 레벨 미들웨어

라우터 레벨 미들웨어는 express.Router() 인스턴스에 바인드된다는 점을 제외하면 애플리케이션 레벨 미들웨어와 동일한 방식으로 작동한다.

var app = express();
var router = express.Router();

router.use(function (req, res, next) {
    console.log('Time: ', Date.now());
    next();
});

router.use('/user/:id', function (req, res, next) {
    console.log('Request URL: ', req.originalUrl);
    next();
}, function (req, res, next) {
    console.log('Request Type: ', req.method);
    next();
});

router.get('/user/:id', funtion (req, res, next) {
    if (req.params.id == 0) next('route');
    else next();
}, function (req, res, next) {
    res.render('regular');
});

router.get('/user/:id', function (req, res, next) {
    console.log(req.params.id);
    res.render('special');
});

app.use('/', router);

오류 처리 미들웨어

다른 미들웨어 함수와 동일한 방법으로 다음과 같이 오류 처리 미들웨어 함수를 정의할 수 있지만, 오류 처리 함수는 3개가 아닌 4개의 인수, (err, req, res, next) 를 갖는다는 점이 다르다.

third party 미들웨어

필요한 기능을 위한 Node.js 모듈을 설치한 후, 애플리케이션 레벨 또는 라우터 레벨에서 해당 모듈을 앱에 로드한다.

예) 쿠키 구문 분석 미들웨어 함수인 cookie-parser의 설치 및 로드를 나타낸다.

npm install cookie-parser
var express = require('express');
var app = express();
var cookieParser = require('cookie-parser');

app.use(cookieParser());

오류 처리

오류 처리 미들웨어는 다른 app.use() 및 라우트 호출을 정의한 후에 마지막으로 정의해야 한다.

var bodyParser = require('body-parser');
var methodOverride = require('method-override');

app.use(bodyParser());
app.use(methodOverride());
app.use(function (err, req, res, next) {
    // logic
});

미들웨어 함수 내부로부터의 응답은 HTML 오류 페이지, 단순한 메시지 또는 JSON 문자열 등 선호하는 모든 형식일 수 있다.

예를 들어 XHR을 이용한 요청 및 그렇지 않은 요청에 대한 오류 처리를 정의하려는 경우, 다음의 예제처럼 사용할 수 있다.

var bodyParser = require('body-parser');
var methodOverride = require('method-override');

app.use(bodyParser());
app.use(methodOverride());
app.use(logErrors);
app.use(clientErrorHandler);
app.use(errorHandler);

logErrors는 요청 및 오류 정보를 stderr에 기록할 수 있다.

function logErrors (err, req, res, next) {
    console.error(err.stack);
    next(err);
}

clientErrorHandler는 다음 항목으로 전달된다.

function clientErrorHandler(err, req, res, next) {
    if (req.xhr) {
        res.status(500).send({ error: 'Something failed!' });
    } else {
        next(err);
    }
}

errorHandler 함수는 다음과 같이 구현될 수 있다.

function errorHandler(err, req, res, next) {
    res.status(500);
    res.render('error', { error: err });
}

next() 함수로 어떠한 내용을 전달하는 경우 ('route'라는 문자열을 제외하고) Express는 현재 요청에 오류가 있는 것으로 간주하며, 오류 처리와 관련되지 않은 나머지 라우팅 및 미들웨어 함수를 건너뛴다. 이러한 오류를 어떻게든 처리하기 원하는 경우 오류 처리 라우트를 작성해야한다. 여러 콜백 함수를 갖는 라우트 핸들러가 있는 경우에는 route 매개변수를 사용하여 그 다음의 라우트 핸들러로 건너뛸 수 있다.

app.get('/a_route_behind_paywall',
    function checkIfPaidSubscriber (req, res, next) {
        if (!req.user.hasPaid) {
            next('route');
        }
    }, function getPaidContent (req, res, next) {
        PaidContent.rind(function (err, doc) {
            if (err) return next(err);
            res.json(doc);
        }
    }

이 예시에서 getPaidContent 핸들러의 실행은 건너뛰지만, /a_route_behind_paywall에 대한 app 내의 나머지 핸들러는 계속 실행한다.

데이터베이스 연결 방법

MySQL

모듈 mysql 설치

npm install mysql

예제

var mysql = require('mysql');
var connection = mysql.createConnection({
    host        : 'localhost',
    user        : 'dbuser',
    password    : 's3kreee7'
});

connection.connect();

connection.query('SELECT 1 + 1 AS solution', function (err, rows, fields) {
    if (err) throw err;
    console.log('The solution is: ', rows[0].solution);
});

connection.end();

 


 

Reference

https://expressjs.com/ko/

 

 

 

728x90

'Node.js > Express' 카테고리의 다른 글

[Express] alert 띄우기(+한글 깨짐 해결)  (0) 2022.08.30
  1.  
  2. Express 시작하기
  3. Express 안내서
'Node.js/Express' 카테고리의 다른 글
  • [Express] alert 띄우기(+한글 깨짐 해결)
mean-ji
mean-ji
저년차 기록들mean-ji 님의 블로그입니다.
mean-ji
저년차 기록들
mean-ji
전체
오늘
어제
  • 분류 전체보기 (104)
    • 소개 (1)
    • Server (25)
      • DevOps (9)
      • Database (4)
    • Spring (11)
    • Spring Boot (0)
    • Java (6)
    • Kotlin (3)
    • Vue.js (12)
      • Nuxt (12)
    • Node.js (3)
      • Express (2)
    • Python (9)
      • Flask (2)
    • Git (9)
    • IDE & Tool (4)
    • TIL (16)
    • 생각 (2)
    • 토스 (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

최근 댓글

최근 글

hELLO · Designed By 정상우.
mean-ji
Express 공식 문서 보고 배운 내용 정리
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.