Skip to main content Skills Marketplace 커뮤니티가 만든 AI 스킬을 발견하고 탐색하세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/InugamiDev/ultrathink-oss --skill nestjs명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Zip 다운로드 다운로드 중... 이 저장소의 다른 Skills Unified design foundations — design system architecture, tokens, component specs, visual principles, creative vision, figma integration, plus brand design system loader (66 real brands via DESIGN.md). Absorbs design, design-system, design-systems, design-principles, design-router, creative-vision, figma, design-md.
Render, summarize, and present markdown documents and structured content in multiple output modes
Ultra UI skill - combines Google's DESIGN.md spec (machine-readable design tokens) with the ui-ux-pro-max knowledge base (91 styles, 161 palettes, 73 font pairings, 161 products, 104 UX guidelines, 25 chart types). Generates lint-clean DESIGN.md files, validates token references and WCAG contrast, exports Tailwind/DTCG tokens, and diffs design systems version-over-version.
name nestjs description NestJS framework patterns — modules, providers, guards, interceptors, pipes, and microservices. layer domain category backend triggers ["nestjs","nest module","nest guard","nest interceptor","nest pipe"] inputs ["NestJS application architecture decisions","Module and provider organization","Guard and interceptor implementation","Microservice communication patterns"] outputs ["NestJS modules with proper dependency injection","Guards, interceptors, and pipes","Controller and service implementations","Microservice transport configurations"] linksTo ["typescript-patterns","graphql","websockets","microservices"] linkedFrom ["dependency-injection"] preferredNextSkills ["typescript-patterns","graphql","microservices"] fallbackSkills ["fastapi","hono"] riskLevel low memoryReadPolicy selective memoryWritePolicy none sideEffects []
NestJS Framework Patterns
Purpose
Provide expert guidance on NestJS application architecture including module organization, dependency injection, request lifecycle (guards, interceptors, pipes, filters), microservice patterns, and production deployment. Covers NestJS 10+ with modern decorators and TypeScript strict mode.
Module Architecture
Organize by domain, not technical concern:
src/
app.module.ts
main.ts
common/
decorators/
filters/
guards/
interceptors/
pipes/
config/
config.module.ts
config.service.ts
users/
users.module.ts
users.controller.ts
users.service.ts
users.repository.ts
dto/
create-user.dto.ts
update-user.dto.ts
entities/
user.entity.ts
orders/
orders.module.ts
orders.controller.ts
orders.service.ts
...
Module definition with proper imports/exports:
import { Module } from '@nestjs/common' ;
import { TypeOrmModule } from '@nestjs/typeorm' ;
import { UsersController } from './users.controller' ;
import { UsersService } from './users.service' ;
import { User } from './entities/user.entity' ;
@Module ({
imports : [TypeOrmModule .forFeature ([User ])],
controllers : [UsersController ],
providers : [UsersService ],
exports : [UsersService ],
})
{}
export
class
UsersModule
Controllers — Keep Thin Controllers handle HTTP concerns only. Delegate all business logic to services:
import {
Controller , Get , Post , Put , Delete ,
Param , Body , Query , HttpCode , HttpStatus ,
ParseIntPipe , UseGuards ,
} from '@nestjs/common' ;
import { ApiTags , ApiOperation , ApiBearerAuth } from '@nestjs/swagger' ;
import { JwtAuthGuard } from '../common/guards/jwt-auth.guard' ;
import { UsersService } from './users.service' ;
import { CreateUserDto } from './dto/create-user.dto' ;
import { UpdateUserDto } from './dto/update-user.dto' ;
import { PaginationDto } from '../common/dto/pagination.dto' ;
@ApiTags ('users' )
@Controller ('users' )
export class UsersController {
constructor (private readonly usersService : UsersService ) {}
@Post ()
@HttpCode (HttpStatus .CREATED )
@ApiOperation ({ summary : 'Create a new user' })
create (@Body () createUserDto : CreateUserDto ) {
return this .usersService .create (createUserDto);
}
@Get ()
@UseGuards (JwtAuthGuard )
@ApiBearerAuth ()
findAll (@Query () pagination : PaginationDto ) {
return this .usersService .findAll (pagination);
}
@Get (':id' )
@UseGuards (JwtAuthGuard )
findOne (@Param ('id' , ParseIntPipe) id : number ) {
return this .usersService .findOneOrFail (id);
}
@Put (':id' )
@UseGuards (JwtAuthGuard )
update (
@Param ('id' , ParseIntPipe) id : number ,
@Body () updateUserDto : UpdateUserDto ,
) {
return this .usersService .update (id, updateUserDto);
}
@Delete (':id' )
@UseGuards (JwtAuthGuard )
@HttpCode (HttpStatus .NO_CONTENT )
remove (@Param ('id' , ParseIntPipe) id : number ) {
return this .usersService .remove (id);
}
}
Services — Business Logic Layer
import { Injectable , NotFoundException , ConflictException } from '@nestjs/common' ;
import { InjectRepository } from '@nestjs/typeorm' ;
import { Repository } from 'typeorm' ;
import { User } from './entities/user.entity' ;
import { CreateUserDto } from './dto/create-user.dto' ;
import { PaginationDto } from '../common/dto/pagination.dto' ;
@Injectable ()
export class UsersService {
constructor (
@InjectRepository (User)
private readonly userRepo : Repository <User >,
) {}
async create (dto : CreateUserDto ): Promise <User > {
const exists = await this .userRepo .findOneBy ({ email : dto.email });
if (exists) {
throw new ConflictException ('Email already registered' );
}
const user = this .userRepo .create (dto);
return this .userRepo .save (user);
}
async findAll (pagination : PaginationDto ) {
const [items, total] = await this .userRepo .findAndCount ({
skip : (pagination.page - 1 ) * pagination.limit ,
take : pagination.limit ,
order : { createdAt : 'DESC' },
});
return { items, total, page : pagination.page , limit : pagination.limit };
}
async findOneOrFail (id : number ): Promise <User > {
const user = await this .userRepo .findOneBy ({ id });
if (!user) throw new NotFoundException (`User #${id} not found` );
return user;
}
async update (id : number , dto : Partial <CreateUserDto >): Promise <User > {
const user = await this .findOneOrFail (id);
Object .assign (user, dto);
return this .userRepo .save (user);
}
async remove (id : number ): Promise <void > {
const result = await this .userRepo .delete (id);
if (result.affected === 0 ) {
throw new NotFoundException (`User #${id} not found` );
}
}
}
DTOs with Validation
import { IsEmail , IsString , MinLength , MaxLength } from 'class-validator' ;
import { ApiProperty } from '@nestjs/swagger' ;
export class CreateUserDto {
@ApiProperty ({ example : 'user@example.com' })
@IsEmail ()
email : string ;
@ApiProperty ({ example : 'Jane Doe' })
@IsString ()
@MinLength (1 )
@MaxLength (100 )
name : string ;
@ApiProperty ({ minLength : 8 })
@IsString ()
@MinLength (8 )
password : string ;
}
import { PartialType } from '@nestjs/swagger' ;
import { CreateUserDto } from './create-user.dto' ;
export class UpdateUserDto extends PartialType (CreateUserDto ) {}
Guards JWT authentication guard:
import { Injectable , ExecutionContext , UnauthorizedException } from '@nestjs/common' ;
import { AuthGuard } from '@nestjs/passport' ;
import { Reflector } from '@nestjs/core' ;
import { IS_PUBLIC_KEY } from '../decorators/public.decorator' ;
@Injectable ()
export class JwtAuthGuard extends AuthGuard ('jwt' ) {
constructor (private reflector : Reflector ) {
super ();
}
canActivate (context : ExecutionContext ) {
const isPublic = this .reflector .getAllAndOverride <boolean >(IS_PUBLIC_KEY , [
context.getHandler (),
context.getClass (),
]);
if (isPublic) return true ;
return super .canActivate (context);
}
handleRequest (err : any , user : any ) {
if (err || !user) {
throw err || new UnauthorizedException ();
}
return user;
}
}
import { Injectable , CanActivate , ExecutionContext } from '@nestjs/common' ;
import { Reflector } from '@nestjs/core' ;
import { ROLES_KEY } from '../decorators/roles.decorator' ;
@Injectable ()
export class RolesGuard implements CanActivate {
constructor (private reflector : Reflector ) {}
canActivate (context : ExecutionContext ): boolean {
const requiredRoles = this .reflector .getAllAndOverride <string []>(ROLES_KEY , [
context.getHandler (),
context.getClass (),
]);
if (!requiredRoles) return true ;
const { user } = context.switchToHttp ().getRequest ();
return requiredRoles.some ((role ) => user.roles ?.includes (role));
}
}
Interceptors
import {
Injectable , NestInterceptor , ExecutionContext , CallHandler , Logger ,
} from '@nestjs/common' ;
import { Observable , tap } from 'rxjs' ;
@Injectable ()
export class LoggingInterceptor implements NestInterceptor {
private readonly logger = new Logger (LoggingInterceptor .name );
intercept (context : ExecutionContext , next : CallHandler ): Observable <any > {
const req = context.switchToHttp ().getRequest ();
const { method, url } = req;
const start = Date .now ();
return next.handle ().pipe (
tap (() => {
const duration = Date .now () - start;
this .logger .log (`${method} ${url} — ${duration} ms` );
}),
);
}
}
Transform response interceptor:
import { Injectable , NestInterceptor , ExecutionContext , CallHandler } from '@nestjs/common' ;
import { Observable , map } from 'rxjs' ;
export interface ApiResponse <T> {
data : T;
meta ?: Record <string , any >;
}
@Injectable ()
export class TransformInterceptor <T> implements NestInterceptor <T, ApiResponse <T>> {
intercept (context : ExecutionContext , next : CallHandler ): Observable <ApiResponse <T>> {
return next.handle ().pipe (map ((data ) => ({ data })));
}
}
Pipes Custom validation pipe with whitelist:
import { ValidationPipe } from '@nestjs/common' ;
app.useGlobalPipes (
new ValidationPipe ({
whitelist : true ,
forbidNonWhitelisted : true ,
transform : true ,
transformOptions : {
enableImplicitConversion : true ,
},
}),
);
Exception Filters
import {
ExceptionFilter , Catch , ArgumentsHost , HttpException , HttpStatus , Logger ,
} from '@nestjs/common' ;
import { Request , Response } from 'express' ;
@Catch ()
export class AllExceptionsFilter implements ExceptionFilter {
private readonly logger = new Logger (AllExceptionsFilter .name );
catch (exception : unknown , host : ArgumentsHost ) {
const ctx = host.switchToHttp ();
const response = ctx.getResponse <Response >();
const request = ctx.getRequest <Request >();
const status =
exception instanceof HttpException
? exception.getStatus ()
: HttpStatus .INTERNAL_SERVER_ERROR ;
const message =
exception instanceof HttpException
? exception.getResponse ()
: 'Internal server error' ;
this .logger .error (`${request.method} ${request.url} ` , exception);
response.status (status).json ({
statusCode : status,
message : typeof message === 'string' ? message : (message as any ).message ,
timestamp : new Date ().toISOString (),
path : request.url ,
});
}
}
Custom Decorators
import { SetMetadata } from '@nestjs/common' ;
export const IS_PUBLIC_KEY = 'isPublic' ;
export const Public = ( ) => SetMetadata (IS_PUBLIC_KEY , true );
import { SetMetadata } from '@nestjs/common' ;
export const ROLES_KEY = 'roles' ;
export const Roles = (...roles : string [] ) => SetMetadata (ROLES_KEY , roles);
import { createParamDecorator, ExecutionContext } from '@nestjs/common' ;
export const CurrentUser = createParamDecorator (
(data : string | undefined , ctx : ExecutionContext ) => {
const request = ctx.switchToHttp ().getRequest ();
return data ? request.user ?.[data] : request.user ;
},
);
Configuration with ConfigModule
import { Module } from '@nestjs/common' ;
import { ConfigModule as NestConfigModule } from '@nestjs/config' ;
import * as Joi from 'joi' ;
@Module ({
imports : [
NestConfigModule .forRoot ({
isGlobal : true ,
validationSchema : Joi .object ({
NODE_ENV : Joi .string ().valid ('development' , 'production' , 'test' ).default ('development' ),
PORT : Joi .number ().default (3000 ),
DATABASE_URL : Joi .string ().required (),
JWT_SECRET : Joi .string ().required (),
JWT_EXPIRATION : Joi .string ().default ('1h' ),
}),
}),
],
})
export class AppConfigModule {}
Best Practices
One module per domain — Keep modules focused on a single bounded context.
Export only what is needed — Minimize the module's public API surface.
Use constructor injection — Avoid property injection; it is harder to test.
Global guards/interceptors via APP_GUARD — Register in app.module.ts providers.
Use DTOs for all input — Never trust raw @Body() without validation.
Custom exceptions extend HttpException — Maintain consistent error contracts.
Use @nestjs/config for env vars — Validate at startup with Joi.
Scope providers carefully — Default singleton scope; use REQUEST scope only when necessary.
Use @nestjs/swagger — Auto-generate API docs from DTOs and decorators.
Test with @nestjs/testing — Use Test.createTestingModule() for isolated unit tests.
Common Pitfalls Pitfall Problem Fix Circular dependency Two modules importing each other Use forwardRef() or extract shared logic to a third module Missing @Injectable() Provider not recognized by DI Always decorate services with @Injectable() REQUEST scope leak Entire dependency chain becomes request-scoped Minimize REQUEST-scoped providers; use @Inject(REQUEST) sparingly No whitelist: true Extra properties pass validation Set whitelist and forbidNonWhitelisted in global ValidationPipe Heavy controllers Controllers contain business logic Move logic to services; controllers handle HTTP only Forgetting async Promise returned but not awaited All DB operations should be async/await