Daily Logs/TIL (Today I Learned)

NestJS에서 DTO에 password가 없어도 실제로 password를 제거해야 하는 이유

Jcob.moon 2025. 6. 27. 00:00

NestJS에서 DTO에 password가 없어도 실제로 password를 제거해야 하는 이유

NestJS, TypeORM, 그리고 타입스크립트를 사용하다 보면

“응답 DTO(UserResponseDto)에 password가 없는데,

굳이 구조분해 할당으로 password를 제거해야 하나?”

라는 의문이 들 수 있습니다.

이 부분을 정확히 이해하는 것이 보안과 타입스크립트의 동작 원리를 이해하는 데 매우 중요합니다.


1. DTO는 “설계도”일 뿐, 실제 데이터가 아니다

  • DTO(Data Transfer Object)는

“이런 필드만 응답에 포함되어야 한다”는 타입(설계도)입니다.

  • export class UserResponseDto { id: number; email: string; name: string; }

이렇게 정의하면,

“id, email, name만 응답에 포함되어야 한다”는 약속을 의미합니다.


2. 실제 데이터는 User 엔티티(ORM 모델)에서 온다

  • DB에서 유저 정보를 가져오면

실제로는 User 엔티티 객체가 반환됩니다.

  • 이 객체에는

password, created_at, updated_at 등 모든 필드가 다 들어있습니다.


3. 타입스크립트의 타입은 “컴파일 시점”에만 동작

  • 타입스크립트의 타입은 코드 작성/컴파일 시점에만 체크됩니다.
  • 런타임(실제 실행 시점)에는 타입 정보가 완전히 사라집니다.
  • 즉,Apply to auth.service...
  • return user as UserResponseDto;
  • typescript

이렇게 해도,

실제로는 user 객체의 모든 필드가 응답에 포함됩니다.

  • 타입스크립트는 “이 객체가 UserResponseDto 타입과 맞는지”만 체크할 뿐,

실제 데이터를 가공하지 않습니다.


4. password를 응답에서 빼려면 “직접 제거”해야 한다

  • 그래서 아래처럼 구조분해 할당을 사용해서

password 필드를 실제로 제거해야 합니다.

const { password, ...userWithoutPassword } = user;

return userWithoutPassword as UserResponseDto;
  • 이렇게 하면

password가 빠진 객체만 클라이언트에 응답으로 전달됩니다.


5. 결론

  • DTO는 설계도일 뿐, 실제 데이터를 가공하지 않는다.
  • 보안상 민감 정보(password 등)는 반드시 직접 제거해야 한다.
  • 타입 단언(as UserResponseDto)만으로는 실제 데이터에서 필드가 빠지지 않는다.
  • 구조분해 할당 등으로 실제 객체에서 password를 제거한 뒤 반환해야 안전하다.

프로젝트 안 코드

const { password, ...userWithoutPassword } = user;

return userWithoutPassword as UserResponseDto;

한 줄 요약

“타입스크립트의 타입은 설계도일 뿐, 실제 데이터에서 password를 빼려면 반드시 직접 제거해야 한다!”