[Java] JPA에서 DTO는 Interface로 구현할까? Class로 구현할까?

2025. 8. 3. 22:33·개발 (Development)/Java

JPA를 사용할 때 DTO(Data Transfer Object)를 어떻게 정의할지 고민이 되는 경우가 많습니다. 특히 interface 기반 DTO와 class 기반 DTO 중 어떤 방식을 선택해야 할지 혼란스러울 수 있는데요, 이번 글에서는 두 방식의 차이점과 사용 목적에 따라 어떤 방식을 선택하면 좋을지 정리해보았습니다.

Interface 기반 DTO

예시

public interface UserDto {
    String getName();
    int getAge();
}
@Query("SELECT u.name as name, u.age as age FROM User u")
List<UserDto> findUsers();

장점

  • 코드가 간단하며, getter만 정의하면 JPA가 구현체를 자동으로 생성합니다.
  • 읽기 전용 DTO에 적합합니다.
  • 추가적인 클래스를 정의하지 않아도 되어 빠르게 개발할 수 있습니다.

단점

  • getter만 지원되며, 로직을 포함할 수 없습니다.
  • 구조 변경이나 커스터마이징에 제약이 많습니다.
  • 필드명이 쿼리와 정확히 일치해야 하므로 유연성이 떨어집니다.

Class 기반 DTO

예시

public class UserDto {
    private String name;
    private int age;

    public UserDto(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getter, setter
}
@Query("SELECT new com.example.dto.UserDto(u.name, u.age) FROM User u")
List<UserDto> findUsers();

장점

  • 생성자, 메서드, 유효성 검사 등 자유로운 커스터마이징이 가능합니다.
  • 복잡한 데이터 변환이나 후처리가 필요한 경우에 유용합니다.
  • 일반적인 Java 객체처럼 다룰 수 있어 유연성이 높습니다.

단점

  • new 키워드를 활용한 객체 생성이 필요해 쿼리가 다소 복잡해질 수 있습니다.
  • 생성자 매개변수의 순서와 타입을 정확히 맞춰야 합니다.

어떤 방식을 선택할까?

상황 권장 방식
단순한 조회 쿼리 Interface
계산, 파싱, 후처리 등 로직 필요 Class
DTO에 포맷팅, 유효성 검사 등 추가 작업이 필요한 경우 Class
빠르게 읽기용 결과만 보고 싶을 때 Interface

마무리

결론적으로 JPA에서 DTO를 구현할 때 interface와 class는 각각의 목적에 따라 선택하는 것이 가장 좋습니다. 단순한 조회만 필요할 때는 interface가 효율적이며, 로직이 필요하거나 유연성이 중요한 경우에는 class 방식이 더 적합합니다. 상황에 따라 두 방식을 병행해 사용하는 것도 좋은 전략이 될 수 있습니다.

반응형

'개발 (Development) > Java' 카테고리의 다른 글

[Java] Interface란? 클래스와 다른 점은?  (0) 2025.08.03
[Java] MyBatis와 JPA 속도 비교: 어떤 상황에 어떤 선택이 더 나을까?  (0) 2025.08.03
[Java] MyBatis만 쓰던 내가 JPA를 처음 접했을 때 이해한 구조 정리  (0) 2025.08.03
[Java] Spring Boot 프로젝트에서 MyBatis와 JPA를 함께 사용하는 방법과 오류 해결 과정  (0) 2025.08.03
[Java] Spring Boot 2.x + Java 11 환경에서 JPA Native Query와 DTO 매핑 문제 해결 기록  (4) 2025.08.03
'개발 (Development)/Java' 카테고리의 다른 글
  • [Java] Interface란? 클래스와 다른 점은?
  • [Java] MyBatis와 JPA 속도 비교: 어떤 상황에 어떤 선택이 더 나을까?
  • [Java] MyBatis만 쓰던 내가 JPA를 처음 접했을 때 이해한 구조 정리
  • [Java] Spring Boot 프로젝트에서 MyBatis와 JPA를 함께 사용하는 방법과 오류 해결 과정
LoopThinker
LoopThinker
모르는 것을 알아가고, 아는 것을 더 깊게 파고드는 공간
  • LoopThinker
    CodeMemoir
    LoopThinker
  • 전체
    오늘
    어제
    • 분류 전체보기 (216)
      • 개발 (Development) (151)
        • Algorithm (1)
        • Angular (1)
        • AWS (4)
        • DeepSeek (2)
        • Docker (7)
        • Git (3)
        • Java (30)
        • JavaScript (4)
        • Kafka (5)
        • Kubernetes (4)
        • Linux (6)
        • PostgreSQL (37)
        • Python (26)
        • React (3)
        • TypeScript (3)
        • Vue.js (5)
        • General (10)
      • 데이터 분석 (Data Analysis) (1)
      • 알고리즘 문제 풀이 (Problem Solving.. (27)
      • 자격증 (Certifications) (24)
        • ADsP (14)
        • 정보처리기사 (4)
        • Linux Master (5)
        • SQLD (1)
      • 기술 동향 (Tech Trends) (10)
      • 기타 (Others) (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    백준온라인저지
    springboot
    Vue.js
    JPA
    pandas
    AWS
    Linux master
    백준
    typescript
    ADsP
    백준자바
    자바
    Linux
    javascript
    python
    DevOps
    timescaledb
    리눅스 마스터 2급 2차
    java
    Kafka
    리눅스 마스터 2급
    JSON
    MyBatis
    Kubernetes
    deepseek
    데이터분석
    docker
    오답노트
    PostgreSQL
    백준알고리즘
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
LoopThinker
[Java] JPA에서 DTO는 Interface로 구현할까? Class로 구현할까?
상단으로

티스토리툴바