DAO๋ Data Access Object์ ์ฝ์๋ก, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ๋ ์ญํ ์ ํ๋ ๊ฐ์ฒด์ด๋ค.
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ๊ธฐ ์ํ ๋ก์ง๊ณผ ๋น์ฆ๋์ค ๋ก์ง์ ๋ถ๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค. (ํ๋ก์ ํธ์ ์๋น์ค ๋ชจ๋ธ์ ํด๋นํ๋ ๋ถ๋ถ๊ณผ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ฐ๊ฒฐํ๋ ์ญํ )
์ฆ, DB์ ์ ์ํ์ฌ ๋ฐ์ดํฐ์ CRUD(์์ฑ, ์กฐํ, ์์ , ์ญ์ ) ์์ ์ ์ ๋ดํ๋ ํด๋์ค์ด๋ค.
DAO๋ฅผ ์ฌ์ฉํ๋ ์ด์ ๊ฐ ๋ญ๊น?
DAO ์์
Data Transfer Object์ ์ฝ์๋ก, ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ธฐ ์ํ ๊ฐ์ฒด(Java Bean)์ด๋ค.
Controller (Web Layer)์ VIew (Service Layer) ์ฌ์ด์์ ๊ณ์ธต ๊ฐ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํ๊ธฐ ์ํ "๋ฐ๊ตฌ๋"๋ก ์ดํดํ ์ ์๊ฒ ๋ค. Entity Class๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋งคํ๋์ด ์๋ ํต์ฌ ํด๋์ค์ด๋ค. Entity Class๋ฅผ ๊ธฐ์ค์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค๊ฐ ๋ณ๊ฒฝ๋๊ธฐ ๋๋ฌธ์, ์์ฒญ์ด๋ ์๋ต ๊ฐ์ ์ ๋ฌํ๋ ํด๋์ค๋ก Entity Class๋ฅผ ์ฌ์ฉํด์๋ ์ ๋๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ DTO ํด๋์ค๋ฅผ ๋ฌ View์ ๋ค์ํ ๋ณํ์ Entity ํด๋์ค๊ฐ ์ง์ ์ ์ผ๋ก (์ํ์ง ์๋) ์ํฅ์ ๋ฐ์ง ์๋๋ก ํ๋ ๊ฒ์ด๋ค.
์ผ๋ฐ์ ์ผ๋ก DTO๋ ๋ก์ง์ ๊ฐ์ง๊ณ ์์ง ์์ ์์ํ ๋ฐ์ดํฐ ๊ฐ์ฒด์ด๋ฉฐ getter, setter ๋ฉ์๋๋ฅผ ํฌํจํ์ง๋ง ๋ค๋ฅธ ๋น์ฆ๋์ค ๋ก์ง์ ํฌํจํ์ง ์๋๋ค.
( DTO๋ ๋ฐ์ดํฐ ์ ๋ฌ๋ง์ ์ํ ๊ฐ์ฒด๋ผ๋ ๊ฒ ํต์ฌ ์ ์์๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์์ ํ ๋ฐ์ดํฐ ์ ๋ฌ ์ฉ๋๋ก๋ง ์ฌ์ฉํ๋ ๊ฒ ๋ชฉ์ ์ด๋ผ๋ฉด, gettet/setter๋ง ํ์ํ์ง, ์ด์ธ์ ๋น์ฆ๋์ค ๋ก์ง์ ๊ตณ์ด ์์ ํ์๊ฐ ์๋ค. )
DTO๋ ์ด๋ป๊ฒ ๊ตฌํํ๋๋์ ๋ฐ๋ผ ๊ฐ๋ณ ๊ฐ์ฒด๋ก ํ์ฉํ ์๋ ์๊ณ ๋ถ๋ณ ๊ฐ์ฒด๋ก ํ์ฉํ ์๋ ์๋ค. ์ด๋ ์์๋ฅผ ํตํด ์ดํด๋ณด์.
DTO ์์
// ๊ฐ๋ณ ๊ฐ์ฒด DTO
// ๊ธฐ๋ณธ ์์ฑ์๋ก ์์ฑ ํ ๊ฐ์ ์ ๋์ ์ผ๋ก ๋ณ๊ฒฝ
public class DtoEx {
private String name;
private int age;
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
}
// ๋ถ๋ณ ๊ฐ์ฒด DTO
// ์์ฑ์ ์ง์ ํ๋ ๊ฐ์ด ๋ณํ์ง ์๊ณ getter() ๋ฉ์๋๋ง ์ฌ์ฉ ๊ฐ๋ฅ
public class DtoEx {
private final String name;
private final int age;
public DtoEx(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
VO๋ Value Object์ ์ฝ์๋ก, ๊ฐ ์์ฒด๋ฅผ ํํํ๋ ๊ฐ์ฒด์ด๋ค. ์ฌ๊ธฐ์ ์ค์ํ ์ ์, VO๋ ๋ ๊ฐ์ฒด์ ํ๋ ๊ฐ์ด ๊ฐ์ผ๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ก ๋ณธ๋ค๋ ๊ฒ์ด๋ค. ์ฝ๊ฒ ์ค๋ช ํ์๋ฉด, ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ 10,000์ ์งํ๋ ๋ชจ๋ ๊ณ ์ ๋ฒํธ๊ฐ ์ธ์๋์ด ์์ง๋ง ์ฐ๋ฆฌ๋ ๊ทธ๊ฒ์ ์ธ์งํ์ง ์๊ณ ๋ค ๋๊ฐ์ '10,000์ ์งํ'๋ก๋ง ์ธ์ํ๋ค. ์ด๊ฒ์ด VO์ ๊ฐ์ ๊ฐ๋ (๊ฐ์ 10,000 / ๊ฐ์ฒด ์ฃผ์๋ ๊ณ ์ ๋ฒํธ)์ด๋ค.
์ ์์ ๋ง๊ฒ, VO๋ ๊ฐ ์์ฒด๋ฅผ ํํํด์ผ ํ๊ธฐ์ ๋ถ๋ณ์ฑ์ ๊ฐ์ ธ์ผ ํ๋ค. ๋ฐ๋ผ์, ์์ฑ์๋ฅผ ํตํด์๋ง ์ด๊ธฐํํด์ผ ํ๊ณ , setter๋ ์๋ Read-Only ์์ฑ ๊ฐ์ ๊ฐ์ ธ์ผ ํ๋ค.
DTO๋ '์ ๋ฌ'๋ง์ ๋ชฉ์ ์ผ๋ก ํ๊ธฐ์ getter, setter๋ง ํฌํจํ ์ ์๋ ๋ฐ๋ฉด, VO๋ ์ด์ธ์ ๋น์ฆ๋์ค ๋ก์ง๋ ํฌํจํ ์ ์๋ค๋ ์ฐจ์ด์ ์ด ์๋ค.
VO๋ ๋ ๊ฐ์ฒด์ ๋ชจ๋ ํ๋ ๊ฐ๋ค์ด ๋์ผํ๋ฉด ๋ ๊ฐ์ฒด๋ ๊ฐ๋ค! ๊ฐ ํต์ฌ ์ ์์๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์์ ํ ๊ฐ ์์ฒด ํํ ์ฉ๋๋ก๋ง ์ฌ์ฉํ๋ ๊ฒ ๋ชฉ์ ์ด๋ผ๋ฉด, ๋ ๊ฐ์ฒด์ ๋ชจ๋ ํ๋ ๊ฐ๋ค์ด ๋ชจ๋ ๊ฐ์ผ๋ฉด ๊ฐ์ ๊ฐ์ฒด์ด๋๋ก ๋ง๋๋ ๊ฒ(equals()์ hashCode()์ ์ค๋ฒ๋ผ์ด๋ฉ)์ด ์ค์ํ๋ค.
equals()์ hashCode()?
์์ฒ๋ผ, ๊ฐ์ฒด๋ฅผ ๋น๊ตํ๋ ๊ณผ์ ์์ ๋ ๊ฐ์ฒด์ hashCode() ๋ฆฌํด๊ฐ์ด ๊ฐ๊ณ , ๋์์ equals() ๋ฆฌํด๊ฐ์ด true์ผ ๊ฒฝ์ฐ ๋ ๊ฐ์ฒด๋ ๋์ผํ ๊ฐ์ฒด๋ผ๊ณ ํ๋จํ๋ค.
๊ทธ๋ฐ๋ฐ VO๋ '๋ ๊ฐ์ฒด์ ๋ชจ๋ ๊ฐ๋ง ๊ฐ์ผ๋ฉด ๊ฐ๋ค(ํ๋๋ก ๋ณธ๋ค)'๊ฐ ๊ทธ ์ ์์ด๋ฏ๋ก ์ผ๋ฐ์ ์ธ (์์) ํด๋์ค Money๋ฅผ VO๋ก ๋ง๋ค๊ธฐ ์ํด์๋ hashCode()์ equals()๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉ ํด ์ฃผ์ด์ผ ํ๋ค. ๊ตฌํ์ ๋ค์ ์์๋ฅผ ํตํด ์ดํด๋ณด์.
VO ์์
// VO์์
// ๊ฐ์ ํํ๋ง ํ๊ธฐ ๋๋ฌธ์ setter()๋ฉ์๋๋ ์ฌ์ฉํ์ง ์๋๋ค.
public class VoEx {
static class Money{
private final int value;
Money(int value) {
this.value = value;
}
public int getValue() {
return value;
}
// ์ฌ์ฉ์ ์์ฑ ๋ฉ์๋์ด์ง๋ง setterํํ์ ๋ฉ์๋๊ฐ ์๋๋ฏ๋ก ๋ฌด๊ดํจ
public String printMoney(){
return this.value + "์";
}
// ๋ ๊ฐ์ฒด์ ๋ชจ๋ ํ๋ ๊ฐ๋ค์ด ๋ชจ๋ ๊ฐ์ผ๋ฉด ๊ฐ์ ๊ฐ์ฒด์ด๋๋ก ๋ง๋ค๊ธฐ ์ํ ์ค๋ฒ๋ผ์ด๋ฉ โ ์ด๋ก์จ Money ๊ฐ์ฒด๊ฐ ์์ ํ VO๊ฐ ๋๋ค!
@Override
public int hashCode() {
return Objects.hash(value);
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null || getClass() != obj.getClass())
return false;
Money money = (Money) obj;
if(value == money.value)
return true;
else
return false;
}
}
}
DTO์ VO ๋น๊ต ์ ๋ฆฌ