[JPA] JPA vs MySQL vs JDBC vs JPQL vs QueryDSL

2025. 3. 11. 09:01·Spring/JPA
728x90
반응형
SMALL

JPA vs MyBatis vs JDBC vs QueryDSL vs JPQL 비교 및 분석

 

Spring 환경에서 데이터베이스를 다룰 때 사용되는 대표적인 기술로 JPA, MyBatis, JDBC, QueryDSL, JPQL 등이 있다.

각 기술은 특징, 장점, 단점, 사용 방식이 다르며 프로젝트 요구 사항에 따라 적절한 기술을 선택해야 한다.

 


1. JDBC (Java Database Connectivity)

 

특징

• Java의 표준 데이터베이스 API.

• SQL을 직접 작성하여 데이터베이스와 통신.

• Connection, Statement, ResultSet 등을 사용하여 데이터 처리.

 

장점

 

  • 직접적인 SQL 사용 → 데이터베이스의 모든 기능 활용 가능.
  • 가장 빠른 성능 → 별도의 프레임워크 없이 최소한의 오버헤드로 실행.
  • 단순한 프로젝트에서 유용 → JPA, MyBatis보다 가볍고 간단한 경우 적합.

 

단점

 

반복적인 코드가 많음 → Connection, Statement, ResultSet을 직접 다뤄야 함.

SQL을 직접 관리해야 하므로 유지보수가 어려움.

객체-관계 매핑(ORM) 기능이 없음 → 엔티티 매핑을 직접 구현해야 함.

 

예제 코드

Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/db", "user", "password");
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM product WHERE id = ?");
pstmt.setLong(1, 1);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
    System.out.println(rs.getString("name"));
}
rs.close();
pstmt.close();
conn.close();

 

 


2. MyBatis

 

특징

SQL을 XML 또는 어노테이션 기반으로 관리.

SQL을 직접 작성하지만, 객체 매핑을 지원.

JDBC보다 코드가 간결하며 자동 매핑 기능을 제공.

 

장점

 

  • SQL을 직접 컨트롤 가능 → 복잡한 쿼리를 최적화할 수 있음.
  • 객체 매핑 지원 → SQL 결과를 객체로 변환 가능.
  • 자동 매핑 기능 → resultMap을 활용하여 엔티티 매핑 가능.
  • JDBC보다 코드가 간결하고 유지보수가 쉬움.

 

단점

 

  • SQL을 직접 관리해야 함 → 유지보수 부담 증가.
  • 객체 지향적인 설계가 어려움 → SQL 중심 설계로 인해 객체 모델과 분리가 필요.
  • 영속성 컨텍스트가 없음 → JPA의 변경 감지 기능을 사용할 수 없음.

 

예제 코드

<select id="findById" parameterType="long" resultType="Product">
    SELECT * FROM product WHERE id = #{id}
</select>
Product product = productMapper.findById(1L);

 

 


3. JPA (Java Persistence API)

 

특징

• ORM(Object-Relational Mapping) 기반 기술.

• 객체 중심으로 데이터를 관리하고 자동으로 SQL을 생성.

• 트랜잭션과 영속성 컨텍스트를 통해 데이터 변경 사항을 자동 반영.

 

 

장점

 

  • 객체 지향적인 개발 가능 → 엔티티 중심 설계가 가능.
  •  SQL 작성 없이 데이터 조작 가능 → 자동으로 SQL 생성.
  • 트랜잭션 및 영속성 컨텍스트 관리 → Dirty Checking, 1차 캐시, Lazy Loading 지원.
  • Spring Data JPA와 결합하면 CRUD가 매우 간단함.
  • DB 벤더 종속성이 낮음 → JPQL, QueryDSL 등을 활용하면 특정 DB에 종속되지 않음.
  • 내부적으로 PreparedStatement를 활용하기 때문에 바인딩 처리하여 SQLInjection 방지가능

 

단점

 

초기 학습 비용이 높음 → Hibernate의 내부 동작을 이해해야 함.

SQL을 직접 컨트롤하기 어려움 → 복잡한 쿼리는 QueryDSL과 함께 사용해야 함.

단순 조회 성능이 MyBatis보다 느릴 수 있음 → 최적화가 필요.

 

예제 코드

@Entity
public class Product {
    @Id @GeneratedValue
    private Long id;
    private String name;
    private int price;
}
@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findByName(String name);
}

 


4. JPQL (Java Persistence Query Language)

 

특징

• JPA에서 제공하는 SQL과 유사한 쿼리 언어.

• 테이블이 아니라 엔티티 객체를 대상으로 쿼리를 실행.

• EntityManager.createQuery() 또는 @Query를 사용하여 실행.

 

장점

  • SQL과 유사하여 배우기 쉬움.
  • 데이터베이스 독립적 → 특정 DB에 종속되지 않음.
  • 자동 변환 기능 제공 → 결과를 엔티티 객체로 매핑해줌.

 

단점

  • 컴파일 시점에 문법 오류를 확인할 수 없음.
  • 동적 쿼리 작성이 불편함 → QueryDSL보다 사용성이 떨어짐.
  • 동적 쿼리 사용시 오류 발생 가능성이 높고 SQL Injection에 취약하다. 사용자가 입력한 데이터가 SQL문에 그대로 포함되기 때문이다.

 

예제 코드

public List<Product> findProducts(String name, Integer minPrice, Integer maxPrice) {
    String jpql = "SELECT p FROM Product p WHERE 1=1";

    if (name != null) {
        jpql += " AND p.name = :name";
    }
    if (minPrice != null) {
        jpql += " AND p.price >= :minPrice";
    }
    if (maxPrice != null) {
        jpql += " AND p.price <= :maxPrice";
    }

    TypedQuery<Product> query = entityManager.createQuery(jpql, Product.class);

    if (name != null) {
        query.setParameter("name", name);
    }
    if (minPrice != null) {
        query.setParameter("minPrice", minPrice);
    }
    if (maxPrice != null) {
        query.setParameter("maxPrice", maxPrice);
    }

    return query.getResultList();
}

 

 


5. QueryDSL

 

특징

• JPQL을 타입 안전하게 사용할 수 있도록 지원.

• QClass를 활용하여 SQL-like한 코드로 쿼리 작성 가능.

• JPAQueryFactory를 사용하여 쿼리를 실행.

 

장점

 

 컴파일 시점에 문법 오류를 체크할 수 있음 (타입 안전).

 가독성이 높고 유지보수가 쉬움.

 동적 쿼리를 편리하게 작성 가능.

 페이징, 정렬 등 JPA와 결합하여 사용 가능.

내부적으로 PreparedStatement를 활용하기 때문에 바인딩 처리하여 SQLInjection 방지가능

 

단점

 

빌드 시 추가적인 코드 생성 과정(QClass)이 필요함.

JPQL보다 상대적으로 학습 비용이 높음.

 

예제 코드

QProduct p = QProduct.product;

List<Product> products = queryFactory
    .selectFrom(p)
    .where(p.name.eq("스마트폰"))
    .fetch();

 

 


6. 비교 요약 표

 

비교 항목 JDBC MySQL JPA JPQL QueryDSL
쿼리 작성 방식 SQL 직접 작성 SQL(XML, 어노테이션) ORM 기반 (SQL 자동 생성) SQL 유사 코드 기반 DSL
타입 안전성 ❌ ❌ ✅ ❌ ✅
객체 매핑 ❌ 수동 매핑 필요 ✅ 자동 매핑 지원 ✅ 엔티티 매핑 ✅ 엔티티 매핑 ✅ 엔티티 매핑
트랜잭션 관리 직접 처리 직접 처리 자동 처리 자동 처리 자동 처리
동적 쿼리 작성 불편 보통 어려움 어려움 편리
성능 가장 빠름 빠름 최적화 필요 최적화 필요 최적화 필요
복잡한 쿼리 지원 가능 매우 강력 보통 (QueryDSL 필요) 가능하지만 불편 매우 강력
학습 난이도 쉬움 중간 높음 중간 중간

 

 


7. 결론 및 선택 기준

• JDBC → 가장 빠르지만 유지보수가 어려움. SQL을 직접 컨트롤해야 하는 경우 사용.

• MyBatis → SQL을 직접 사용하면서도 자동 매핑을 제공하여 유지보수가 용이함. 복잡한 쿼리가 많은 프로젝트에 적합.

• JPA → 객체 중심으로 데이터를 다룰 수 있으며, Spring Data JPA와 함께 사용하면 매우 편리함. 객체 지향적인 개발을 원한다면 선택.

• JPQL → SQL과 유사하지만 객체 지향적 접근이 가능. 기본적인 쿼리에 적합하지만 동적 쿼리는 QueryDSL이 더 좋음.

• QueryDSL → 타입 안전하며 동적 쿼리가 필요한 경우 가장 적합한 선택.

 

JPA를 사용하면 SQL을 직접 작성하지 않아도 되고, 유지보수성이 뛰어나지만 QueryDSL과 함께 사용하면 더욱 강력한 기능을 제공할 수 있다.

728x90
반응형
SMALL

'Spring > JPA' 카테고리의 다른 글

[JPA, Kafka] @Transactional과 Kafka 메세지 전송 시점  (0) 2025.03.09
[JPA] @Transaction을 붙이지 않았을 때 생기는 문제, JPA Proxy, LazyLoading과 EagerLoading N+1 문제  (0) 2025.02.22
[JPA] Soft Delete 개발 방법(Hard Delete과의 차이)  (0) 2025.02.17
[개념 정리]Spring Boot에서 JPA의 Soft Delete와 Cascade 연관관계  (1) 2024.12.09
save the transient instance before flushing  (1) 2024.11.20
'Spring/JPA' 카테고리의 다른 글
  • [JPA, Kafka] @Transactional과 Kafka 메세지 전송 시점
  • [JPA] @Transaction을 붙이지 않았을 때 생기는 문제, JPA Proxy, LazyLoading과 EagerLoading N+1 문제
  • [JPA] Soft Delete 개발 방법(Hard Delete과의 차이)
  • [개념 정리]Spring Boot에서 JPA의 Soft Delete와 Cascade 연관관계
공부하고 기억하는 공간
공부하고 기억하는 공간
IT 비전공자로 시작하여 훌륭한 개발자가 되기 위해 공부하고 있는 공간입니다. 틀린 내용이나 부족한 부분이 있으면 댓글로 알려주세요 바로 수정하겠습니다.
    250x250
  • 공부하고 기억하는 공간
    IT - railroad
    공부하고 기억하는 공간
  • 전체
    오늘
    어제
    • 분류 전체보기 (315)
      • 면접 준비 (36)
        • OS (6)
        • Spring Security (0)
        • Java (2)
        • DB (9)
        • Network (3)
      • ElasticSearch (2)
      • Kafka (4)
      • Spring (22)
        • Spring Cloud (7)
        • Security6 (5)
        • JPA (12)
        • 프로젝트 리팩토링 회고록 (4)
        • Logging (8)
        • Batch (2)
      • Redis (17)
        • Redis 개념 (8)
        • Redis 채팅 (5)
        • Redis 읽기쓰기 전략 (1)
      • AWS (11)
      • 리눅스 (29)
        • 리눅스 마스터 2급 (5)
        • 네트워크(기초) (7)
        • 리눅스의 이해 (6)
        • 리눅스의 설치 (2)
        • 리눅스 운영 및 관리 (6)
      • JAVA-기초 (16)
        • JAVA기본 (11)
        • Design Pattern (5)
      • JSP (27)
        • JSP 기본 개념 (10)
        • JSP (1)
      • SQL (1)
      • TIL (36)
      • 문제 풀이 (2)
        • Programmers (9)
        • 백준 문제풀이 (28)
      • JavaScript (10)
      • HTML (17)
      • Ngrinder (1)
        • Ngrinder 문서 정리 (1)
  • 블로그 메뉴

    • 링크

    • 공지사항

    • 인기 글

    • 태그

      Spring Data Redis
      스프링프레임워크
      리눅스
      자바 면접
      자바
      백준
      자바스크립트
      리눅스마스터2급정리
      spring redis
      자바기초
      jsp기초
      JSP
      자바 면접질문
      레디스
      프로그래머스
      자바 반복문
      jsp request
      java
      리눅스마스터2급
      HTML
      CSS
      자바 알고리즘
      Spring
      Til
      redis 채팅
      redis
      springsecurity
      JS
      Springframework
      JavaScript
    • 최근 댓글

    • 최근 글

    • hELLO· Designed By정상우.v4.10.3
    공부하고 기억하는 공간
    [JPA] JPA vs MySQL vs JDBC vs JPQL vs QueryDSL
    상단으로

    티스토리툴바