[Clone Coding] What I Learn 4-1 : Dynamic Module & Middleware

먹보·2023년 1월 30일
0

MUK_BO's Clone Coding

목록 보기
4/7

이번 클론코딩 시간에는 방대한 양의 지식이 한꺼번에 흘러들어와..2번에 걸쳐서 정리를 해보려고 한다.

✍ <기술 스택>

  • Programming Language
    TypeScript
  • Framework
    NestJS
  • API 설계
    GraphQL and Apollo
  • Database & Relevant
    PostgresQL & TypeORM

✍ Static Module vs Dynamic Module

📝 Static Module (정적 모듈)

NestJS에서 대표적으로 모듈이 사용되는 방식이며, 정적 모듈 바인딩을 통해 의존성 주입을 할 수 있다.

여기서 의존성 주입을 간단하게 설명하자면, 두 가지 이상의 모듈을 서로 묶어 하나가 다른 하나 이상의 결과 값에 따라 다른 결과를 가지는 것을 뜻한다.
=> 추후, 클론코딩이 종류된 후 NestJS를 더욱 더 깊이 다룰 때 알아보려고 한다.

@Module({
  imports: [AuthService],
  providers: [UsersService, UsersResolver],
  exports: [UsersService],
})

다시 정적모듈 설명으로 돌아와서 상위의 코드는 정적 모듈의 대표적인 예이다.

정적으로 짜여져 있는 코드들을 ImportsExports를 하여 그 내부에 클래스를 인스턴스화 하여 메서드를 쓸 수 있게끔 도와준다.

📝 Dynamic Module (동적 모듈)

정적 모듈 바인딩을 사용하면 사용 모듈이 호스트 모듈의 providers에 영향을 미칠 기회가 없기에 동적 모듈을 통해서 이를 극복합니다.

간단하게 코드를 통해서 설명하자면,

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { UsersResolver } from './users.resolver';
import { UsersService } from './users.service';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: [UsersService, UsersResolver],
  exports: [UsersService],
})
export class UsersModule {}

상기 코드에서 TypeOrmModule은 동적 모듈 역할을 하는데, forFeature이란 메서드를 통해 인자로 어떤 것을 받느냐에 따라 모듈에 영향을 줄 수 있다.

✍ Middleware (미들 웨어)

누구나 다 한 번쯤은 사용해 봤을 법한 미들웨어

필자도 ExpressJS에서 Middleware Function을 만들어 다음과 같이 클라이언트에서 요청이 들어왔을 때 걸러내는 미들웨어를 거치도록 구현한 적이 있다.

const express = require('express');
const { paymentController } = require('../controllers');
const { loginRequired } = require('../utils/auth');

const paymentRoutes = express.Router();

paymentRoutes.post('/approval', loginRequired, paymentController.finalizePayment);

module.exports = { paymentRoutes };

위 코드를 잠깐 보면, paymentControllerfinalizePayment 로직에 접근하기 위해서는 loginRequired라는 미들웨어를 지나야지만 접근이 되므로 로그인을 하지 못한 사람들은 결제를 할 수 없게 된다.

NestJS에서도 비슷하게 Middleware를 설정할 수 있는데 한 가지 큰 차이가 있다면, 구조를 가지고 있기 때문에 정해진 방식으로만 Middleware를 구현 할 수 있다.

그렇기에 다음 코드 예제를 통해서 알아보도록 하자.

📝 NestJs에서 Middleware 구현

// class middleware
@Injectable()
export class JwtMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    if ("x-jwt" in req.headers) {
      const token = req.headers["x-jwt"];
    }
    next();
  }
}

//Class로 Middleware 사용해야 할 시
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(JwtMiddleware).forRoutes({
      path: "/graphql",
      method: RequestMethod.ALL,
    });
  }
}

export function logger(req: Request, res: Response, next: NextFunction) {
  console.log(`Request...`);
  next();
};

//function으로 Middleware 사용해야 할 시 
app.use(logger); 

상위 코드는 Class로 미들웨어를 구현한 것과 function으로 미들웨어를 구현한 것이다.

  • Class Middleware 구현
    1. NestMiddleware(Interface)에서 Class를 Implements 한다.
    2. use()를 활용하여 Middleware 코어 로직 작성
    3. AppModule에서 NestModule을 Implement하여 원하는 설정에 맞춰 Middleware 적용
  • function Middleware 구현
    1. ExpressJS와 동일하게 function 로직 정의
    2. ExpressJS와 동일하게 app.use()로 미들웨어 설정, exclude 조건을 추가하여 특정 path는 무시 할 수 있다.

사실, 위 설명이 전부는 아니지만 알게 된 것을 그나마 간략하게 표현하는 시간을 가지는 것이기 때문에 더욱 자세하게 파고드는 것은 다음 기회에 NestJS 시리즈를 시작하면서 다루게 될 것 같다.

profile
🍖먹은 만큼 성장하는 개발자👩‍💻

0개의 댓글