HandlerInterceptor
는 Express.js의 기본 기능은 아니지만, 미들웨어와 핸들러 래퍼를 사용하여 인터셉터와 유사한 동작을 구현할 수 있습니다. 이를 통해 요청이 컨트롤러에 도달하기 전과 응답이 준비된 후에 요청을 가로채는 기능을 구현
할 수 있으며, 전처리, 후처리, 오류 처리 등의 작업을 수행할 수 있습니다.
Middleware와 HandlerInterceptor의 차이점
특징 | Middleware | HandlerInterceptor |
---|---|---|
실행 방식 | 라우트에 걸쳐 순차적으로 실행 | 전처리와 후처리를 제공 |
적용 범위 | 전역 또는 특정 라우트에 적용 가능 | 특정 핸들러에 밀접하게 연결 |
사용 사례 | 로깅, 인증, 파싱 등의 일반 작업 | 요청/응답 변환, 예외 처리 등 |
Express.js에서 HandlerInterceptor 구현하기
Express.js에는 기본적으로 인터셉터 기능이 제공되지 않으므로, 전처리, 후처리, 오류 처리를 수행하는 미들웨어를 직접 만들어서 이러한 동작을 흉내 낼 수 있습니다.
1단계: 기본 HandlerInterceptor 만들기
아래는 전처리, 후처리, 오류 처리를 수행하는 간단한 구현 예시입니다.
import { Request, Response, NextFunction } from "express";
// 전처리 함수
function preProcess(req: Request) {
console.log(`[전처리] 요청 처리 중: ${req.url}`);
}
// 후처리 함수
function postProcess(req: Request, res: Response) {
console.log(`[후처리] 응답 상태 코드: ${res.statusCode}`);
}
// 오류 처리 함수
function handleError(err: Error, req: Request, res: Response) {
console.error(`[오류] ${err.message}`);
res
.status(500)
.json({ message: "오류가 발생했습니다", details: err.message });
}
// Handler Interceptor
export function handlerInterceptor(
handler: (req: Request, res: Response, next: NextFunction) => Promise<void>
) {
return async (req: Request, res: Response, next: NextFunction) => {
try {
preProcess(req);
await handler(req, res, next);
postProcess(req, res);
} catch (error) {
handleError(error, req, res);
}
};
}
2단계: 라우트에 HandlerInterceptor 적용하기
import express, { Request, Response } from "express";
import { handlerInterceptor } from "./handlerInterceptor";
const app = express();
// 예시 라우트 핸들러
async function exampleHandler(req: Request, res: Response) {
if (!req.query.name) throw new Error("Name이 필요합니다.");
res.json({ message: `안녕하세요, ${req.query.name}` });
}
// 인터셉터 적용
app.get("/greet", handlerInterceptor(exampleHandler));
app.listen(3000, () => {
console.log("서버가 3000번 포트에서 실행 중입니다.");
});
고급 HandlerInterceptor 기능
1. 다중 인터셉터 적용
다중 인터셉터를 사용하여 각 인터셉터를 순차적으로 실행할 수 있습니다. 이를 통해 더욱 유연하고 재사용 가능한 인터셉터 로직을 구축할 수 있습니다.
type Interceptor = (
req: Request,
res: Response,
next: NextFunction
) => Promise<void>;
export function handlerInterceptors(interceptors: Interceptor[]) {
return (
handler: (req: Request, res: Response, next: NextFunction) => Promise<void>
) => {
return async (req: Request, res: Response, next: NextFunction) => {
try {
for (const interceptor of interceptors) {
await interceptor(req, res, next);
}
await handler(req, res, next);
} catch (error) {
next(error);
}
};
};
}
다중 인터셉터 사용하기
const logInterceptor: Interceptor = async (req, res, next) => {
console.log(`[LogInterceptor] ${req.method} ${req.url}`);
next();
};
const authInterceptor: Interceptor = async (req, res, next) => {
if (!req.headers["authorization"]) {
throw new Error("Unauthorized");
}
next();
};
// 다중 인터셉터 적용
app.get(
"/secure",
handlerInterceptors([logInterceptor, authInterceptor])(async (req, res) => {
res.json({ message: "보안 데이터에 접근했습니다." });
})
);
HandlerInterceptor의 일반적인 사용 사례
- 인증/인가: 라우트에 접근하기 전에 사용자 인증 정보를 검증합니다.
- 로깅: 요청 및 응답에 대한 정보를 수집하여 감사 또는 디버깅 목적으로 사용합니다.
- 데이터 변환: 요청 데이터가 핸들러에 도달하기 전에 변경하거나 응답 데이터를 클라이언트에 전달하기 전에 수정합니다.
- 관심사 분리: 전처리, 후처리, 오류 처리 로직을 명확하게 분리하여 코드를 유지보수하기 쉽게 만듭니다.
- 오류 처리: 인터셉터에서 발생하는 오류를 항상 적절하게 처리하여 애플리케이션의 비정상적인 종료를 방지합니다.
- 체인 가능성: 다중 인터셉터를 사용하여 유연하고 재사용 가능한 로직을 구현합니다.
결론
Express.js는 기본적으로 HandlerInterceptor
기능을 제공하지 않지만, 미들웨어와 함수 래퍼를 사용하여 인터셉터와 유사한 동작을 구현할 수 있습니다. 이를 통해 전처리 및 후처리 로직에 대한 더 큰 제어권을 확보하고 더 모듈화되고 유지보수 가능한 애플리케이션을 구축할 수 있습니다.
이러한 방식으로 Express.js에서 HandlerInterceptor
를 사용하여 요청 및 응답을 효과적으로 관리하고, 향상된 기능을 갖춘 API를 개발할 수 있습니다.
'JavaScript & TypeScript' 카테고리의 다른 글
Node.js와 Express에서 JSON 처리하기 (1) | 2024.12.10 |
---|---|
Express.js에서 CORS 처리 방법 (0) | 2024.12.03 |
CI 환경에서 `npm ci` 명령어를 사용해야 하는 이유 (1) | 2024.11.25 |
Express.js 미들웨어의 역할 (TypeScript 버전) (0) | 2024.11.19 |
JavaScript 모듈 시스템: export와 export default의 차이점 및 사용법 (0) | 2024.11.12 |