← 개발일지

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 공식 스타일 가이드 권고사항입니다.


클래스 네이밍: AlramTalkBasDTOAlramTalkBasDto

클래스명은 PascalCase (각 단어 첫 글자 대문자)를 씁니다. 여기서 약어(DTO, DAO 등)도 하나의 단어처럼 취급해서 첫 글자만 대문자로 씁니다.

// ❌ 수정 전
public class AlramTalkBasDTO { }

// ✅ 수정 후
public class AlramTalkBasDto { }

약어별 변환 규칙:

| 약어 | PascalCase 표기 | |------|----------------| | DTO | Dto | | DAO | Dao | | HTTP | Http | | URL | Url | | ID | Id |

팀마다 DTO 전체 대문자를 허용하는 경우도 있습니다. 항상 팀 컨벤션이 최우선입니다.


정리: 오늘 할 일 체크리스트

코드리뷰 피드백을 받았다면 다음 순서로 작업하면 됩니다.

  • [ ] 패키지명 DAOdao, DTOdto 로 소문자 변경
  • [ ] dao 패키지 클래스들이 실제 DB 접근 로직을 담고 있는지 확인
  • [ ] DB 로직 없이 데이터만 담고 있다면 → dto 패키지로 이동 또는 분리
  • [ ] 클래스명 약어 부분 DTODto, DAODao 로 수정
  • [ ] 패키지/클래스명 변경 후 import 경로 전체 확인

IntelliJ를 쓴다면 Shift+F6 (Rename) 또는 우클릭 → Refactor → Rename을 사용하면 import 경로까지 자동으로 바꿔줍니다.


처음 보면 사소해 보이는 네이밍 규칙이지만, 팀 전체가 같은 규칙을 따를 때 코드 가독성이 크게 올라갑니다. DAO와 DTO의 역할만 명확히 분리해도 코드를 읽는 사람의 인지 부담이 줄어드니까요.