μ„œλ²„λ¦¬μŠ€ ν™˜κ²½μ—μ„œ Swagger DTO ν‘œμ‹œ 문제 ν•΄κ²° 및 μ‚¬μš© νŒ¨ν„΄ κ°œμ„ ν•˜κΈ°

seunghunlim-wall
  • #nestjs
  • #api docs
  • #swagger
  • #serverless
  • #bundling
  • #microservice
  • #dto

λ“€μ–΄κ°€λ©°

μ•ˆλ…•ν•˜μ„Έμš”. λ…Έλ¨ΈμŠ€ λ°±μ—”λ“œ μ—”μ§€λ‹ˆμ–΄ μž„μŠΉν›ˆμž…λ‹ˆλ‹€.

이번 κΈ€μ—μ„œλŠ” μ„œλ²„λ¦¬μŠ€ λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€ ν™˜κ²½μ—μ„œ Swaggerλ₯Ό 톡해 API λ¬Έμ„œλ₯Ό κ΄€λ¦¬ν•˜λ©° κ²ͺμ—ˆλ˜ μ΄μŠˆμ™€ ν•΄κ²° 과정을 κ³΅μœ ν•˜κ³ μž ν•©λ‹ˆλ‹€. λ²ˆλ“€λ§ ν™˜κ²½μ—μ„œ DTO 클래슀λͺ…이 μ˜λ„ν•œ λŒ€λ‘œ ν‘œμ‹œλ˜μ§€ μ•ŠλŠ” 문제λ₯Ό λ°œκ²¬ν–ˆκ³ , 이λ₯Ό κ³„κΈ°λ‘œ Swagger μ‚¬μš© νŒ¨ν„΄ μ „λ°˜μ„ μ κ²€ν•˜κ³  κ°œμ„ ν•  수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.


κ°œμ„ μ˜ 계기

이전에 πŸ‘‰ Serverless λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€ ν™˜κ²½μ—μ„œ API Docs ν†΅ν•©ν•˜κΈ°μ—μ„œ μ†Œκ°œν•΄λ“œλ¦° κ²ƒμ²˜λŸΌ λ…Έλ¨ΈμŠ€μ—μ„œλŠ” Swagger UIλ₯Ό μ‚¬μš©ν•΄ API Docsλ₯Ό κ΅¬μ„±ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

μ„œλ²„λ¦¬μŠ€ ν™˜κ²½μ—μ„œ λ²ˆλ“€λ§μ„ 거쳐 λ°°ν¬ν•˜λŠ” κ³Όμ •μ—μ„œ Swagger UIκ°€ 잘 μž‘λ™ν•˜λŠ” κ²ƒμ²˜λŸΌ λ³΄μ˜€μ§€λ§Œ, ν”„λ‘ νŠΈμ—”λ“œ νŒ€κ³Ό OpenAPI μŠ€νŽ™μ„ κ³΅μœ ν•˜μ—¬ νƒ€μž…μ„ μžλ™ μƒμ„±ν•˜λŠ” ν…ŒμŠ€νŠΈλ₯Ό μ§„ν–‰ν•˜λ˜ 쀑 μ˜ˆμƒμΉ˜ λͺ»ν•œ 문제λ₯Ό λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€. 배포 ν›„ Swagger λ¬Έμ„œμ—μ„œ DTO 클래슀λͺ…이 μš°λ¦¬κ°€ μ •μ˜ν•œ μ΄λ¦„λŒ€λ‘œ ν‘œμ‹œλ˜μ§€ μ•ŠλŠ” κ²ƒμ΄μ—ˆμŠ΅λ‹ˆλ‹€.


λ°œκ²¬ν•œ λ¬Έμ œμ λ“€

Swagger λ¬Έμ„œλ₯Ό μžμ„Ένžˆ μ κ²€ν•˜λ©° λ°œκ²¬ν•œ λ¬Έμ œμ μ€ 크게 λ„€ κ°€μ§€μ˜€μŠ΅λ‹ˆλ‹€.

1. λ²ˆλ“€λ§ μ‹œ 클래슀λͺ… ν‘œμ‹œ 이슈

배포 ν›„ Swagger UIλ₯Ό ν™•μΈν•˜λ‹ˆ, μš°λ¦¬κ°€ μ •μ˜ν•œ DTO 클래슀λͺ…이 μ˜λ„ν•œ λŒ€λ‘œ ν‘œμ‹œλ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.

배포 ν™˜κ²½μ˜ Swagger UIμ—μ„œ λ‹€μŒκ³Ό 같은 ν˜„μƒλ“€μ΄ λ°œκ²¬λ˜μ—ˆμŠ΅λ‹ˆλ‹€:

  • CreateOrderDtoκ°€ CreateOrderDto1, _CreateOrderDto λ“± μ˜λ„ν•˜μ§€ μ•Šμ€ λ¬Έμžκ°€ λΆ™μ–΄μ„œ ν‘œμ‹œ
  • GetProductQueryκ°€ Object λ˜λŠ” 의미 μ—†λŠ” μ΄λ¦„μœΌλ‘œ ν‘œμ‹œ
  • 같은 DTOκ°€ μ—¬λŸ¬ 번 μ •μ˜λ˜μ–΄ Swagger λ¬Έμ„œκ°€ λ³΅μž‘ν•΄μ§

DTO 클래슀λͺ… ν‘œμ‹œ 였λ₯˜λ‘œ μΈν•œ νƒ€μž… 문제

λ‹Ήμ‹œ Swagger λ¬Έμ„œλ₯Ό OpenAPI μŠ€νŽ™μœΌλ‘œ exportν•˜μ—¬ ν”„λ‘ νŠΈμ—”λ“œ νŒ€κ³Ό νƒ€μž…μ„ κ³΅μœ ν•˜κΈ° μœ„ν•œ μ€€λΉ„λ₯Ό ν•˜κ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€. μœ„ μ΄λ―Έμ§€μ²˜λŸΌ [object Object] 같은 νƒ€μž…μ΄ μƒμ„±λ˜λ©΄ ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ TypeScript νƒ€μž…μ„ μžλ™ 생성할 λ•Œ μ‹€μ œ 컴파일 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. DTO 이름이 CreateOrderDto1, Object 같은 ν˜•νƒœλ‘œ μƒμ„±λ˜λ©΄ μ½”λ“œμ—μ„œ ν™œμš©ν•˜κΈ° μ–΄λ ΅κΈ° λ•Œλ¬Έμ—, λ°±μ—”λ“œμ™€ ν”„λ‘ νŠΈμ—”λ“œ κ°„ νƒ€μž… κ³΅μœ λΌλŠ” λͺ©ν‘œλ₯Ό λ‹¬μ„±ν•˜κΈ° μœ„ν•΄μ„œλŠ” λ°˜λ“œμ‹œ 해결이 ν•„μš”ν–ˆμŠ΅λ‹ˆλ‹€.

원인:

μ΄λŸ¬ν•œ ν˜„μƒμ€ esbuild λ“± λ²ˆλ“€λŸ¬κ°€ μ½”λ“œλ₯Ό μ΅œμ ν™”ν•˜λŠ” κ³Όμ •μ—μ„œ 클래슀의 메타데이터가 μ†μ‹€λ˜κ±°λ‚˜ λ³€κ²½λ˜κΈ° λ•Œλ¬Έμ— λ°œμƒν•©λ‹ˆλ‹€. SwaggerλŠ” λŸ°νƒ€μž„μ— 클래슀 이름을 μ½μ–΄μ„œ λ¬Έμ„œμ— ν‘œμ‹œν•˜λŠ”λ°, λ²ˆλ“€λ§ ν›„μ—λŠ” 클래슀 정보가 μ œλŒ€λ‘œ μ „λ‹¬λ˜μ§€ μ•Šμ•„ Swaggerκ°€ 쀑볡을 ν”Όν•˜κΈ° μœ„ν•΄ μžλ™μœΌλ‘œ 숫자λ₯Ό λΆ™μ΄κ²Œ λ©λ‹ˆλ‹€.

// μš°λ¦¬κ°€ μž‘μ„±ν•œ μ½”λ“œ
export class CreateOrderDto {
  // ...
}

export class GetGoodsOptionsResponse {
  // ...
}

// Swaggerμ—μ„œ ν‘œμ‹œλ˜λŠ” 이름
CreateOrderDto1  // μ˜λ„ν•˜μ§€ μ•Šμ€ 이름
_GetGoodsOptionsResponse  // μ–Έλ”μŠ€μ½”μ–΄κ°€ λΆ™κ±°λ‚˜
Object  // μ•„μ˜ˆ 의미 μ—†λŠ” μ΄λ¦„μœΌλ‘œ λ³€κ²½

// ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ μžλ™ μƒμ„±λœ νƒ€μž…
interface CreateOrderDto1 {  // 이런 νƒ€μž…μ€ ν™œμš©ν•˜κΈ° 어렀움
  // ...
}

interface _GetGoodsOptionsResponse {  // μ˜ˆμƒμΉ˜ λͺ»ν•œ 넀이밍
  // ...
}

2. Controller와 DTO κ°„ λ°μ½”λ ˆμ΄ν„° 관리

μ„œλΉ„μŠ€ μ΄ˆκΈ°μ—λŠ” Swagger μ‚¬μš© νŒ¨ν„΄μ— 따라 @ApiQuery, @ApiParam, @ApiHeader λ“±μ˜ λ°μ½”λ ˆμ΄ν„°λ₯Ό Controller에 직접 μ„ μ–Έν•˜κ³  μžˆμ—ˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ μ„œλΉ„μŠ€κ°€ μ„±μž₯ν•˜λ©΄μ„œ DTO μ€‘μ‹¬μœΌλ‘œ API μŠ€νŽ™μ„ κ΄€λ¦¬ν•˜λŠ” 것이 더 νš¨μœ¨μ μ΄λΌλŠ” 것을 μ•Œκ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 초기의 μ ‘κ·Ό 방식을 κ·ΈλŒ€λ‘œ μœ μ§€ν•˜λ©΄μ„œ μƒˆλ‘œμš΄ μ½”λ“œκ°€ μΆ”κ°€λ˜λ‹€ λ³΄λ‹ˆ λ‹€μŒκ³Ό 같은 λ¬Έμ œκ°€ μžˆμ—ˆμŠ΅λ‹ˆλ‹€:

  • 같은 정보λ₯Ό Controller와 DTO μ–‘μͺ½μ—μ„œ 관리
  • DTO λ³€κ²½ μ‹œ Controller λ°μ½”λ ˆμ΄ν„°λ„ ν•¨κ»˜ μˆ˜μ •ν•΄μ•Ό ν•˜λŠ” λ²ˆκ±°λ‘œμ›€
  • λ―Έμ‚¬μš© 속성듀이 계속 λ‚¨μ•„μžˆμ–΄ λ¬Έμ„œλ₯Ό 더 λͺ…ν™•ν•˜κ²Œ λ§Œλ“€ ν•„μš”

3. νƒ€μž… ν‘œκΈ° 방식 톡일

μ„œλΉ„μŠ€ μ΄ˆκΈ°μ—λŠ” Swagger λ¬Έμ„œν™”μ— λŒ€ν•œ λͺ…ν™•ν•œ κ°€μ΄λ“œκ°€ μ—†μ—ˆκ³ , 각자의 λ°©μ‹μœΌλ‘œ μž‘μ„±ν•˜λ‹€ λ³΄λ‹ˆ λ‹€μ–‘ν•œ μž‘μ„± νŒ¨ν„΄μ΄ κ³΅μ‘΄ν•˜κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ‹œκ°„μ΄ μ§€λ‚˜λ©° ꢌμž₯λ˜λŠ” μž‘μ„± 방식이 λ°œμ „ν–ˆμ§€λ§Œ κΈ°μ‘΄ μ½”λ“œλŠ” μ—…λ°μ΄νŠΈλ˜μ§€ μ•Šμ•„ 톡일이 ν•„μš”ν–ˆμŠ΅λ‹ˆλ‹€:

  • type: Number vs type: 'number' λ“± νƒ€μž… μ§€μ • λ°©μ‹μ˜ 차이
  • empty arrayλ₯Ό κΈ°λ³Έκ°’μ΄λ‚˜ 예제둜 μ‚¬μš©ν•œ μΌ€μ΄μŠ€ 쑴재
  • μ„€λͺ…(description)을 μΆ”κ°€ν•˜λ©΄ 더 λͺ…ν™•ν•΄μ§ˆ DTO ν•„λ“œλ“€
  • Header의 μ–Έμ–΄ ν•„λ“œ λ“± 곡톡 νƒ€μž…μ˜ μ„œλΉ„μŠ€λ³„ 톡일 ν•„μš”

4. Union νƒ€μž… 응닡 처리

μ½”λ“œλ² μ΄μŠ€λ₯Ό μ κ²€ν•˜λ˜ 쀑, 일뢀 API의 응닡 νƒ€μž…μ΄ Union νƒ€μž…μœΌλ‘œ μ •μ˜λ˜μ–΄ μžˆλŠ” 것을 λ°œκ²¬ν–ˆμŠ΅λ‹ˆλ‹€. Swagger의 oneOf μŠ€νŽ™μ€ μ—¬λŸ¬ 응닡 νƒ€μž… 쀑 ν•˜λ‚˜λ₯Ό λ°˜ν™˜ν•  수 μžˆμŒμ„ ν‘œν˜„ν•˜μ§€λ§Œ, μ‹€μ œλ‘œ OpenAPI μŠ€νŽ™μ—μ„œ νƒ€μž…μ„ 생성할 λ•ŒλŠ” ν•˜λ‚˜μ˜ νƒ€μž…μœΌλ‘œλ§Œ μΆ”λ‘ λ˜λŠ” κ²½μš°κ°€ μžˆμ–΄ ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ μ •ν™•ν•œ νƒ€μž… 정보λ₯Ό λ°›κΈ° μ–΄λ €μšΈ 수 μžˆμŠ΅λ‹ˆλ‹€.

Union νƒ€μž… 응닡을 μ‚¬μš©ν•˜λŠ” λ©”μ„œλ“œ ν˜„ν™©

총 3개 λ©”μ„œλ“œκ°€ 응닡 μžμ²΄κ°€ oneOf/Union νƒ€μž…μœΌλ‘œ μ •μ˜λ˜μ–΄ μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 이 문제의 ν•΄κ²° 방법은 μ•„λž˜ 6. 곡톡 Response 래퍼 νƒ€μž… 처리 κ°œμ„ μ—μ„œ λ‹€λ£Ήλ‹ˆλ‹€.


κ°œμ„  방법

λ°œκ²¬ν•œ λ¬Έμ œλ“€μ„ ν•΄κ²°ν•˜κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같은 μž‘μ—…μ„ μ§„ν–‰ν–ˆμŠ΅λ‹ˆλ‹€.

1. @ApiSchema λ°μ½”λ ˆμ΄ν„°λ‘œ 클래슀λͺ… λͺ…μ‹œμ  μ§€μ •

λͺ¨λ“  DTO ν΄λž˜μŠ€μ— @ApiSchema() λ°μ½”λ ˆμ΄ν„°λ₯Ό μΆ”κ°€ν•˜κ³ , 클래슀λͺ…을 λͺ…μ‹œμ μœΌλ‘œ μ§€μ •ν•˜μ—¬ λ²ˆλ“€λ§ 후에도 μ˜¬λ°”λ₯Έ 이름이 μœ μ§€λ˜λ„λ‘ ν–ˆμŠ΅λ‹ˆλ‹€.

@ApiSchema({ name: 'CreateOrderDto' })
export class CreateOrderDto {
  @ApiProperty({ type: 'string', description: '수령인 이름' })
  recipientName: string;
}

μ΄λ ‡κ²Œ ν•˜λ©΄ λ²ˆλ“€λ§ κ³Όμ •μ—μ„œ 클래슀λͺ…이 λ³€κ²½λ˜λ”λΌλ„ SwaggerλŠ” μš°λ¦¬κ°€ μ§€μ •ν•œ 'CreateOrderDto' 이름을 μ‚¬μš©ν•˜μ—¬ λ¬Έμ„œμ— ν‘œμ‹œν•©λ‹ˆλ‹€. 더 이상 CreateOrderDto1, CreateOrderDto2λ‚˜ Object 같은 의미 μ—†λŠ” 이름이 λ‚˜νƒ€λ‚˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

이 μž‘μ—…μ„ μ§„ν–‰ν•˜λ©΄μ„œ SwaggerλŠ” 같은 μ΄λ¦„μ˜ DTOκ°€ μ—¬λŸ¬ 개 μ‘΄μž¬ν•  경우 ν•˜λ‚˜λ§Œ μ²˜λ¦¬ν•œλ‹€λŠ” 점을 μœ μ˜ν–ˆμŠ΅λ‹ˆλ‹€. λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€ ν™˜κ²½μ—μ„œλŠ” μ„œλΉ„μŠ€ κ°„ DTO 이름이 μ€‘λ³΅λ˜μ§€ μ•Šλ„λ‘ 넀이밍 κ·œμΉ™μ„ μ •ν•˜λ©΄μ„œ μž‘μ—…ν–ˆμŠ΅λ‹ˆλ‹€.


2. Controller λ°μ½”λ ˆμ΄ν„°λ₯Ό DTO둜 이전

기쑴에 Controller에 흩어져 있던 @ApiQuery, @ApiParam, @ApiHeaderλ₯Ό DTO둜 ν†΅ν•©ν–ˆμŠ΅λ‹ˆλ‹€.

λ³€κ²½ μ „:

@Get()
@ApiHeader({ name: 'lang' })
@ApiQuery({ name: 'productId', type: 'number' })
async getProduct(@Headers('lang') lang: string, @Query('productId') id: number) {
  // ...
}

λ³€κ²½ ν›„:

@Get()
async getProduct(@Headers() headers: GetProductHeaders, @Query() query: GetProductQuery) {
  // ...
}

Controllerκ°€ κ°„κ²°ν•΄μ§€κ³ , DTO만 보면 API μŠ€νŽ™μ„ ν•œλˆˆμ— νŒŒμ•…ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.


3. νƒ€μž…μ„ λ¬Έμžμ—΄ λ¦¬ν„°λŸ΄λ‘œ 톡일

λ²ˆλ“€λ§ ν™˜κ²½μ—μ„œ μ•ˆμ •μ μœΌλ‘œ λ™μž‘ν•˜λ„λ‘ νƒ€μž…μ„ λ¬Έμžμ—΄ λ¦¬ν„°λŸ΄λ‘œ ν†΅μΌν–ˆμŠ΅λ‹ˆλ‹€.

// λ³€κ²½ μ „
@ApiProperty({ type: Number })
price: number;

// λ³€κ²½ ν›„
@ApiProperty({ type: 'number' })
price: number;

// 배열인 경우
@ApiProperty({ type: 'number', isArray: true })
discountRates: number[];

4. nullableκ³Ό optional 처리 λͺ…ν™•ν™”

// Optional ν•„λ“œ
@ApiPropertyOptional({ type: 'string' })
@IsOptional()
memo?: string;

// Nullable ν•„λ“œ
@ApiProperty({ type: 'string', nullable: true })
couponCode: string | null;

5. 곡톡 νƒ€μž… 톡일

λͺ¨λ“  μ„œλΉ„μŠ€μ—μ„œ μ‚¬μš©ν•˜λŠ” header νƒ€μž…μ„ ν†΅μΌν•˜μ—¬ 일관성을 ν™•λ³΄ν–ˆμŠ΅λ‹ˆλ‹€.

// 곡톡 νƒ€μž… μ •μ˜
export const ALL_LANGUAGES = ['ko', 'en', 'ja', 'zh'] as const;
export type Language = typeof ALL_LANGUAGES[number];

// λͺ¨λ“  μ„œλΉ„μŠ€μ—μ„œ λ™μΌν•˜κ²Œ μ‚¬μš©
@ApiSchema()
export class CommonRequestHeader {
  @ApiProperty({ enum: ALL_LANGUAGES })
  lang: Language;
}

6. 곡톡 Response 래퍼 νƒ€μž… 처리 κ°œμ„ 

λ…Έλ¨ΈμŠ€μ—μ„œλŠ” λͺ¨λ“  API 응닡을 μΌκ΄€λœ ν˜•νƒœλ‘œ μ œκ³΅ν•˜κΈ° μœ„ν•΄ FrommResponse<T> 곡톡 Response 래퍼λ₯Ό μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. ν•˜μ§€λ§Œ Swagger λ¬Έμ„œ 생성 μ‹œ λ‹€μŒκ³Ό 같은 λ¬Έμ œκ°€ μžˆμ—ˆμŠ΅λ‹ˆλ‹€:

기쑴 문제:

  • FrommResponse.dataκ°€ void인 κ²½μš°μ—λ„ Swagger에 빈 객체둜 ν‘œμ‹œλ¨
  • FrommResponse.dataκ°€ null일 수 μžˆλŠ” 경우 required: false 섀정이 어렀움
  • FrommResponse<T>μ—μ„œ Tκ°€ Union νƒ€μž…μΈ 경우 Swagger의 oneOf, allOf λ“± 볡합 νƒ€μž… 처리 μ œμ•½

Union νƒ€μž…μ„ μ‚¬μš©ν•˜λŠ” 응닡 μ˜ˆμ‹œ

μœ„ μ΄λ―Έμ§€μ²˜λŸΌ μ‘λ‹΅μ˜ data ν•„λ“œκ°€ Union νƒ€μž…(oneOf)으둜 μ—¬λŸ¬ κ°€λŠ₯ν•œ νƒ€μž…μ„ κ°€μ§€λŠ” 경우, OpenAPI μŠ€νŽ™μ—μ„œ νƒ€μž…μ„ μ •ν™•ν•˜κ²Œ ν‘œν˜„ν•˜λŠ” 것이 μ€‘μš”ν•©λ‹ˆλ‹€.

κ°œμ„  방법:

FrommResponse 클래슀의 data ν•„λ“œ 처리λ₯Ό κ°œμ„ ν–ˆμŠ΅λ‹ˆλ‹€.

  • void 처리: dataκ°€ void인 경우 Swagger μƒμ—μ„œ ν‘œμ‹œλ˜μ§€ μ•Šλ„λ‘ μˆ˜μ •
  • nullable 처리: dataκ°€ nullable인 경우 required: false둜 μ„€μ • κ°€λŠ₯ν•˜λ„λ‘ μˆ˜μ •
  • 볡합 νƒ€μž… 처리: dataκ°€ Union νƒ€μž…μΈ 경우 oneOf, allOf λ“±μ˜ OpenAPI μŠ€νŽ™μ„ μ˜¬λ°”λ₯΄κ²Œ μƒμ„±ν•˜λ„λ‘ κ°œμ„ 

이λ₯Ό 톡해 각 API의 응닡 νƒ€μž…μ— λ§žλŠ” μ •ν™•ν•œ Swagger λ¬Έμ„œκ°€ μƒμ„±λ˜κ³ , μ˜¬λ°”λ₯Έ νƒ€μž…μ„ μ•Œ 수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.


κ²°κ³Ό 및 κ°œμ„ μ‚¬ν•­

배포 ν›„ 정상 μž‘λ™ 확인

  • DTO 클래슀λͺ…이 μ˜λ„ν•œ λŒ€λ‘œ Swagger UI에 μ˜¬λ°”λ₯΄κ²Œ ν‘œμ‹œ
  • OpenAPI μŠ€νŽ™μ—μ„œ μƒμ„±λœ TypeScript νƒ€μž…μ΄ μ •ν™•ν•œ μ΄λ¦„μœΌλ‘œ μƒμ„±λ˜μ–΄ ν”„λ‘ νŠΈμ—”λ“œ νŒ€κ³Όμ˜ νƒ€μž… 곡유 성곡
  • Request/Response μŠ€ν‚€λ§ˆκ°€ λͺ…ν™•ν•˜κ²Œ λ Œλ”λ§
  • λͺ¨λ“  λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€μ˜ Swagger λ¬Έμ„œκ°€ 일관성 있게 κ°œμ„ 

개발 κ²½ν—˜ κ°œμ„ 

  • Controller μ½”λ“œκ°€ κ°„κ²°ν•΄μ Έ 가독성 ν–₯상
  • DTO만 보면 API μŠ€νŽ™μ„ ν•œλˆˆμ— νŒŒμ•… κ°€λŠ₯
  • 곡톡 νƒ€μž… μž¬μ‚¬μš©μœΌλ‘œ μ½”λ“œ 쀑볡 κ°μ†Œ
  • λͺ…μ‹œμ  νƒ€μž… μ •μ˜λ‘œ IDE μžλ™μ™„μ„± ν’ˆμ§ˆ ν–₯상

μœ μ§€λ³΄μˆ˜μ„± ν–₯상

  • DTO λ³€κ²½ μ‹œ Swagger λ¬Έμ„œ μžλ™ μ—…λ°μ΄νŠΈ 보μž₯
  • μƒˆλ‘œμš΄ API μΆ”κ°€ μ‹œ λ™μΌν•œ νŒ¨ν„΄μœΌλ‘œ λΉ λ₯΄κ²Œ μž‘μ„± κ°€λŠ₯
  • νƒ€μž… μ•ˆμ •μ„± κ°•ν™”λ‘œ λŸ°νƒ€μž„ μ—λŸ¬ κ°μ†Œ

마치며

μ²˜μŒμ—λŠ” ν”„λ‘ νŠΈμ—”λ“œμ™€ νƒ€μž…μ„ κ³΅μœ ν•˜κΈ° μœ„ν•œ μ€€λΉ„ κ³Όμ •μ—μ„œ μš°μ—°νžˆ λ°œκ²¬ν•œ λ¬Έμ œμ˜€μ§€λ§Œ, 이λ₯Ό ν•΄κ²°ν•˜λŠ” κ³Όμ •μ—μ„œ Swagger μ‚¬μš© νŒ¨ν„΄ μ „λ°˜μ„ μ κ²€ν•˜λ©° 더 λ‚˜μ€ λ°©ν–₯으둜 λ°œμ „μ‹œν‚¬ 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€. 특히 UIμƒμœΌλ‘œλŠ” 속성 등이 μ˜¬λ°”λ₯΄κ²Œ λ³΄μ—¬μ„œ μ²˜μŒμ—λŠ” μ•Œμ•„μ°¨λ¦¬κΈ° μ–΄λ €μ› κΈ° λ•Œλ¬Έμ—, ν”„λ‘ νŠΈμ—”λ“œ νŒ€κ³Όμ˜ ν˜‘μ—…μ΄ μ—†μ—ˆλ‹€λ©΄ 계속 λ†“μΉ˜κ³  μžˆμ—ˆμ„ λ¬Έμ œμ˜€μŠ΅λ‹ˆλ‹€.

이번 μž‘μ—…μ„ 톡해 배운 점은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

  1. λ²ˆλ“€λ§ ν™˜κ²½μ˜ νŠΉμ„± 이해: λ²ˆλ“€λŸ¬λŠ” μ½”λ“œλ₯Ό μ΅œμ ν™”ν•˜λ©΄μ„œ 클래슀 메타데이터λ₯Ό λ³€κ²½ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 배포 ν™˜κ²½μ—μ„œλ§Œ λ°œμƒν•˜λŠ” μ΄μŠˆλ“€μ€ λ°œκ²¬ν•˜κΈ° μ–΄λ €μš°λ―€λ‘œ, λͺ…μ‹œμ μΈ 메타데이터 지정이 μ€‘μš”ν•©λ‹ˆλ‹€.
  2. μΌκ΄€λœ νƒ€μž… μ •μ˜ νŒ¨ν„΄: λ§ˆμ΄ν¬λ‘œμ„œλΉ„μŠ€ ν™˜κ²½μ—μ„œλŠ” λͺ¨λ“  μ„œλΉ„μŠ€κ°€ λ™μΌν•œ νŒ¨ν„΄μ„ λ”°λ₯Ό λ•Œ 전체 μ„œλΉ„μŠ€μ˜ ν’ˆμ§ˆμ„ 효과적으둜 높일 수 μžˆμŠ΅λ‹ˆλ‹€.
  3. DTO μ€‘μ‹¬μ˜ API λ¬Έμ„œν™”: Controller에 흩어진 메타데이터λ₯Ό DTO둜 ν†΅ν•©ν•˜λ©΄, API μŠ€νŽ™μ„ ν•œλˆˆμ— νŒŒμ•…ν•  수 있고 μœ μ§€λ³΄μˆ˜μ„±μ΄ 크게 ν–₯μƒλ©λ‹ˆλ‹€.
  4. νŒ€ κ°„ ν˜‘μ—…μ˜ μ€‘μš”μ„±: ν”„λ‘ νŠΈμ—”λ“œ νŒ€κ³Όμ˜ νƒ€μž… 곡유 μž‘μ—…μ΄ μ—†μ—ˆλ‹€λ©΄ λ°œκ²¬ν•˜μ§€ λͺ»ν–ˆμ„ λ¬Έμ œμ˜€μŠ΅λ‹ˆλ‹€. μ„œλ‘œ λ‹€λ₯Έ κ΄€μ μ—μ„œ λ°”λΌλ³΄λŠ” 것이 ν’ˆμ§ˆ ν–₯상에 도움이 λ©λ‹ˆλ‹€.

μ„œλ²„λ¦¬μŠ€ ν™˜κ²½μ—μ„œ Swaggerλ₯Ό μ‚¬μš©ν•˜λ©° λΉ„μŠ·ν•œ 고민을 ν•˜μ‹œλŠ” λΆ„λ“€κ»˜ 이 글이 도움이 λ˜μ—ˆμœΌλ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€.

μ½μ–΄μ£Όμ…”μ„œ κ°μ‚¬ν•©λ‹ˆλ‹€.

← λͺ©λ‘μœΌλ‘œ λŒμ•„κ°€κΈ°

Art Changes Life

λ…Έλ¨ΈμŠ€μ™€ ν•¨κ»˜ μ—”ν„°ν…Œν¬ 산업을 ν˜μ‹ ν•΄λ‚˜κ°ˆ 멀버λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.

μ±„μš© 쀑인 곡고 보기