[JAVA] DTO(Data Transfer Object)์™€ VO(Value Object)

DANIยท2023๋…„ 10์›” 5์ผ
0

JAVA๋ฅผ ๊ณต๋ถ€ํ•ด๋ณด์ž

๋ชฉ๋ก ๋ณด๊ธฐ
10/29
post-thumbnail

๐Ÿ“• DTO(Data Transfer Object)๋ž€?


์ˆœ์ˆ˜ํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ด์•„ ๊ณ„์ธต ๊ฐ„(Controller, View, Business Layer) ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ ์œ„ํ•œ ์ž๋ฐ” ๋นˆ์ฆˆ(Java Beans)๋ฅผ ์˜๋ฏธํ•œ๋‹ค.

๋กœ์ง์„ ๊ฐ–๊ณ  ์žˆ์ง€ ์•Š์€ ์ˆœ์ˆ˜ํ•œ ๋ฐ์ดํ„ฐ ๊ฐ์ฒด์ด๋ฉฐ ๋ฉ”์„œ๋“œ๋กœ๋Š” getter/setter ๋งŒ์„ ๊ฐ–๋Š”๋‹ค.(์ถ”๊ฐ€์ ์œผ๋กœ toString(), equals()๋“ฑ์˜ Object ํด๋ž˜์Šค ๋ฉ”์†Œ๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.)

๐Ÿ’ก DTO์˜ ํŠน์ง•


  • ์ฃผ๋กœ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ๋•Œ ์‚ฌ์šฉ.
  • getter/setter ๋ฉ”์„œ๋“œ๋งŒ ๊ฐ€์ง„ ํด๋ž˜์Šค๋ฅผ ์˜๋ฏธํ•จ.
  • DB์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์–ป์–ด์„œ Service๋‚˜ Controller ๋“ฑ์œผ๋กœ ๋ณด๋‚ผ ๋•Œ ์‚ฌ์šฉ.(์ฆ‰ ์—”ํ‹ฐํ‹ฐ๋ฅผ DTO ํ˜•ํƒœ๋กœ ๋ณ€ํ™˜ํ•œ ํ›„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.)

๐Ÿ”ด DTO์˜ ์˜ˆ (getter/setter๋กœ์ง์ด ์žˆ๋Š” ๊ฒฝ์šฐ)

public class DTO {
	private String name;
	private int age;
	
	public void setAge(int age) {
		this.age = age;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}
}

๐Ÿ”ด DTO์˜ ์˜ˆ (์ƒ์„ฑ์ž๋ฅผ ์ด์šฉํ•œ ๋ถˆ๋ณ€ ๊ฐ์ฒด์ธ ๊ฒฝ์šฐ)

public class DTO {
	private String name;
	private int age;
	
    public DTO(String name, int age){
    	this.name = name;
        this.age = age;
    }
	
	public String getName() {
		return name;
	}

	public int getAge() {
		return age;
	}
}

DB์—์„œ ๊บผ๋‚ธ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” Entity๋ฅผ ๊ฐ€์ง€๊ณ  ๋งŒ๋“œ๋Š” ์ผ์ข…์˜ Wrapper๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, Entity๋ฅผ Controller์™€ ๊ฐ™์€ ํด๋ผ์ด์–ธํŠธ๋‹จ๊ณผ ์ง์ ‘ ๋งˆ์ฃผํ•˜๋Š” ๊ณ„์ธต์— ์ง์ ‘ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹  DTO๋ฅผ ์‚ฌ์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ตํ™˜ํ•œ๋‹ค.


๐Ÿ’ป DTO๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ ํ•˜๋Š” ์˜ˆ์‹œ


๐Ÿ’พ Entity ์˜ˆ์‹œ

@Getter
@Setter
@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;
	private int age;
}

id(๊ธฐ๋ณธํ‚ค), name, age์˜ ์†์„ฑ์„ ๊ฐ–๋Š” User Entity


๐Ÿ’พ DTO class

@Getter
@Setter
static class UsernameDto {
	private String name;

    public UserDto(User user) {
    	this.name = user.getName();
    }
}

์ด๋ฆ„๊ฐ’๋งŒ ๊ฐ–๋Š” DTO


๐Ÿ’ป Controller

@PostMapping("api/useDTO")
@ResponseBody
public UsernameDto userDTO(@RequestParam String name, @RequestParam Long id) {
	User finduser = userService.findId(id);
    return new UsernameDto(finduser);
}

@PostMapping("api/notUseDTO")
@ResponseBody
public FindUser notUseDTO(@RequestParam String name, @RequestParam Long id) {
	User finduser = userService.findId(id);
    return new FindMember(finduser);
}

userDTO๋Š” name๊ฐ’๋งŒ ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ฐ˜ํ™˜ํ•˜๊ณ , notUseDTO๋Š” ์—”ํ‹ฐํ‹ฐ์˜ ๋ชจ๋“  ์†์„ฑ(id, name, age)๋ฅผ ๋ฐ˜ํ™˜ํ•จ



๐Ÿ“• VO(Value Object)๋ž€?


VO๋Š” ๊ฐ’ ๊ทธ ์ž์ฒด๋ฅผ ๋‚˜ํƒœ๋Š” ๊ฐ์ฒด๋กœ์„œ, Read-Only์˜ ํŠน์ง•์„ ๊ฐ€์ง„๋‹ค.

DTO์™€ ๋ฐ˜๋Œ€๋กœ ๋กœ์ง์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, VO์˜ ๊ฒฝ์šฐ ํŠน์ • ๊ฐ’ ์ž์ฒด๋ฅผ ํ‘œํ˜„ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋ถˆ๋ณ€์„ฑ์˜ ๋ณด์žฅ์„ ์œ„ํ•ด ์ƒ์„ฑ์ž๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ์•ผ ํ•œ๋‹ค.

VO๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ์ด๋ฆ„์„ ๊ฐ–๋Š” VO ์ธ์Šคํ„ด์Šค๋ผ๋„ ๋ชจ๋“  ์†์„ฑ ๊ฐ’์ด ๊ฐ™๋‹ค๋ฉด ๋‘ ์ธ์Šคํ„ด์Šค๋Š” ๊ฐ™์€ ๊ฐ์ฒด์ธ ๊ฒƒ์ด ํ•ต์‹ฌ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด ๋ชจ๋‘ ๋˜‘๊ฐ™์€ ์ž๋™์ฐจ๊ฐ€ ์ƒ‰๊น”๋งŒ ๋‹ค๋ฅด๋‹ค๊ณ  ํ•˜๋”๋ผ๋„ ์ด๋ฅผ ๋ณ„๊ฐœ์˜ ๊ฐ์ฒด๋กœ ๋ณด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ•˜๋‚˜์˜ ๊ฐ์ฒด(์ž๋™์ฐจ)๋กœ ๋ณด๋Š”๊ฒƒ๊ณผ ๊ฐ™๋‹ค.

์ฆ‰, VO๋Š” ๊ฐ’ ๊ทธ ์ž์ฒด๋ฅผ ๋‚˜ํƒ€๋‚ด๊ธฐ ๋•Œ๋ฌธ์— setter ๊ฐ™์€ ์„ฑ๊ฒฉ์˜ ๋ณ€์กฐ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•˜๋ฉด ์•ˆ๋˜๋ฉฐ, ๋‘ ๊ฐ์ฒด์˜ 'ํ•„๋“œ ๊ฐ’์ด ๊ฐ™๋‹ค๋ฉด' ๋ชจ๋‘ ๊ฐ™์€ ๊ฐ์ฒด๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ํ•ต์‹ฌ์ด๋‹ค.

VO์˜ ํ•ต์‹ฌ ์—ญํ• ์€ equals()์™€ hashcode() ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉ ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

๐Ÿ”ด VO์˜ ์˜ˆ (์ƒ์„ฑ์ž๋ฅผ ์ด์šฉํ•œ ๋ถˆ๋ณ€ ๊ฐ์ฒด)

public class VO {
	private final String name;
	
	public VO(String name) {
		this.name = name;
	}
}

๐Ÿ”ด equals()์™€ hashcode() ์˜ค๋ฒ„๋ผ์ด๋”ฉ

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Article article = (Article) o;
    return Objects.equals(id, article.id);
}

@Override
public int hashCode() {
    return Objects.hash(id);
}

โœ… DTO vs VO

DTOVO
์šฉ๋„๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์ธต๊ฐ„ ๊ตํ™˜(Transfer)ํ•˜๋Š”๋ฐ ์˜๋ฏธ์ฝ๊ธฐ๋งŒ ๊ฐ€๋Šฅํ•œ read-only ์†์„ฑ์„ ๊ฐ€์ง„ ๊ฐ์ฒด๋กœ์„œ ๋ฐ์ดํ„ฐ ๊ทธ ์ž์ฒด์— ์˜๋ฏธ
๋™๋“ฑ ๊ฒฐ์ •์†์„ฑ๊ฐ’์ด ๋ชจ๋‘ ๊ฐ™์•„๋„ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ ์•„๋‹ ์ˆ˜ ์žˆ์Œ์†์„ฑ๊ฐ’์ด ๋ชจ๋‘ ๊ฐ™์œผ๋ฉด ๊ฐ™์€ ๊ฐ์ฒด๋กœ ๋ด„
๊ฐ€๋ณ€/๋ถˆ๋ณ€์„ฑ๊ฐ€๋ณ€์„ฑ, ๋ถˆ๋ณ€์„ฑๆœ‰๋ถˆ๋ณ€
๋กœ์งgetter/settergetter/setter์ด์™ธ์˜ ๋กœ์ง์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Œ
-์ธ์Šคํ„ด์Šค ๊ฐœ๋…๋ฆฌํ„ฐ๋Ÿด ๊ฐœ๋…
-์ฆ‰, Layer๊ฐ„์˜ ํ†ต์‹  ์šฉ๋„๋กœ ์˜ค๊ณ ๊ฐ€๋Š” ๊ฐ์ฒดํŠน์ •ํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๊ฐ’์„ ๋‹ด๋Š” ๊ฐ์ฒด


๐Ÿ“• DAO(Data Access Object)๋ž€?


DB์˜ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ๊ฐ์ฒด๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค. DB์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•œ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. ์ง์ ‘ DB์— ์ ‘๊ทผํ•˜์—ฌ data๋ฅผ ์‚ฝ์ž…, ์‚ญ์ œ, ์กฐํšŒ, ์ˆ˜์ • ๋“ฑ CRUD ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. Service์™€ DB๋ฅผ ์—ฐ๊ฒฐํ•˜๋Š” ๊ณ ๋ฆฌ ์—ญํ• ์„ ํ•œ๋‹ค.

๐Ÿ“ฅ ์œ ์ €๊ฐ€ ์ž…๋ ฅํ•œ ๋ฐ์ดํ„ฐ๋ฅผ DB์— ๋„ฃ๋Š” ๊ณผ์ •


  1. ์œ ์ €๊ฐ€ ์ž์‹ ์˜ ๋ธŒ๋ผ์šฐ์ €์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•˜์—ฌ form์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ DTO์— ๋„ฃ์–ด ์ „์†กํ•œ๋‹ค.
  2. ํ•ด๋‹น DTO๋ฅผ ๋ฐ›์€ ์„œ๋ฒ„๊ฐ€ DAO๋ฅผ ์ด์šฉํ•ด DB๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ง‘์–ด๋„ฃ๋Š”๋‹ค.

0๊ฐœ์˜ ๋Œ“๊ธ€