Express
1. Express란?
Express는 Node.js 기반의 웹 애플리케이션 프레임워크로, 최소한의 기능을 갖추고 있어 빠르고 유연한 웹 애플리케이션 개발이 가능하다.
Node.js의 http 모듈을 직접 사용하는 것보다 더 간결하고 체계적인 방식으로 웹 서버를 구축할 수 있다.
라우팅, 미들웨어, 템플릿 엔진 등의 기능을 제공하여 웹 애플리케이션 개발 과정을 단순화한다.
1.1. Express의 장점
1) 간결한 API
Express는 복잡한 웹 서버 기능을 쉽게 구현할 수 있는 직관적인 API를 제공한다.
기본적인 라우팅부터 미들웨어 체인, 요청/응답 처리까지 명확하고 간결하게 작성할 수 있다.
ex)
// 기본 라우팅 예시
app.get('/', (req, res) => {
res.send('Hello World!');
});
2) 미들웨어 아키텍처
Express의 핵심 기능인 미들웨어 아키텍처는 요청 처리 과정을 모듈화하고 재사용 가능하게 만든다.
또한, 서드파티 미들웨어도 쉽게 통합할 수 있어 기능 확장이 쉽다.
3) 라우팅
URL 경로와 HTTP 메서드에 따라 다양한 핸들러를 연결할 수 있는 유연한 라우팅 시스템을 제공한다.
라우트 매개변수, 쿼리 문자열 등을 쉽게 처리할 수 있다.
4) 성능
Express는 경량화된 프레임워크로, 최소한의 오버헤드만 추가한다.
따라서 Node.js의 빠른 실행 속도와 비동기 특성을 그대로 활용할 수 있다.
2. 미들웨어
미들웨어는 요청과 응답 사이에 위치하는 중간 처리 함수이다.
클라이언트의 요청이 들어오면 최종 응답을 보내기 전에 여러 미들웨어를 순차적으로 실행할 수 있다.
Express 자체 기능 외에도 추가적인 기능을 삽입할 수 있어 애플리케이션의 기능을 확장하고 모듈화할 수 있다.
2.1. 미들웨어의 특징
1) 요청-응답 사이클에서의 역할
미들웨어는 요청 객체(req), 응답 객체(res), 그리고 다음 미들웨어 함수(next)에 접근할 수 있다.
요청 데이터를 처리하거나 변환하고, 응답을 생성하거나 수정할 수 있다.
2) 순서의 중요성
미들웨어는 선언된 순서대로 실행된다.
따라서 미들웨어의 실행 순서가 애플리케이션의 동작에 큰 영향을 미친다.
예를 들어, 인증 미들웨어는 권한이 필요한 라우트 처리 전에 실행되어야 한다.
3) 흐름 제어
next() 함수를 호출하면 다음 미들웨어로 제어가 넘어간다.
next()를 호출하지 않으면 요청-응답 사이클이 중단되고 클라이언트는 응답을 받지 못하게 된다.
next('route')를 호출하면 현재 라우트의 나머지 미들웨어를 건너뛰고 다음 라우트로 이동한다.
4) 오류 처리
next(err)와 같이 인자와 함께 next를 호출하면 일반 미들웨어를 건너뛰고 오류 처리 미들웨어로 제어가 넘어간다.
2.2. 미들웨어 사용 방법
1) 애플리케이션 레벨 미들웨어
app.use() 또는 app.METHOD()를 사용하여 애플리케이션 레벨 미들웨어를 등록한다.
ex)
// 모든 요청에 적용되는 미들웨어
app.use((req, res, next) => {
console.log('Time:', Date.now());
next();
});
// 특정 경로에만 적용되는 미들웨어
app.use('/user', (req, res, next) => {
console.log('Request Type:', req.method);
next();
});
// 특정 HTTP 메서드와 경로에 적용되는 미들웨어
app.get('/user', (req, res, next) => {
res.send('GET 요청을 받았습니다.');
});
2) 라우터 레벨 미들웨어
라우터 인스턴스에 바인딩되는 미들웨어로, 애플리케이션 레벨 미들웨어와 동일한 방식으로 작동한다.
ex)
const router = express.Router();
router.use((req, res, next) => {
console.log('Router 미들웨어 실행');
next();
});
router.get('/user', (req, res) => {
res.send('User 페이지');
});
app.use('/', router);
3) 오류 처리 미들웨어
오류 처리 미들웨어는 일반 미들웨어와 달리 4개의 인자를 받는다.
ex)
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('서버 오류가 발생했습니다.');
});
4) 내장 미들웨어
Express는 몇 가지 내장 미들웨어를 제공한다.
- express.static: 정적 파일 제공
- express.json: JSON 요청 본문 파싱
- express.urlencoded: URL-encoded 요청 본문 파싱
ex)
// 정적 파일 제공
app.use(express.static('public'));
// JSON 요청 본문 파싱
app.use(express.json());
// URL-encoded 요청 본문 파싱
app.use(express.urlencoded({ extended: false }));
3. Express 사용 방법
const express = require('express');
const app = express();
const port = 3000;
// 미들웨어 설정
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// 기본 라우트
app.get('/', (req, res) => {
res.send('Hello World!');
});
// 서버 시작
app.listen(port, () => {
console.log(`서버가 http://localhost:${port} 에서 실행 중입니다.`);
});
// 로깅 미들웨어
app.use((req, res, next) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
next(); // 다음 미들웨어로 제어 이동
});
// 인증 확인 미들웨어
const authenticate = (req, res, next) => {
const authHeader = req.headers.authorization;
if (!authHeader) {
return res.status(401).json({ message: '인증 정보가 필요합니다.' });
// next()를 호출하지 않아 요청 처리가 여기서 중단됨
}
// 인증 토큰 확인 (간단한 예시)
if (authHeader === 'Bearer valid-token') {
req.user = { id: 1, name: '인증된 사용자' };
next(); // 인증 성공, 다음 미들웨어로 이동
} else {
res.status(403).json({ message: '유효하지 않은 인증 정보입니다.' });
// 인증 실패, 다음 미들웨어로 이동하지 않음
}
};
// 권한 확인 미들웨어
const checkAdmin = (req, res, next) => {
if (req.user && req.user.isAdmin) {
next(); // 관리자 권한 있음, 다음 미들웨어로 이동
} else {
res.status(403).json({ message: '관리자 권한이 필요합니다.' });
// 권한 없음, 다음 미들웨어로 이동하지 않음
}
};
// 특정 라우트에만 인증 미들웨어 적용
app.get('/api/public', (req, res) => {
res.json({ message: '공개 데이터입니다.' });
});
app.get('/api/protected', authenticate, (req, res) => {
res.json({
message: '보호된 데이터입니다.',
user: req.user
});
});
app.get('/api/admin', authenticate, checkAdmin, (req, res) => {
res.json({ message: '관리자 데이터입니다.' });
});
이 예시에서 next() 함수는 미들웨어 체인의 흐름을 제어한다.
- 로깅 미들웨어는 항상 next()를 호출하여 모든 요청이 다음 단계로 진행되게 한다.
- 인증 미들웨어는 인증에 성공한 경우에만 next()를 호출한다.
- 권한 확인 미들웨어는 관리자 권한이 있는 경우에만 next()를 호출한다.