Java DAO와 DTO, 제대로 구분하고 있나요?
Java DAO와 DTO, 제대로 구분하고 있나요?
코드리뷰를 받다 보면 한 번쯤 이런 피드백을 만나게 됩니다.
"DAO가 DTO처럼 쓰이고 있어요. 역할을 분리해주세요."
처음엔 무슨 말인지 헷갈릴 수 있습니다. DAO도 데이터 관련이고, DTO도 데이터 관련인데 뭐가 다른 걸까요? 게다가 패키지명도 DAO로 써야 하는지 dao로 써야 하는지 애매하죠.
이 글에서는 DAO와 DTO의 역할 차이, 그리고 Java 네이밍 규칙까지 한 번에 정리해드립니다.
DAO와 DTO, 무엇이 다른가요?
DAO (Data Access Object)
DAO는 데이터베이스에 접근하는 로직을 담당하는 객체입니다. SELECT, INSERT, UPDATE, DELETE 같은 SQL을 실행하고 DB Connection을 관리하는 것이 DAO의 역할입니다.
// ✅ 올바른 DAO 예시
public class UserDao {
public UserDto findById(int id) {
// DB SELECT 로직
String sql = "SELECT * FROM users WHERE id = ?";
// Connection, PreparedStatement 처리...
return userDto;
}
public void save(UserDto dto) {
// DB INSERT 로직
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
// ...
}
}
DTO (Data Transfer Object)
DTO는 데이터를 담아서 계층 간에 전달하는 객체입니다. Controller ↔ Service ↔ DAO 사이를 오가며 데이터를 나릅니다. 비즈니스 로직은 없고, 필드와 getter/setter만 존재합니다.
// ✅ 올바른 DTO 예시
public class UserDto {
private String name;
private String email;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
한눈에 비교
| 구분 | 역할 | 담당 내용 | |------|------|-----------| | DAO | DB 접근 담당 | SQL 실행, Connection 관리 | | DTO | 데이터 전달 담당 | 필드 + getter/setter만 존재 |
흔한 실수: DAO가 DTO처럼 쓰이는 경우
// ❌ 안티패턴: DAO인데 DB 로직이 없고 데이터만 담고 있음
public class UserDAO {
private String name;
private String email;
public String getName() { return name; }
public String getEmail() { return email; }
// DB 접근 로직이 전혀 없다!
}
이렇게 되면 DAO라는 이름이 붙어 있지만 실제로는 DTO 역할을 하고 있는 겁니다. 나중에 코드를 읽는 사람이 "이 클래스가 DB를 다루나?" 하고 열어봤다가 혼란스러워집니다.
패키지 네이밍: 왜 DAO가 아니라 dao인가?
Java에서 패키지명은 모두 소문자가 공식 관례입니다. 약어도 예외가 없습니다.
✅ com.project.dao
✅ com.project.dto
✅ com.project.service
❌ com.project.DAO
❌ com.project.DTO
이유는 단순합니다. 대소문자를 구분하지 않는 파일 시스템(예: Windows)에서 패키지 충돌을 방지하기 위한 Java 공식 스타일 가이드 권고사항입니다.
클래스 네이밍: AlramTalkBasDTO → AlramTalkBasDto
클래스명은 PascalCase (각 단어 첫 글자 대문자)를 씁니다. 여기서 약어(DTO, DAO 등)도 하나의 단어처럼 취급해서 첫 글자만 대문자로 씁니다.
// ❌ 수정 전
public class AlramTalkBasDTO { }
// ✅ 수정 후
public class AlramTalkBasDto { }
약어별 변환 규칙:
| 약어 | PascalCase 표기 | |------|----------------| | DTO | Dto | | DAO | Dao | | HTTP | Http | | URL | Url | | ID | Id |
팀마다
DTO전체 대문자를 허용하는 경우도 있습니다. 항상 팀 컨벤션이 최우선입니다.
정리: 오늘 할 일 체크리스트
코드리뷰 피드백을 받았다면 다음 순서로 작업하면 됩니다.
- [ ] 패키지명
DAO→dao,DTO→dto로 소문자 변경 - [ ]
dao패키지 클래스들이 실제 DB 접근 로직을 담고 있는지 확인 - [ ] DB 로직 없이 데이터만 담고 있다면 →
dto패키지로 이동 또는 분리 - [ ] 클래스명 약어 부분
DTO→Dto,DAO→Dao로 수정 - [ ] 패키지/클래스명 변경 후 import 경로 전체 확인
IntelliJ를 쓴다면 Shift+F6 (Rename) 또는 우클릭 → Refactor → Rename을 사용하면 import 경로까지 자동으로 바꿔줍니다.
처음 보면 사소해 보이는 네이밍 규칙이지만, 팀 전체가 같은 규칙을 따를 때 코드 가독성이 크게 올라갑니다. DAO와 DTO의 역할만 명확히 분리해도 코드를 읽는 사람의 인지 부담이 줄어드니까요.