한동안 너무 많은 회사일과, 학교 기말고사 준비로 인해 블로그의 개인적인 정리를 거의 못한거 같다.
일을하면서 회사노션에 정리를 하다보니, 공부한 것들을 올리는 개인 블로그는 어느샌가 관리가 소흘해진 느낌이다. 그래도 공부한것을 기록하기 위해 꾸준이 올리는 연습을 하자.
미들웨어는 클라이언트로부터 들어온 요청을 각 컨트롤러의 요청 핸들러가 처리하기 이전에 코드를 실행할 수 있는 기능입니다. 미들웨어 함수는 애플리케이션의 요청-응답 주기에서 요청(request) 및 응답(response) 객체에 접근할 수 있으며 next()라는 미들웨어 함수를 사용할 수 있습니다. 다음 미들웨어 함수는 일반적으로 next라는 변수로 표시됩니다
또한 주로 아래와 같은 작업을 수행합니다.
쿠키 파싱: 쿠키를 파싱하여 사용하기 쉬운 데이터 구조로 변경합니다. 이를 이용하면 라우터 핸들러가 매번 쿠키를 파싱할 필요가 없습니다.
세션 관리: 세션 쿠키를 찾고, 해당 쿠키에 대한 세션의 상태를 조회해서 요청에 세션 정보를 추가합니다. 이를 통해 다른 핸들러가 세션 객체를 이용할 수 있도록 해 줍니다.
인증/인가: 사용자가 서비스에 접근 가능한 권한이 있는지 확인합니다. 단, Nest는 인가를 구현할 때 가드(Guard)를 이용하도록 권장하고 있습니다.
본문(body) 파싱: 본문은 POST/PUT 요청으로 들어오는 json 타입뿐 아니라 파일 스트림과 같은 데이터도 있습니다. 이 데이터를 유형에 따라 읽고 해석한 다음 파라미터에 넣는 작업을 합니다. 앞서 컨트롤러 장에서 보았던 본문은 이렇게 분석된 결과가 포함되어 있습니다.
import {
ArgumentsHost,
Catch,
Logger,
ExceptionFilter,
HttpException,
InternalServerErrorException
} from '@nestjs/common';
import { Request, Response } from 'express';
@Catch()
export class HttpExceptionFilter implements ExceptionFilter {
private readonly Logger = new Logger(HttpExceptionFilter.name);
catch(exception: Error, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const res = ctx.getResponse<Response>();
const req = ctx.getRequest<Request>();
if (!(exception instanceof HttpException)) {
exception = new InternalServerErrorException();
}
const response = (exception as HttpException).getResponse();
const log = {
timestamp: new Date(),
url: req.url,
response
};
this.Logger.error(log);
res.status((exception as HttpException).getStatus()).json(response);
}
}
프로젝트 진행했던 간단한 HttpExceptionFilter 코드이다. 해당 코드도 Middlewere를 사용한다고 생각하면 된다.
비록 내장된 exception filter 가 자동으로 많은 예외를 처리해주지만, exceptions layer를 완전히 제어하고 싶을 수 있다. 예를 들면, log를 추가해주고 싶다거나, 여러 동적인 요인을 기반으로 다른 JSON schema를 사용하고 싶을 수 있다. 이런 목적을 위해 고안한 것이 Exception filter 이다. 이는 Client에게 보내지는 응답의 내용이나 제어의 정확한 flow를 제어할 수 있게 한다.
Controller 에서 데코레이터로 HttpExceptionFilter 를 사용 할 수 있다.
@Post('uri')
@UseGuards(JwtAuthGuard)
@HttpCode(200)
async 함수명(
@Body() dto: Dto) {
return await this.service.함수명(dto);
}
이런식으로 UseGuards 를 이용하여 JwuAuthGuard를 쓰는것도 Middleware 의 한종류 이며, 전역으로 사용하고 싶으면
@UseFilters(HttpExceptionFilter)
export class Controller {
constructor(private readonly service: AService) {}
이런식으로 클래스 전체에 적용을 하면 된다.