generated from ttipo/project-base
Initial commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { ScheduleModule } from '@nestjs/schedule';
|
||||
import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler';
|
||||
import { CacheModule } from '@nestjs/cache-manager';
|
||||
import { APP_GUARD } from '@nestjs/core';
|
||||
|
||||
import { RequestIdMiddleware } from '@/common/middleware/request-id.middleware';
|
||||
import { HealthModule } from '@/modules/health/health.module';
|
||||
import { UploadModule } from '@/modules/upload/upload.module';
|
||||
import { UserModule } from '@/modules/user/user.module';
|
||||
import { parsePositiveInt } from '@/shared/utils/env';
|
||||
import { buildDatabaseOptions } from '@/shared/config/database.config';
|
||||
import { validateEnv } from '@/shared/config/env.validation';
|
||||
import { ShutdownLogger } from '@/shared/logger/shutdown.logger';
|
||||
|
||||
// Rate Limiting 기본 정책 — 루트 .env 의 THROTTLE_* 로 덮어쓸 수 있다 (.claude/rules/env-structure.md)
|
||||
const THROTTLE_DEFAULT_TTL_MS = 60_000; // 집계 구간: 60초
|
||||
const THROTTLE_DEFAULT_LIMIT = 100; // 구간당 IP별 최대 요청 수
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
ScheduleModule.forRoot(),
|
||||
ConfigModule.forRoot({
|
||||
isGlobal: true,
|
||||
envFilePath: `.env.${process.env.NODE_ENV || 'development'}`,
|
||||
// 설정이 잘못되면 조용히 기본값으로 굴러가지 않고 기동 시점에 실패시킨다
|
||||
validate: validateEnv,
|
||||
}),
|
||||
// 전역 캐시 매니저 — Redis 도입 시 store 옵션을 redisStore 로 변경
|
||||
CacheModule.register({
|
||||
isGlobal: true,
|
||||
ttl: 60_000, // 60초 기본 TTL
|
||||
}),
|
||||
// 전역 Rate Limiter — API 남용/브루트포스 방지 (프로젝트의 유일한 rate limiting 수단)
|
||||
// 한도 초과 시 429 → 전역 필터가 REQ_001 로 매핑한다.
|
||||
// 라우트 단위 조정은 @Throttle({ default: { ttl, limit } }), 제외는 @SkipThrottle().
|
||||
ThrottlerModule.forRoot([
|
||||
{
|
||||
// compose 가 미정의 변수를 빈 문자열로 주입하므로 parsePositiveInt 로 방어한다
|
||||
ttl: parsePositiveInt(
|
||||
process.env.THROTTLE_TTL_MS,
|
||||
THROTTLE_DEFAULT_TTL_MS,
|
||||
),
|
||||
limit: parsePositiveInt(
|
||||
process.env.THROTTLE_LIMIT,
|
||||
THROTTLE_DEFAULT_LIMIT,
|
||||
),
|
||||
},
|
||||
]),
|
||||
// DB 접속 설정은 database.config.ts 하나만 수정한다 (CLI 와 공유)
|
||||
TypeOrmModule.forRootAsync({
|
||||
useFactory: () => ({
|
||||
...buildDatabaseOptions(),
|
||||
// Nest 모듈에 등록된 엔티티를 자동으로 수집한다 (CLI 는 glob 경로를 사용)
|
||||
autoLoadEntities: true,
|
||||
}),
|
||||
}),
|
||||
HealthModule,
|
||||
UploadModule,
|
||||
UserModule,
|
||||
],
|
||||
providers: [
|
||||
ShutdownLogger,
|
||||
{
|
||||
provide: APP_GUARD,
|
||||
useClass: ThrottlerGuard,
|
||||
},
|
||||
],
|
||||
})
|
||||
export class AppModule implements NestModule {
|
||||
// 모든 요청에 추적 ID 를 부여한다 (로그·에러 응답 traceId 와 동일 값)
|
||||
configure(consumer: MiddlewareConsumer): void {
|
||||
consumer.apply(RequestIdMiddleware).forRoutes('*');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user