made-by-AI

NestJS ์™„์ „์ •๋ณต NestJS์— ๋‚ด์žฅ๋˜์–ด ์žˆ๋Š” ๊ธฐ๋Šฅ๋“ค

sila_kr 2025. 6. 8. 22:44
๋ฐ˜์‘ํ˜•

๐Ÿ› ๏ธ NestJS ๋‚ด์žฅ ๊ธฐ๋Šฅ ์™„์ „ ์ •๋ณต

๐Ÿ“‹ ํ•ต์‹ฌ ์š”์•ฝ

• Guards & Interceptors • Pipes & Filters • ๋ฏธ๋“ค์›จ์–ด • ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ • ์˜ˆ์™ธ ์ฒ˜๋ฆฌ • ์œ ํšจ์„ฑ ๊ฒ€์ฆ • ์บ์‹ฑ • ์Šค์ผ€์ค„๋ง

NestJS๋Š” ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ๊ธ‰ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๋‹ค์–‘ํ•œ ๊ธฐ๋Šฅ๋“ค์„ ๋‚ด์žฅํ•˜๊ณ  ์žˆ์–ด, ๊ฐœ๋ฐœ์ž๊ฐ€ ๋ณ„๋„์˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—†์ด๋„ ๊ฐ•๋ ฅํ•œ ๋ฐฑ์—”๋“œ ์„œ๋น„์Šค๋ฅผ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿš€ ์ด๋Ÿฌํ•œ ๋‚ด์žฅ ๊ธฐ๋Šฅ๋“ค์€ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํŒจํ„ด๊ณผ ์˜์กด์„ฑ ์ฃผ์ž…์„ ํ†ตํ•ด ์„ ์–ธ์ ์ด๊ณ  ์ง๊ด€์ ์ธ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํŠนํžˆ ์š”์ฒญ ๋ผ์ดํ”„์‚ฌ์ดํด ๊ด€๋ฆฌ๋ฅผ ์œ„ํ•œ Guards, Interceptors, Pipes, Filters ๋“ฑ์˜ ๊ธฐ๋Šฅ๋“ค์€ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ๊ณผ ๋ชจ๋“ˆํ™”๋ฅผ ๊ทน๋Œ€ํ™”ํ•˜๋ฉฐ, ํšก๋‹จ ๊ด€์‹ฌ์‚ฌ(Cross-cutting Concerns)๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. โšก


๐Ÿ” Guards - ์ธ์ฆ๊ณผ ์ธ๊ฐ€

Guards๋Š” ์š”์ฒญ์ด ๋ผ์šฐํŠธ ํ•ธ๋“ค๋Ÿฌ์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ์‹คํ–‰๋˜๋Š” ๋ณด์•ˆ ๊ณ„์ธต์ž…๋‹ˆ๋‹ค. ๐Ÿ›ก๏ธ ์ฃผ๋กœ ์ธ์ฆ(Authentication)๊ณผ ์ธ๊ฐ€(Authorization)๋ฅผ ๋‹ด๋‹นํ•˜๋ฉฐ, CanActivate ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

 

์นดํ…Œ๊ณ ๋ฆฌ Guard ์œ ํ˜• ์‚ฌ์šฉ ๋ชฉ์  ์ ์šฉ ๋ฒ”์œ„
ํ•ต์‹ฌ ๊ธฐ๋Šฅ AuthGuard ์‚ฌ์šฉ์ž ์ธ์ฆ ํ™•์ธ โœ… ๊ธ€๋กœ๋ฒŒ/์ปจํŠธ๋กค๋Ÿฌ/๋ฉ”์„œ๋“œ
ํ•ต์‹ฌ ๊ธฐ๋Šฅ RolesGuard ์—ญํ•  ๊ธฐ๋ฐ˜ ์ ‘๊ทผ ์ œ์–ด โœ… ๋ฉ”์„œ๋“œ๋ณ„ ์„ธ๋ฐ€ ์ œ์–ด
์„ฑ๋Šฅ ๊ด€๋ จ ThrottlerGuard API ํ˜ธ์ถœ ์ œํ•œ โœ… DDoS ๋ฐฉ์–ด
๊ฐœ๋ฐœ ๊ฒฝํ—˜ JwtAuthGuard JWT ํ† ํฐ ๊ฒ€์ฆ โœ… ๋ฌด์ƒํƒœ ์ธ์ฆ


๐Ÿ”„ Interceptors - ์š”์ฒญ/์‘๋‹ต ๋ณ€ํ™˜

Interceptors๋Š” AOP(Aspect-Oriented Programming) ํŒจํ„ด์„ ๊ตฌํ˜„ํ•˜์—ฌ ์š”์ฒญ ์ „ํ›„ ์ฒ˜๋ฆฌ ๋กœ์ง์„ ๊น”๋”ํ•˜๊ฒŒ ๋ถ„๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค. ๐Ÿ”„ NestInterceptor ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ, ๋กœ๊น…, ์บ์‹ฑ, ์‘๋‹ต ๋ณ€ํ™˜ ๋“ฑ ๋‹ค์–‘ํ•œ ์šฉ๋„๋กœ ํ™œ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

์นดํ…Œ๊ณ ๋ฆฌ Interceptor ์œ ํ˜• ๊ธฐ๋Šฅ ์žฅ์ 
๊ฐœ๋ฐœ ๊ฒฝํ—˜ LoggingInterceptor ์š”์ฒญ/์‘๋‹ต ๋กœ๊น… โœ… ๋””๋ฒ„๊น… ํŽธ์˜์„ฑ
์„ฑ๋Šฅ ๊ด€๋ จ CacheInterceptor ์‘๋‹ต ์บ์‹ฑ โœ… ์„ฑ๋Šฅ ์ตœ์ ํ™”
ํ•ต์‹ฌ ๊ธฐ๋Šฅ TransformInterceptor ์‘๋‹ต ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ โœ… ์ผ๊ด€๋œ API ํ˜•์‹
๊ฐœ๋ฐœ ๊ฒฝํ—˜ TimeoutInterceptor ์š”์ฒญ ํƒ€์ž„์•„์›ƒ ์ฒ˜๋ฆฌ โœ… ์•ˆ์ •์„ฑ ํ–ฅ์ƒ

 


๐Ÿ”ง Pipes - ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜๊ณผ ๊ฒ€์ฆ

Pipes๋Š” ๋ผ์šฐํŠธ ํ•ธ๋“ค๋Ÿฌ๊ฐ€ ์‹คํ–‰๋˜๊ธฐ ์ „์— ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ๊ฒ€์ฆํ•˜๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ”ง PipeTransform ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ, NestJS๋Š” ์—ฌ๋Ÿฌ ์œ ์šฉํ•œ ๋‚ด์žฅ ํŒŒ์ดํ”„๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

 

ํŠนํžˆ ValidationPipe๋Š” class-validator์™€ ์—ฐ๋™๋˜์–ด DTO ๊ธฐ๋ฐ˜์˜ ๊ฐ•๋ ฅํ•œ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ“Š ์ด๋ฅผ ํ†ตํ•ด API ์ž…๋ ฅ๊ฐ’์˜ ํƒ€์ž… ์•ˆ์ „์„ฑ๊ณผ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

Pipe ์ด๋ฆ„ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ์‚ฌ๋ก€ ์˜ˆ์‹œ
ValidationPipe DTO ๊ธฐ๋ฐ˜ ๊ฒ€์ฆ โœ… ์š”์ฒญ ๋ฐ”๋”” ๊ฒ€์ฆ @Body() dto: CreateUserDto
ParseIntPipe ๋ฌธ์ž์—ด์„ ์ •์ˆ˜๋กœ ๋ณ€ํ™˜ โœ… ๊ฒฝ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ @Param('id', ParseIntPipe)
ParseUUIDPipe UUID ํ˜•์‹ ๊ฒ€์ฆ โœ… ID ํ˜•์‹ ๋ณด์žฅ @Param('uuid', ParseUUIDPipe)
DefaultValuePipe ๊ธฐ๋ณธ๊ฐ’ ์„ค์ • โœ… ์„ ํƒ์  ๋งค๊ฐœ๋ณ€์ˆ˜ @Query('page', new DefaultValuePipe(1))

 


๐Ÿšจ Exception Filters - ์˜ˆ์™ธ ์ฒ˜๋ฆฌ

Exception Filters๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์˜ˆ์™ธ๋ฅผ ์ผ๊ด€๋œ ํ˜•ํƒœ๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ ์ ˆํ•œ ์‘๋‹ต์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๐Ÿšจ ExceptionFilter ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ, ์ „์—ญ ๋˜๋Š” ํŠน์ • ๋ฒ”์œ„์—์„œ ์˜ˆ์™ธ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

NestJS๋Š” HTTP ์˜ˆ์™ธ ํด๋ž˜์Šค๋“ค์„ ๋‚ด์žฅํ•˜๊ณ  ์žˆ์–ด, BadRequestException, UnauthorizedException, NotFoundException ๋“ฑ์„ ์‰ฝ๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. โšก ๋˜ํ•œ ์ปค์Šคํ…€ ์˜ˆ์™ธ ํ•„ํ„ฐ๋ฅผ ํ†ตํ•ด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋งž๋Š” ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


โšก ๊ณ ๊ธ‰ ๋‚ด์žฅ ๊ธฐ๋Šฅ๋“ค

NestJS๋Š” ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ๊ธ‰ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ๋“ค๋„ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค:

 

์นดํ…Œ๊ณ ๋ฆฌ ๊ธฐ๋Šฅ ์„ค๋ช… ์ฃผ์š” ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ
์„ฑ๋Šฅ ๊ด€๋ จ ์บ์‹ฑ ๋ฉ”๋ชจ๋ฆฌ/Redis ๊ธฐ๋ฐ˜ ์บ์‹ฑ @CacheKey(), @CacheTTL()
๊ฐœ๋ฐœ ๊ฒฝํ—˜ ์Šค์ผ€์ค„๋ง Cron ์ž‘์—… ๋ฐ ๊ฐ„๊ฒฉ ์ž‘์—… @Cron(), @Interval()
ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์„ค์ • ๊ด€๋ฆฌ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ๋ฐ ์„ค์ • ํŒŒ์ผ @ConfigService()
ํ•ต์‹ฌ ๊ธฐ๋Šฅ ์ด๋ฒคํŠธ ์‹œ์Šคํ…œ ๋„๋ฉ”์ธ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ @OnEvent(), @EventPattern()
์„ฑ๋Šฅ ๊ด€๋ จ ํ—ฌ์Šค ์ฒดํฌ ์„œ๋น„์Šค ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง @HealthCheck()
๊ธฐํƒ€/์ฐธ๊ณ  ํŒŒ์ผ ์—…๋กœ๋“œ Multer ๊ธฐ๋ฐ˜ ํŒŒ์ผ ์ฒ˜๋ฆฌ @UseInterceptors(FileInterceptor())

๐Ÿ”— ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ†ตํ•ฉ

NestJS๋Š” ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ํ†ตํ•ฉ์„ ์œ„ํ•œ ๊ณต์‹ ํŒจํ‚ค์ง€๋“ค์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ—„๏ธ @nestjs/typeorm, @nestjs/mongoose, @nestjs/sequelize ๋“ฑ์„ ํ†ตํ•ด ์›ํ•˜๋Š” ORM/ODM์„ ์‰ฝ๊ฒŒ ํ†ตํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํŠนํžˆ `@InjectRepository()` ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ํ†ตํ•ด ์˜์กด์„ฑ ์ฃผ์ž… ๋ฐฉ์‹์œผ๋กœ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด ํ…Œ์ŠคํŠธ์™€ ๋ชจํ‚น์ด ๋งค์šฐ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค. โšก ๋˜ํ•œ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ, ์—ฐ๊ฒฐ ํ’€๋ง, ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋“ฑ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ๊ธ‰ ๊ธฐ๋Šฅ๋„ ๋ชจ๋‘ ์ง€์›๋ฉ๋‹ˆ๋‹ค.

 


๐Ÿงช ํ…Œ์ŠคํŒ… ์ง€์›

NestJS๋Š” ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ(TDD)์„ ์—ผ๋‘์— ๋‘๊ณ  ์„ค๊ณ„๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๐Ÿงช Test ๋ชจ๋“ˆ์„ ํ†ตํ•ด ์˜์กด์„ฑ ์ฃผ์ž… ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋ชจํ‚นํ•˜๊ณ , ์œ ๋‹› ํ…Œ์ŠคํŠธ์™€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

`Test.createTestingModule()`์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฉ๋ฆฌ๋œ ํ…Œ์ŠคํŠธ ํ™˜๊ฒฝ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, Guards, Interceptors, Pipes ๋“ฑ ๋ชจ๋“  ๋‚ด์žฅ ๊ธฐ๋Šฅ๋“ค์„ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํ‹ธ๋ฆฌํ‹ฐ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๐Ÿ“Š

 


๐ŸŽฏ ๊ฒฐ๋ก 

NestJS์˜ ๋‚ด์žฅ ๊ธฐ๋Šฅ๋“ค์€ ํ˜„๋Œ€์ ์ธ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์— ํ•„์š”ํ•œ ๋ชจ๋“  ์š”์†Œ๋ฅผ ํฌ๊ด„ํ•˜๋Š” ์™„์„ฑ๋„ ๋†’์€ ์ƒํƒœ๊ณ„๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๐Ÿš€ Guards, Interceptors, Pipes, Filters๋ฅผ ํ†ตํ•œ ์š”์ฒญ ๋ผ์ดํ”„์‚ฌ์ดํด ๊ด€๋ฆฌ๋ถ€ํ„ฐ ์บ์‹ฑ, ์Šค์ผ€์ค„๋ง, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ†ตํ•ฉ๊นŒ์ง€ ๋ชจ๋“  ๊ฒƒ์ด ์ผ๊ด€๋œ ํŒจํ„ด์œผ๋กœ ์„ค๊ณ„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

ํŠนํžˆ ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ๊ธฐ๋ฐ˜์˜ ์„ ์–ธ์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ ์˜์กด์„ฑ ์ฃผ์ž… ์‹œ์Šคํ…œ์€ ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ๊ทน๋Œ€ํ™”ํ•ฉ๋‹ˆ๋‹ค. โšก ์ด๋Ÿฌํ•œ ๋‚ด์žฅ ๊ธฐ๋Šฅ๋“ค์„ ์ ์ ˆํžˆ ์กฐํ•ฉํ•˜๋ฉด ๋ณ„๋„์˜ ๋ณต์žกํ•œ ์„ค์ • ์—†์ด๋„ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ๊ธ‰ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋น ๋ฅด๊ฒŒ ๊ตฌ์ถ•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ฒฐ๊ตญ NestJS์˜ ๋‚ด์žฅ ๊ธฐ๋Šฅ๋“ค์„ ๋งˆ์Šคํ„ฐํ•˜๋Š” ๊ฒƒ์€ ์ƒ์‚ฐ์„ฑ ๋†’์€ ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์˜ ํ•ต์‹ฌ์ž…๋‹ˆ๋‹ค. ๐ŸŒŸ ๊ฐ ๊ธฐ๋Šฅ์˜ ํŠน์„ฑ๊ณผ ์ ์ ˆํ•œ ์‚ฌ์šฉ ์‹œ์ ์„ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•œ๋‹ค๋ฉด, ๋”์šฑ ๊ฒฌ๊ณ ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ ๊ฐ€๋Šฅํ•œ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 


 

๋ฐ˜์‘ํ˜•