NestJS - 개념 및 기본 사용방법
왜 Nest.js를 사용할까?
> NestJS의 아키텍처 계층
보통 node.js로 백엔드 개발을 할때 가장 유명한 프레임워크는 Express.js이다.
하지만 Express.js는 정해진 아키텍처가 없기에 개발자마다 다른 구조로 작성하게 되는 장점이자, 단점인 유연성으로 아키텍처가 잘 구조화된 프로젝트 일지라도 프로젝트가 커지면 커질수록 유지보수가 어려워지고, 확장성이 떨어진다.
이러한 문제를 해결하기 위해 Nest.js가 등장했다.
Nest.js는 Angular의 아키텍처와 구조를 기반으로 하며, 모듈화, 의존성 주입, 데코레이터 등의 개념을 도입하여 코드의 구조를 명확하게 하고 유지보수성을 높인다.
또한, Nest.js는 Express.js를 기반으로 하기 때문에 Express.js의 기능을 모두 사용할 수 있으며, 추가적으로 WebSocket, GraphQL, Microservices 등의 기능을 제공한다. NestJS는 TypeScript를 사용하여 효율적이고 확장 가능한 Node.js 서버 사이드 애플리케이션을 구축하기 위한 프레임워크이다.
NestJS의 핵심 요소
구분 | 내용 |
---|---|
주요 특징 |
|
주요 기능 |
|
사용 사례 |
|
장점 |
|
단점 |
|
대체 기술 |
|
보다 자세한 내용은 Nest.js 공식 문서를 참고하자.
동작 방식(라이프 사이클)
NestJS는 다음과 같은 라이프 사이클을 가진다:
각 단계별 상세 설명
1. Client Side -> HTTP Request
- 클라이언트 측에서
HTTP 요청
을 시작 합니다.
2. 미들웨어 (Middleware)
- 요청은 먼저 미들웨어를 통과합니다.
- 미들웨어는 요청을
전처리
하는 역할을 합니다.
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: NextFunction) {
console.log(`Request to ${req.path}`);
next(); // 다음 단계로 진행
}
}
3. 가드 (Guards)
- 가드(Guard)는 주로
인증/인가
를 담당합니다. - 요청이 특정 핸들러에 접근할 수 있는지 권한을 검사합니다.
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest();
return this.validateRequest(request);
}
private validateRequest(request: any) {
// 인증 로직 구현
return true;
}
}
4. 인터셉터 (Interceptors - Before)
- 인터셉터는
요청과 응답을 가로채서 변형
할 수 있습니다. - 요청 처리 전에 먼저 실행됩니다.
@Injectable()
export class TransformInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
// 요청 처리 전
console.log("Before...");
return next.handle().pipe(
map((data) => {
// 응답 데이터 변환
return { data, timestamp: new Date() };
})
);
}
}
5. 파이프 (Pipes)
- 파이프는
데이터 변환과 유효성 검사
를 수행합니다. - 예를 들어, 문자열을 숫자로 변환하거나 DTO 유효성을 검사합니다.
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { ValidationPipe } from "@nestjs/common";
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // DTO에 정의되지 않은 속성 제거
forbidNonWhitelisted: true, // DTO에 정의되지 않은 속성이 있으면 요청 거부
transform: true, // 요청 데이터를 DTO 타입으로 자동 변환
})
);
await app.listen(process.env.PORT ?? 8080);
}
bootstrap();
결론
NestJS는 대규모 애플리케이션 개발에 적합한 프레임워크로, TypeScript를 기반으로 하며 모듈화된 아키텍처와 의존성 주입 시스템을 제공한다. 또한 다양한 기능과 라이브러리 통합을 지원하며, 확장성과 유지보수성이 뛰어나다. 하지만 학습 곡선이 상대적으로 높고, 초기 설정 및 구성이 복잡할 수 있다. 따라서 대규모 프로젝트나 마이크로서비스 아키텍처를 구축하는 경우에 적합하며, 작은 규모의 프로젝트나 간단한 웹 애플리케이션에는 Express.js나 Fastify와 같은 가벼운 프레임워크를 고려할 수 있다.