BackEnd๐Ÿงต

[Spring] DTO

hae02y 2023. 7. 9. 18:19
๋ฐ˜์‘ํ˜•

DTO?

DTO๋ž€?

DTO(Data Transfer Object)์˜ ์•ฝ์ž๋กœ ๋งˆํ‹ดํŒŒ์šธ๋Ÿฌ๊ฐ€ ์†Œ๊ฐœํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์ค‘์˜ ํ•˜๋‚˜์ด๋‹ค. DTO๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ์šฉ๋„์˜ ๊ฐ์ฒด์ด๋‹ค. 

 

 

DTO๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

์ฝ”๋“œ์˜ ๊ฐ„๊ฒฐ์„ฑ

DTO๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ํšŒ์›์ •๋ณด๋ฅผ @RequestParam์„ ํ†ตํ•ด ์ด๋ฉ”์ผ, ์ด๋ฆ„, ์ฃผ์†Œ ๋“ฑ์˜ ์ •๋ณด๋ฅผ ๋ฐ›๋Š”๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ๊ทธ๋Ÿผ ์ปจํŠธ๋กค๋Ÿฌ์˜ ํ•ด๋‹น ๋ฉ”์„œ๋“œ์— ๋ฐ›์œผ๋ ค๋Š” ์ •๋ณด์˜ ์ˆซ์ž๋งŒํผ @RequestParam์ด ํ•„์š”ํ• ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ Dto๋ฅผ ์ ์šฉํ•˜๊ฒŒ๋œ๋‹ค๋ฉด? 

//DTO ์ ์šฉ์ „

@PostMapping
    public ResponseEntity postMember(@RequestParam("email") String email,
                                     @RequestParam("name") String name,
                                     @RequestParam("phone") String phone) {
        Map<String, String> map = new HashMap<>();
        map.put("email", email);
        map.put("name", name);
        map.put("phone", phone);
 //DTO์ ์šฉํ›„
 
 @PostMapping
    public ResponseEntity postMember(MemberDto memberDto) {
        return new ResponseEntity<MemberDto>(memberDto, HttpStatus.CREATED);
    }

Dtoํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์š”์ฒญ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ์ „๋‹ฌ๋ฐ›์•„ ์ปจํŠธ๋กค๋Ÿฌ์˜ ์ฝ”๋“œ๊ฐ€ ํ›จ์”ฌ ๊น”๋”ํ•ด์กŒ๋‹ค.

 

์œ ํšจ์„ฑ(Validation) ๊ฒ€์ฆ

์ƒ๋‹จ์˜ DTO๊ฐ€ ์ ์šฉ๋˜์ง€ ์•Š์€ ์ฝ”๋“œ์— ์œ ํšจ์„ฑ ๊ฒ€์ฆ์ด ์ ์šฉ๋˜๋ ค๋ฉด if๋ฌธ๋“ฑ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปจํŠธ๋กค๋Ÿฌ ๋‚ด๋ถ€์—์„œ ๊ฒ€์ฆ์ด ์ง„ํ–‰๋˜์•ผํ•œ๋‹ค. ์ •๊ทœํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒ€์ฆ์„ ์ง„ํ–‰ํ•œ๋‹ค๊ณ  ํ•ด๋„ ๋กœ์ง์ด ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ์ง์ ‘์ ์œผ๋กœ ํฌํ•จ๋˜์–ด ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์ง„๋‹ค. ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ๋Š” HTTP์š”์ฒญ์„ ์ „๋‹ฌ๋ฐ›๋Š” ๊ฒƒ์ด ์ฃผ๋ชฉ์ ์ด๋ฏ€๋กœ ์ด๋Ÿฌํ•œ ๋กœ์ง์€ ๋‹ค๋ฅธ๊ณณ์— ๊ตฌ์„ฑ๋˜๋Š”๊ฒƒ์ด ๊น”๋”ํ•œ ์ฝ”๋“œ์ด๋‹ค. ์ด๋Ÿฌํ•œ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์— ๋Œ€ํ•œ ๋กœ์ง์„ DTO์—๊ฒŒ ๋งก๊ธฐ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ• ์ˆ˜์žˆ๋‹ค.

  • @NotBlank : ์ •๋ณด๊ฐ€ ๋น„์–ด์žˆ๋Š”์ง€๋ฅผ ๊ฒ€์ฆ , null, ๊ณต๋ฐฑ, ์ŠคํŽ˜์ด์Šค ๊ฐ’์„ ํ—ˆ์šฉํ•˜์ง€์•Š์Œ
  • @Email : ์œ ํšจํ•œ ์ด๋ฉ”์ผ ์ฃผ์†Œ์ธ์ง€๋ฅผ ๊ฒ€์ฆ
  • @Pattern(regexp = "") : ์ •๊ทœํ‘œํ˜„์‹(Regular Expression)์„ ๋งค์น˜์‹œ์ผœ ์œ ํšจํ•œ์ง€ ๊ฒ€์ฆ
//์ปจํŠธ๋กค๋Ÿฌ

@RestController
@RequestMapping("/v1/members")
@Validated
public class MemberController {
		...

    @PatchMapping("/{member-id}")
    public ResponseEntity patchMember(@PathVariable("member-id") @Min(1) long memberId,
                                    @Valid @RequestBody MemberPatchDto memberPatchDto) {
                                    
                                    ...
    }
}
//DTO

@Getter
@Setter
public class MemberPostDto {
    @NotBlank
    @Email
    private String email;

    @NotBlank(message = "๊ณต๋ฐฑ์ด ์•„๋‹ˆ์—ฌ์•ผํ•ฉ๋‹ˆ๋‹ค.")
    private String name;

    @Pattern(regexp = "^010-\\d{3,4}-\\d{4}$")
    private String phone;
    }

์œ„์—์„œ ๋ณด๋‹ค์‹œํ”ผ ์ปจํŠธ๋กค๋Ÿฌ์— @Valid ์• ๋„ˆํ…Œ์ด์…˜๋งŒ ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ์œ ํšจ์„ฑ๊ฒ€์ฆ์— ๋Œ€ํ•œ ๋ถ€๋ถ„์€ DTO์—์„œ ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ฒŒ๋œ๋‹ค. ๋งŒ์•ฝ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ @Min() ๋“ฑ์˜ ์œ ํšจ์„ฑ๊ฒ€์ฆ ์• ๋„ˆํ…Œ์ด์…˜์ด ํ•„์š”ํ•œ๊ฒฝ์šฐ ํด๋ž˜์Šค์— @Validated๋ฅผ ๋ถ™์—ฌ์ค˜์•ผํ•œ๋‹ค.

 

[ref. Jakarta Bean Validation]

 

์›ํ•˜๋Š” ์ •๋ณด๋งŒ ์ „๋‹ฌ

์˜ˆ๋ฅผ๋“ค์–ด Member๋ผ๋Š” ๊ฐ์ฒด๊ฐ€ id, name, password์˜ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  ์žˆ์„๋•Œ password์˜ ๊ฒฝ์šฐ์—๋Š” ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์— ๊ทธ๋Œ€๋กœ ์ „๋‹ฌ๋˜๋ฉด ์•ˆ๋œ๋‹ค. ์ด๋Ÿฐ๊ฒฝ์šฐ Client์—๊ฒŒ ๋…ธ์ถœํ•ด๋„ ๋˜๋Š” ์ •๋ณด๋งŒ ๋ชจ์•„ DTO๋กœ ๊ตฌ์„ฑํ•˜๋ฉด ํ•ด๊ฒฐํ• ์ˆ˜์žˆ๋‹ค.

public class Member {

    private String id;
    private String name;
    private String password;
    
    ...
}
public class MemberDTO {
    private String name;
    
    ...
}

์„œ๋น„์Šค๊ณ„์ธต๊ณผ ๋ฐ์ดํ„ฐ์—‘์„ธ์Šค ๊ณ„์ธต์—์„œ๋Š” Member ๊ฐ์ฒด๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ณ , ์ด๋ฅผ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ DTO๊ฐ์ฒด๋กœ ๋งคํ•‘ํ•˜์—ฌ Client์—๊ฒŒ ๋ฆฌํ„ดํ•˜๋ฉด Client์—์„œ ์ ‘๊ทผํ• ์ˆ˜์žˆ๋Š”๊ฐ’์€ Name๋ฟ์ด๋‹ค. 

๋ฐ˜์‘ํ˜•