๋ฌธ์ œ ์ƒํ™ฉ

๋ณดํ†ต ์—…๋ฌด ์ฝ”๋“œ์—์„œ Entity๋Š” ํ…Œ์ด๋ธ” ์ •๋ณด์™€ ๋™์ผํ•˜๊ฒŒ ์ •์˜ํ•˜๊ณ , DTO๋Š” API๋ฅผ ์œ„ํ•ด ๋ณ„๋„๋กœ ์ •์˜ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋ฌธ์ œ๋Š” Entity์—์„œ DTO๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ๊ทธ ๋ฐ˜๋Œ€์˜ ๊ณผ์ •์ด ํ•„์š”ํ•œ๋ฐ, ๊ฒน์น˜๋Š” ์†์„ฑ์ด ๋งŽ์Œ์—๋„ ๊ฐ์ฒด๋ฅผ ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๊ฒŒ ๋˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๊น”๋”ํ•ด์ง€์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

const foos = await this.getFooList();
 
return foos.map((foo) => ({
  name: foo.name,
  description: foo.description,
  bar: someProcess(foo.bar),
  // ..
}));

ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

class-transformer ํŒจํ‚ค์ง€์˜ plainToInstance ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { plainToInstance } from "class-transformer";
 
const foos = await this.getFooList();
 
return foos.map((foo) =>
  plainToInstance(FooDto, {
    ...foo,
    bar: someProcess(foo.bar),
  })
);

๋ณ„๋„์˜ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๊ฒฝ์šฐ ํ•„์š”ํ•œ ๊ฐ’๋งŒ ๊ต์ฒดํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์œ ์—ฐํ•˜๊ฒŒ ๋Œ€์ฒ˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@Expose ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ ํ™œ์šฉ

ํŠน์ • ํ•„๋“œ๋งŒ ๋…ธ์ถœํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ @Expose() ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { Expose, Exclude } from "class-transformer";
 
@Exclude()
export class FooDto {
  @Expose()
  name: string;
 
  @Expose()
  description: string;
 
  // bar๋Š” ๋…ธ์ถœ๋˜์ง€ ์•Š์Œ
  bar: string;
}

excludeExtraneousValues ์˜ต์…˜๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด @Expose()๊ฐ€ ๋ถ™์€ ํ•„๋“œ๋งŒ ๋ณ€ํ™˜๋ฉ๋‹ˆ๋‹ค.

plainToInstance(FooDto, data, { excludeExtraneousValues: true });

๋Œ€์•ˆ

DTO๊ฐ€ ๋งŽ๊ณ  ๋งคํ•‘์ด ๋ณต์žกํ•ด์ง€๋ฉด @automapper/nestjs๋ฅผ ๊ณ ๋ คํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.