태그
#NESTJS
#NEST
2025년 5월 13일 23:49

NestJS를 사용하다 보면, @Param()이나 @Query()로 받은 값이 기대한 타입과 다르게 넘어오는 현상을 겪을 수 있습니다. 특히 Boolean 타입을 기대했지만 실제로는 string으로 넘어오는 문제가 대표적입니다. 이 글에서는 실제로 겪은 문제와 이를 커스텀 데코레이터로 해결한 방법, 그리고 구현 과정을 정리합니다.
1. 문제점
NestJS에서 DTO에 아래와 같이 Boolean 타입을 선언했을 때에 boolean 값이 제대로 들어오지 않았습니다.
export class ExampleDto {
@ApiProperty({ example: false })
creating: boolean;
}
Swagger나 클라이언트에서 ?creating=false와 같이 요청해도, 실제로 컨트롤러에서 찍어보면 dto.creating 값이 'false'(string)으로 넘어옵니다. typeof dto.creating을 찍어보면 string이 반환되어, Boolean으로 정상 동작하지 않습니다.
이는 query string이 항상 string 타입으로 전달되기 때문입니다. ValidationPipe의 transform 옵션을 활성화해도, enableImplicitConversion이 켜져 있으면 "false" 같은 문자열이 Boolean으로 변환될 때 항상 true로 처리되는 문제가 있습니다. 즉, "false"도 truthy string이기 때문에 Boolean 변환 시 true가 되어버립니다.
2. 해결 방법
2-1. class-transformer 사용
첫번째로는 문제를 해결하기 위해 커스텀 데코레이터와 class-transformer의 @Transform을 활용했습니다. 핵심은 string 값을 명시적으로 Boolean으로 변환해주는 로직을 추가하는 것입니다.
ValidationPipe 설정
app.useGlobalPipes(
new ValidationPipe({
transform: true,
}),
);
transform 옵션을 활성화해도 "false"가 true로 변환되는 문제는 여전히 존재합니다.
2-2. 커스텀 Transform 적용
DTO의 Boolean 필드에 아래와 같이 @Transform을 붙여 명시적으로 변환합니다.
import { Transform } from 'class-transformer';
@Transform(({ value }) => value === 'true' ? true : false)
creating: boolean;
이 코드는 string으로 들어온 값이 정확히 'true'일 때만 true로 변환하고, 나머지는 false로 처리합니다. 혹은 값이 아예 들어오지 않았을 경우에도 처리할 수 있습니다.
2-2-1. 확장된 커스텀 데코레이터
좀 더 다양한 입력('on', 'yes', '1', 'false', 'off', 'no', '0')을 처리하고 싶다면 아래와 같이 커스텀 데코레이터를 만들어 사용할 수 있습니다.
import { Transform } from 'class-transformer';
function ToBoolean() {
const toPlain = Transform(({ value }) => value, { toPlainOnly: true });
const toClass = (target: any, key: string) => {
return Transform(({ obj }) => {
return valueToBoolean(obj[key]);
}, { toClassOnly: true })(target, key);
};
return function (target: any, key: string) {
toPlain(target, key);
toClass(target, key);
};
}
function valueToBoolean(value: any) {
if (value === null || value === undefined) return undefined;
if (typeof value === 'boolean') return value;
if (['true', 'on', 'yes', '1'].includes(value.toLowerCase())) return true;
if (['false', 'off', 'no', '0'].includes(value.toLowerCase())) return false;
return value;
}
DTO에서 아래처럼 사용합니다.
@ToBoolean()
creating: boolean;
이 함수는 다양한 문자열을 Boolean으로 변환하고, Boolean이 아닌 값은 그대로 반환하여 검증 단계에서 걸러지도록 할 수 있습니다.
3. 정리
NestJS에서 Query/Param 값이 기대한 타입과 다르게 넘어오는 이슈는 흔히 발생하며, 특히 Boolean 처리에서 문제가 두드러집니다. 커스텀 데코레이터와 class-transformer를 적절히 활용하면, 이러한 문제를 명확하게 해결할 수 있습니다. 실제로 적용해보면, Swagger나 클라이언트에서 Boolean 값을 string으로 넘겨도, 서버에서 의도한 대로 Boolean 타입으로 안전하게 사용할 수 있습니다.
참고