์์ํ๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ด์ ๊ณ์ธต ๊ฐ(Controller, View, Business Layer) ๋ฐ์ดํฐ ๊ตํ์ ์ํ ์๋ฐ ๋น์ฆ(Java Beans)๋ฅผ ์๋ฏธํ๋ค.
๋ก์ง์ ๊ฐ๊ณ ์์ง ์์ ์์ํ ๋ฐ์ดํฐ ๊ฐ์ฒด์ด๋ฉฐ ๋ฉ์๋๋ก๋ getter/setter ๋ง์ ๊ฐ๋๋ค.(์ถ๊ฐ์ ์ผ๋ก toString(), equals()๋ฑ์ Object ํด๋์ค ๋ฉ์๋๋ฅผ ์์ฑํ ์ ์๋ค.)
๐ก DTO์ ํน์ง
- ์ฃผ๋ก ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ํ ๋ ์ฌ์ฉ.
- getter/setter ๋ฉ์๋๋ง ๊ฐ์ง ํด๋์ค๋ฅผ ์๋ฏธํจ.
- DB์์ ๋ฐ์ดํฐ๋ฅผ ์ป์ด์ Service๋ Controller ๋ฑ์ผ๋ก ๋ณด๋ผ ๋ ์ฌ์ฉ.(์ฆ ์ํฐํฐ๋ฅผ DTO ํํ๋ก ๋ณํํ ํ ์ฌ์ฉํฉ๋๋ค.)
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;
}
}
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๋ฅผ ์ฌ์ฉํด ๋ฐ์ดํฐ๋ฅผ ๊ตํํ๋ค.
@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
@Getter
@Setter
static class UsernameDto {
private String name;
public UserDto(User user) {
this.name = user.getName();
}
}
์ด๋ฆ๊ฐ๋ง ๊ฐ๋ DTO
@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๋ ๊ฐ ๊ทธ ์์ฒด๋ฅผ ๋ํ๋ ๊ฐ์ฒด๋ก์, Read-Only์ ํน์ง์ ๊ฐ์ง๋ค.
DTO์ ๋ฐ๋๋ก ๋ก์ง์ ํฌํจํ ์ ์์ผ๋ฉฐ, VO์ ๊ฒฝ์ฐ ํน์ ๊ฐ ์์ฒด๋ฅผ ํํํ๊ธฐ ๋๋ฌธ์ ๋ถ๋ณ์ฑ์ ๋ณด์ฅ์ ์ํด ์์ฑ์๋ฅผ ์ฌ์ฉํ์ฌ์ผ ํ๋ค.
VO๋ ์๋ก ๋ค๋ฅธ ์ด๋ฆ์ ๊ฐ๋ VO ์ธ์คํด์ค๋ผ๋ ๋ชจ๋ ์์ฑ ๊ฐ์ด ๊ฐ๋ค๋ฉด ๋ ์ธ์คํด์ค๋ ๊ฐ์ ๊ฐ์ฒด์ธ ๊ฒ์ด ํต์ฌ์ด๋ค.
์๋ฅผ ๋ค์ด ๋ชจ๋ ๋๊ฐ์ ์๋์ฐจ๊ฐ ์๊น๋ง ๋ค๋ฅด๋ค๊ณ ํ๋๋ผ๋ ์ด๋ฅผ ๋ณ๊ฐ์ ๊ฐ์ฒด๋ก ๋ณด๋ ๊ฒ์ด ์๋๋ผ ํ๋์ ๊ฐ์ฒด(์๋์ฐจ)๋ก ๋ณด๋๊ฒ๊ณผ ๊ฐ๋ค.
์ฆ, VO๋ ๊ฐ ๊ทธ ์์ฒด๋ฅผ ๋ํ๋ด๊ธฐ ๋๋ฌธ์ setter ๊ฐ์ ์ฑ๊ฒฉ์ ๋ณ์กฐ ๊ฐ๋ฅ์ฑ์ด ์๋ ๋ฉ์๋๊ฐ ์กด์ฌํ๋ฉด ์๋๋ฉฐ, ๋ ๊ฐ์ฒด์ 'ํ๋ ๊ฐ์ด ๊ฐ๋ค๋ฉด' ๋ชจ๋ ๊ฐ์ ๊ฐ์ฒด๋ก ๋ง๋๋ ๊ฒ์ด ํต์ฌ์ด๋ค.
VO์ ํต์ฌ ์ญํ ์ equals()์ hashcode() ๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉ ํ๋ ๊ฒ์ด๋ค.
public class VO {
private final String name;
public VO(String name) {
this.name = name;
}
}
@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 | VO | |
---|---|---|
์ฉ๋ | ๋ฐ์ดํฐ๋ฅผ ๊ณ์ธต๊ฐ ๊ตํ(Transfer)ํ๋๋ฐ ์๋ฏธ | ์ฝ๊ธฐ๋ง ๊ฐ๋ฅํ read-only ์์ฑ์ ๊ฐ์ง ๊ฐ์ฒด๋ก์ ๋ฐ์ดํฐ ๊ทธ ์์ฒด์ ์๋ฏธ |
๋๋ฑ ๊ฒฐ์ | ์์ฑ๊ฐ์ด ๋ชจ๋ ๊ฐ์๋ ๊ฐ์ ๊ฐ์ฒด๊ฐ ์๋ ์ ์์ | ์์ฑ๊ฐ์ด ๋ชจ๋ ๊ฐ์ผ๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ก ๋ด |
๊ฐ๋ณ/๋ถ๋ณ์ฑ | ๊ฐ๋ณ์ฑ, ๋ถ๋ณ์ฑๆ | ๋ถ๋ณ |
๋ก์ง | getter/setter | getter/setter์ด์ธ์ ๋ก์ง์ ๊ฐ์ง ์ ์์ |
- | ์ธ์คํด์ค ๊ฐ๋ | ๋ฆฌํฐ๋ด ๊ฐ๋ |
- | ์ฆ, Layer๊ฐ์ ํต์ ์ฉ๋๋ก ์ค๊ณ ๊ฐ๋ ๊ฐ์ฒด | ํน์ ํ ๋น์ฆ๋์ค ๊ฐ์ ๋ด๋ ๊ฐ์ฒด |
DB์ ๋ฐ์ดํฐ์ ์ ๊ทผํ๊ธฐ ์ํ ๊ฐ์ฒด๋ฅผ ๊ฐ๋ฆฌํจ๋ค. DB์ ์ ๊ทผํ๊ธฐ ์ํ ๋ก์ง์ ๋ถ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค. ์ง์ DB์ ์ ๊ทผํ์ฌ data๋ฅผ ์ฝ์ , ์ญ์ , ์กฐํ, ์์ ๋ฑ CRUD ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค. Service์ DB๋ฅผ ์ฐ๊ฒฐํ๋ ๊ณ ๋ฆฌ ์ญํ ์ ํ๋ค.
๐ฅ ์ ์ ๊ฐ ์ ๋ ฅํ ๋ฐ์ดํฐ๋ฅผ DB์ ๋ฃ๋ ๊ณผ์
- ์ ์ ๊ฐ ์์ ์ ๋ธ๋ผ์ฐ์ ์์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํ์ฌ form์ ์๋ ๋ฐ์ดํฐ๋ฅผ DTO์ ๋ฃ์ด ์ ์กํ๋ค.
- ํด๋น DTO๋ฅผ ๋ฐ์ ์๋ฒ๊ฐ DAO๋ฅผ ์ด์ฉํด DB๋ก ๋ฐ์ดํฐ๋ฅผ ์ง์ด๋ฃ๋๋ค.