
✔ 쉽게 말하면?
"DB와 직접 소통하는 직원"
👉 회사(애플리케이션)에서 창고(DB)에 물건(데이터)을 넣고 빼는 직원
👉 SQL을 실행해서 데이터를 읽고, 쓰고, 수정, 삭제하는 역할
public class UserDAO {
public User getUserById(int id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new UserRowMapper());
}
}
✔ 쉽게 말하면?
"택배 상자 📦"
👉 DAO가 창고(DB)에서 가져온 물건을 상자(DTO)에 담아서 배달(Service → Controller)
👉 데이터를 전달하기 위한 객체 (DB와 직접 연결 X)
✔ 쉽게 말하면?
"창고(DB) 안에 있는 실제 물건"
👉 DAO(직원)가 창고(DB)에서 꺼내오는 진짜 상품(데이터)
👉 JPA를 사용하면 엔티티를 통해 DB 테이블에 직접 접근 가능
아래와 같은 Entity가 있을 때
@Entity
@Getter
@Setter
public class Member {
@Id
@GeneratedValue
private Long id;
private String name;
private int age;
}
✔ DB 테이블과 매핑되는 객체 (JPA 엔티티)
✔ 엔티티는 비즈니스 로직을 위한 객체이므로 API 응답에 직접 사용하면 위험하다.
➡️ DTO 사용
@Getter
@Setter
static class ResponseDto {
private String name;
private String result = "결과입니다.";
public ResponseDto(Member member) {
name = member.getName();
}
}
✔ DTO는 클라이언트에게 필요한 데이터만 포함
✔ result = "결과입니다."처럼 DTO 내부에서 추가적인 가공 가능
Controller
@PostMapping("api/useDTO")
@ResponseBody
public ResponseDto useDTO(@RequestParam String name, @RequestParam Long id) {
Member findMember = memberService.findOne(id);
return new ResponseDto(findMember);
}
✔ DTO를 사용하여 name과 result만 반환 (불필요한 데이터 제거)
엔티티 전체를 반환하면 id, name, age가 모두 클라이언트에 노출되어 보안 문제 발생 가능
예시를 들자면, 웹 화면에서 로그인하는 정보는 DTO로 처리하고, 테이블과 관련된 데이터는 VO로 처리한다.
✔ 쉽게 말하면?
"택배 상자 📦인데, 안에 담긴 물건을 절대 바꿀 수 없는 상자"
👉 한 번 값이 설정되면 변경되지 않음 (Immutable)
👉 equals()와 hashCode()를 오버라이딩하여 값 비교 가능
public class UserVO {
private final Long id;
private final String name;
private final int age;
public UserVO(Long id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Long getId() { return id; }
public String getName() { return name; }
public int getAge() { return age; }
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserVO userVO = (UserVO) o;
return age == userVO.age &&
id.equals(userVO.id) &&
name.equals(userVO.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age);
}
}
✔ final 키워드를 사용하여 값 변경 방지
✔ Setter 없이 생성자로만 값 설정 (불변 객체 유지)
✔ equals()와 hashCode()를 오버라이딩하여 값 비교 가능

1️⃣ Entity = 창고(DB)에 저장된 실제 물건
➕ 정확히는 Entity는 데이터(실제 물건)를 담는 틀이며, 데이터는 그 틀을 따라 만들어진 개별적인 값 (레코드)
2️⃣ DAO = 창고(DB)에서 물건(데이터)을 가져오고 넣는 직원
3️⃣ DTO = 창고에서 꺼낸 물건을 담아서 배달하는 택배 상자 (변경 가능)
4️⃣ VO = 값이 변하지 않는 특수한 택배 상자 (Immutable, 변경 불가능)