

하나의 파일에 Query, Path, Body, Response, 내부용 DTO까지 모두 몰아 넣다 보니 변경 사유가 여러 개가 된다. 그 결과 수정 범위가 불필요하게 커지고, 코드 리뷰도 비효율적으로 진행된다.
CreateXDto, CreateXRequest, CreateXResponse가 한 파일에서 중복/혼용되며 import 시 오타·충돌 위험 증가.
특정 엔드포인트의 스펙만 바꿔도 같은 파일을 건드리면서 다른 DTO까지 린터/빌드/테스트에 영향 → 작은 변경도 큰 PR로 부풀어짐.


@Param() + 파이프(예: ParseIntPipe)로 즉시 변환·검증.// controller
@Get('/:shopId')
getShop(@Param('shopId', ParseIntPipe) shopId: number) {
return this.shopService.findOne(shopId);
}
dto/query/ — Query 전용 DTO의도: 페이지네이션, 정렬, 필터 등 URL 쿼리스트링을 명확히 분리.
특징:
class-transformer로 숫자/불리언 변환 (@Type(() => Number), @Transform(...)).class-validator로 유효성 보장 (@IsInt, @Min, @IsOptional 등).@ApiPropertyOptional)로 클라이언트와 스펙 공유.예: pagination.dto.ts, user.dto.ts(사용자 조회 조건 등)
// shop/dto/query/pagination.dto.ts
import { ApiPropertyOptional } from '@nestjs/swagger';
import { IsInt, IsOptional, Min } from 'class-validator';
import { Type } from 'class-transformer';
export class GetShopWithin1KmDTO {
@ApiProperty({ description: '위도', example: 37.5665 })
@IsNumber()
@IsNotEmpty()
@Type(() => Number)
lat: number;
@ApiProperty({ description: '경도', example: 127 })
@IsNumber()
@IsNotEmpty()
@Type(() => Number)
lng: number;
사용처:
async getShopWithin1Km(
@Query() getShopWithin1KmDTO: GetShopWithin1KmDTO, @GetUUID() uuid: string
) {...}
dto/requests/ — RequestBody 전용 DTO의도: 클라이언트가 서버로 보내는 데이터(Body) 만을 명확히 규정.
특징:
class-validator 필수).user_requests.dto.ts, wishlist_requests.dto.ts, review_request.dto.ts 등.효과: 입력 스키마가 명확해지고 Under/Over-posting 위험 감소.
// shop/dto/requests/review_request.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { IsInt, IsNotEmpty, IsString, MaxLength, Min, Type } from 'class-transformer';
export class SubmitNewShopDto {
@ApiProperty({ description: '소품샵 정보' })
@IsNotEmpty()
shop: SubmitShop;
@ApiPropertyOptional({ description: '운영 시간 정보' })
operatingHours?: OperatingHoursDto;
@ApiPropertyOptional({ description: '판매 제품 리스트', type: [Products] })
products?: Products[];
}
사용처:
async submitNewShop(
@Body() newShopData: SubmitNewShopDto,
@GetUUID() uuid: string
) {...}
dto/responses/ — Response 전용 DTO(ViewModel)의도: 서버가 클라이언트로 반환하는 형태를 명확히 분리(엔티티와 분리).
특징:
@ApiProperty 적극 사용).class-transformer의 @Expose/@Transform으로 직렬화 제어.pagination_response.dto.ts) 등 공용 뷰모델 제공.효과: 엔티티 스키마 변경이 외부 계약을 곧바로 흔들지 않음. 응답 일관성↑.
// shop/dto/responses/shop_responses.dto.ts
import { ApiProperty } from '@nestjs/swagger';
export class ShopWithin1KmResponseItemDTO {
@ApiProperty({ example: 1 })
id: number;
@ApiProperty({ example: 'Green Valley Market' })
name: string;
...
}
서비스 → 응답 매핑은 어셈블러/프레젠터에서:
return new ShopSearchPageNationResultDTO(mappedResults, pageInfoDTO);