스프링 프로젝트를 보다 보면
DTO, Entity, DAO라는 용어가 계속 등장합니다.초보자에게 가장 흔한 실수는
👉 “엔티티를 그대로 API 응답으로 써도 되지 않나요?” 입니다.결론부터 말하면 절대 안 됩니다.
이번 글에서는 각 개념의 역할과 왜 반드시 분리해야 하는지를
실전 예제와 함께 명확하게 설명합니다.
📌 목차
- DTO / Entity / DAO 한 줄 요약
- Entity란 무엇인가?
- DTO란 무엇인가?
- DAO(Repository)란 무엇인가?
- 왜 Entity를 그대로 쓰면 안 되는가?
- 올바른 계층별 흐름
- 실전 예제 (회원 조회 API)
- 자주 하는 실수
- 마무리
- 대표 태그
1️⃣ DTO / Entity / DAO 한 줄 요약
| 구분 | 역할 |
| Entity | DB 테이블과 1:1 매핑되는 객체 |
| DTO | 계층 간 데이터 전달용 객체 |
| DAO(Repository) | DB 접근 담당 |
👉 역할이 완전히 다릅니다.
2️⃣ Entity란 무엇인가?
Entity는 데이터베이스 테이블을 Java 객체로 표현한 클래스입니다.
JPA를 사용할 때 @Entity로 표시합니다.
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String email;
private String password;
}
✔ DTO의 특징
- DB와 직접적인 연관 없음
- 필요한 데이터만 담음
- 보안에 유리 (비밀번호 제외 가능)
- API 스펙에 최적화
4️⃣ DAO(Repository)란?
DAO는 DB에 접근하는 역할만 담당하는 계층입니다.
스프링에서는 보통 Repository로 표현합니다.
public interface UserRepository extends JpaRepository<User, Long> {
}
✔ DAO의 역할
- 저장(save)
- 조회(find)
- 수정
- 삭제
👉 비즈니스 로직은 절대 DAO에 있으면 안 됨
5️⃣ 왜 Entity를 그대로 쓰면 안 되는가? (매우 중요)
❌ 잘못된 예:
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
return userRepository.findById(id).get();
}
🚨 문제점
1️⃣ 보안 문제
- password, 내부 필드가 그대로 노출됨
2️⃣ API 변경 = DB 구조 변경
- 필드 하나 추가/삭제 시 API 깨짐
3️⃣ 엔티티 변경 시 사이드 이펙트
- JPA 영속성 컨텍스트 예기치 않은 업데이트
4️⃣ 레이어 간 결합도 증가
- 유지보수 지옥 시작
6️⃣ 올바른 계층별 흐름
[Client]
↓
Controller (DTO 사용)
↓
Service (Entity ↔ DTO 변환)
↓
Repository (Entity만 사용)
↓
DB
👉 Controller는 DTO만 알고
👉 Repository는 Entity만 알도록 분리
7️⃣ 실전 예제 — 회원 조회 API
✔ Entity
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String email;
private String password;
}
✔ DTO (응답용)
public class UserResponseDto {
private Long id;
private String email;
public UserResponseDto(User user) {
this.id = user.getId();
this.email = user.getEmail();
}
}
✔ Service
@Service
public class UserService {
private final UserRepository repo;
public UserService(UserRepository repo) {
this.repo = repo;
}
public UserResponseDto getUser(Long id) {
User user = repo.findById(id)
.orElseThrow();
return new UserResponseDto(user);
}
}
✔ Controller
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService service;
public UserController(UserService service) {
this.service = service;
}
@GetMapping("/{id}")
public UserResponseDto getUser(@PathVariable Long id) {
return service.getUser(id);
}
}
➡ Entity는 절대 Controller로 나오지 않음
8️⃣ 자주 하는 실수
❌ Entity = DTO 라고 생각함
→ 절대 아님. 목적이 다름
❌ Controller에서 Entity 직접 반환
→ 보안/유지보수 문제 발생
❌ DAO에 비즈니스 로직 작성
→ Service 계층 책임
❌ DTO에 로직 넣기
→ DTO는 데이터 운반용 객체
9️⃣ 마무리
이번 글에서 스프링 실무의 핵심 개념을 정리했습니다.
✔ Entity = DB 전용 객체
✔ DTO = 데이터 전달 객체
✔ DAO(Repository) = DB 접근 계층
✔ Entity와 DTO는 반드시 분리
✔ 유지보수·보안·확장성 모두 개선
이 구조를 지키면 스프링 프로젝트의 70%는 성공이라고 봐도 됩니다.