๊ด€๋ฆฌ ๋ฉ”๋‰ด

๋‚˜์˜ ๋ชจ์–‘

042 | DTO with HTTP Request & Response ๋ณธ๋ฌธ

SEB/TIL

042 | DTO with HTTP Request & Response

kexon 2022. 8. 22. 22:46

๐ŸŽˆ DTO(Data Trasfer Object)

  • ๋งˆํ‹ด ํŒŒ์šธ๋Ÿฌ(Martin Fowler)๊ฐ€ ‘Patterns of Enterprise Application Architecture’ ๋ผ๋Š” ์ฑ…์—์„œ ์ฒ˜์Œ ์†Œ๊ฐœํ•œ ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„ํ‚คํ…์ฒ˜ ํŒจํ„ด์˜ ํ•˜๋‚˜์ด๋‹ค.
  • ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด
    ์ฃผ๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„ ์ชฝ์œผ๋กœ ์ „์†กํ•˜๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ ๋ฐ›์„ ๋•Œ, ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ ์ชฝ์œผ๋กœ ์ „์†กํ•˜๋Š” ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ์šฉ๋„๋กœ ์‚ฌ์šฉ๋œ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์ „์†ก์ด ์ด๋ฃจ์–ด์ง€๋Š” ๊ตฌ๊ฐ„
    • ํด๋ผ์ด์–ธํŠธ → ์„œ๋ฒ„: ์š”์ฒญ(request) ๋ฐ์ดํ„ฐ
    • ์„œ๋ฒ„ → ํด๋ผ์ด์–ธํŠธ: ์‘๋‹ต(response) ๋ฐ์ดํ„ฐ
  • DTO ํด๋ž˜์Šค: ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ์ „๋‹ฌ ๋ฐ›๋Š” ์—ญํ• 

๐ŸŽˆ DTO๊ฐ€ ํ•„์š”ํ•œ ์ด์œ 

  • ํด๋ผ์ด์–ธํŠธ์˜ Request Body๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ์ฒด๋กœ ๋ชจ๋‘ ์ „๋‹ฌ ๋ฐ›์„ ์ˆ˜ ์žˆ์Œ → ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค.
//ํšŒ์› ์ •๋ณด ์ €์žฅ์„ ์œ„ํ•ด postMember์— @RequestParam ์‚ฌ์šฉ

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @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);

        return new ResponseEntity<Map>(map, HttpStatus.CREATED);
    }
		
		...
}
// DTO ์ ์šฉ
// - @RequestParam์„ ํ†ตํ•ด ์ „๋‹ฌ ๋ฐ›์€ ์š”์ฒญ ๋ฐ์ดํ„ฐ๋“ค์„ Map์— ์ถ”๊ฐ€ํ•˜๋Š” ๋กœ์ง์ด ์‚ฌ๋ผ์ง
// - MemberDto ๊ฐ์ฒด๋ฅผ ResponseEntity ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•˜๋„๋ก ๋ณ€๊ฒฝ

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(MemberDto memberDto) {
        return new ResponseEntity<MemberDto>(memberDto, HttpStatus.CREATED);
    }
		
		...
}

 

๐ŸŽˆ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ(Validation) ๊ฒ€์ฆ์˜ ๋‹จ์ˆœํ™”

  • ์œ ํšจ์„ฑ(Validation) ๊ฒ€์ฆ: ์„œ๋ฒ„์—์„œ ์œ ํšจํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌ๋ฐ›๊ธฐ ์œ„ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ฒƒ
  • HTTP ์š”์ฒญ์„ ์ „๋‹ฌ ๋ฐ›๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ์˜ ์ฃผ ๋ชฉ์ 
    • ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์— ์žˆ๋Š” ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๋กœ์ง์„ ์™ธ๋ถ€์— ์ž‘์„ฑ → ์ฝ”๋“œ๊ฐ€ ๊ฐ„๊ฒฐ
    • ์š”์ฒญ์„ ์ „๋‹ฌ๋ฐ›๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ตœ๋Œ€ํ•œ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑ
// ๋ ˆ๊ฑฐ์‹œ ์ฝ”๋“œ์—์„œ ์ด๋ฉ”์ผ ๊ฒ€์ฆํ•˜๊ธฐ

if (!email.matches("^[a-zA-Z0-9_!#$%&'\\*+/=?{|}~^.-]+@[a-zA-Z0-9.-]+$")) {
    throw new InvalidParameterException();
}
// Using DTO Class

public class MemberDto {
    @Email
    private String email;
    private String name;
    private String phone;

    // + getter / setter
}
// Handler Method with DTO

@RestController
@RequestMapping("/v1/members")
public class MemberController {
    @PostMapping
    public ResponseEntity postMember(@Valid MemberDto memberDto) {
        return new ResponseEntity<MemberDto>(memberDto, HttpStatus.CREATED);
    }

		...
}

๐ŸŽˆ HTTP ์š”์ฒญ/์‘๋‹ต ๋ฐ์ดํ„ฐ์— DTO ์ ์šฉํ•˜๊ธฐ

HTTP Request Body != JSON

  • ์ด์ „๊นŒ์ง€ ์‚ฌ์šฉํ•œ ํด๋ผ์ด์–ธํŠธ์—์„œ ์ „๋‹ฌํ•˜๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ: x-www-form-urlencoded
  • ์š”์ฒญ ๋ฐ์ดํ„ฐ ์ค‘ ๋ฐ”๋””์— ํ•ด๋‹น๋˜๋Š” ๋ฐ์ดํ„ฐ: Request Body

HTTP Request Body == JSON

DTO ํด๋ž˜์Šค ์ ์šฉ์„ ์œ„ํ•œ ์ฝ”๋“œ ๋ฆฌํŒฉํ† ๋ง ์ ˆ์ฐจ

  • ์ •๋ณด๋ฅผ ์ „๋‹ฌ ๋ฐ›์„ DTO ํด๋ž˜์Šค ์ƒ์„ฑ
  • ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ ์ „๋‹ฌํ•˜๋Š” ์š”์ฒญ ๋ฐ์ดํ„ฐ๋ฅผ @RequestParam ์• ๋„ˆํ…Œ์ด์…˜์œผ๋กœ ์ „๋‹ฌ ๋ฐ›๋Š” ํ•ธ๋“ค๋Ÿฌ ๋ฉ”์„œ๋“œ ์ฐพ๊ธฐ
  • @RequestParam ์ชฝ ์ฝ”๋“œ๋ฅผ DTO ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋กœ ์ˆ˜์ •
  • Map ๊ฐ์ฒด๋กœ ์ž‘์„ฑ๋˜์–ด ์žˆ๋Š” Response Body๋ฅผ DTO ํด๋ž˜์Šค์˜ ๊ฐ์ฒด๋กœ ๋ณ€๊ฒฝ

๐ŸŽˆ more

  • Response Body๋ฅผ JSON ํ˜•์‹์œผ๋กœ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” @ResponseBody ์• ๋„ˆํ…Œ์ด์…˜์„ ๋ฉ”์„œ๋“œ ์•ž์— ๋ถ™์—ฌ ์ฃผ์–ด์•ผํ•˜์ง€๋งŒ ResponseEntity ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ด ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ @ResponseBody๋ฅผ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ์ชฝ์—์„œ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ฒ„ ์ชฝ์œผ๋กœ ์ „์†กํ•˜๋ฉด ์„œ๋ฒ„ ์ชฝ์˜ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ „๋‹ฌ ๋ฐ›์€ JSON ํ˜•์‹์˜ ๋ฐ์ดํ„ฐ๋ฅผ DTO ๊ฐ™์€ Java์˜ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•˜๋Š”๋ฐ ์ด๋ฅผ ์—ญ์ง๋ ฌํ™”(Deserialization)์ด๋ผ๊ณ  ํ•œ๋‹ค.
    • JSON → DTO: ์—ญ์ง๋ ฌํ™”(Deserialization)
  • ์„œ๋ฒ„ ์ชฝ์—์„œ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•ด์„œ DTO ๊ฐ™์€ Java์˜ ๊ฐ์ฒด๋ฅผ JSON ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ๊ฒƒ์„ ์ง๋ ฌํ™”(Serialization)๋ผ๊ณ  ํ•œ๋‹ค.
    • DTO → JSON: ์ง๋ ฌํ™”(Serialization)

'SEB > TIL' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

043 | Layer interconnect & Class Mapping  (0) 2022.08.23
042 | DTO ์œ ํšจ์„ฑ ๊ฒ€์ฆ  (0) 2022.08.23
031 | RDBMS, SQL, ACID  (0) 2022.08.04
030 | REST API  (0) 2022.08.03
029 | ๋„คํŠธ์›Œํฌ - HTTP  (0) 2022.08.02
Comments