본문 바로가기
Tech Stack/Database

🍃JPA 기초 및 개발 환경 구축

by 박수무당벌레 2026. 7. 9.

1. DB 접근 기술 개념 정리

  • JDBC API: 자바 진영의 Low-Level CRUD API로, DB 엔진(MySQL, H2 등)에서 제공하는 구현체(드라이버)를 통해 통신함. (자바-DB간 연결 지원)
  • JPQL: JPA에서 객체지향 쿼리를 작성하기 위해 정의한 쿼리 언어.
  • QueryDSL: JPQL을 자바 코드로 안전하게 작성할 수 있도록 돕는 JPQL 빌더.
  • Spring Data JPA: JpaRepository 인터페이스를 제공하여 자바 코드만으로 CRUD 작업을 쉽게 수행할 수 있도록 지원.

역할 구분

  • 🔌 애플리케이션-DB 연결점: 자바 앱과 DB 사이를 연결하는 표준 인터페이스.
  • 🗃️ 데이터 저장 계층 (Data Access Layer): 데이터를 영속화하고 관리하는 DB 영역.

2. Maven 프로젝트 설정 (pom.xml)

  • Spring Boot 개발 환경 설정은 여기서. (본문은 Spring Boot 없이 순수 Java 환경(Maven)에서의 개발 환경을 설명한다)
  • 💡 JPA 표준 인터페이스 구현체인 Hibernate Core 데이터베이스 드라이버를 의존성으로 추가한다.
    • mysql-connector-j: MySQL 데이터베이스 드라이버 구현체 제공.
    • h2: 학습 및 테스트용 DB (인메모리 모드 또는 파일/디스크 영속성 모드 지원).
    • 자세한 의존성 설정 및 설명은 여기서.
  • 💡 참고: hibernate-core를 추가하면 JPA 표준 규격인 jakarta.persistence 패키지가 내장(의존성)되어 함께 로드된다.
더보기

ℹ️ JPA 사용 시 멀티 모듈로 구성하는 이유

  • EntityManagerFactory 고유성: JPA는 설정 정보 및 EntityManagerFactory 단위를 다루기 때문에 단순 패키지 분리만으로는 한계가 있어 독립적인 모듈(멀티 프로젝트) 구조로 구성한다.
  • 하위 모듈 등록: 부모 프로젝트의 pom.xml 내 <modules> 태그에 자식 프로젝트를 등록하고, 자식 pom.xml에는 <parent> 설정을 추가 (+ 부모 프로젝트에 Import)

3. JPA 환경 설정 (persistence.xml)

  • src/main/resources/META-INF/persistence.xml 경로에 위치하며, JPA의 핵심 설정을 다룬다.
  • 💡 데이터베이스 연결 정보(JDBC URL, ID/PW)와 JPA 표준 인터페이스 구현체인 Hibernate 속성을 정의한다.
    • hibernate.show_sql: JPA가 생성한 SQL 실행 문장을 콘솔에 보여주는 옵션.
    • H2 TRACE 기능: 네트워크 레벨에서 DB 드라이버 내부의 모든 통신 과정과 상세 동작을 추적하는 기능 (디버깅용).
    • 자세한 환경 설정 및 세부 옵션 설명은 여기서.
  • 💡 참고: 애플리케이션 실행 시 EntityManagerFactory가 생성되는 시점에 이 persistence.xml을 읽어 들여 설정을 초기화한다.

3. 엔티티 클래스 작성 (예시)

데이터베이스의 테이블과 1:1로 매핑되는 객체 클래스.

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import lombok.*;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Entity // JPA가 관리하는 객체임을 지정 (필수)
public class Student {

    @Id // PK(Primary Key) 매핑 (필수)
    private Long id;
    private String name;

    // Getter, Setter는 롬복이 생성
}

4. 메인 애플리케이션 실행 및 트랜잭션 처리

JPA의 모든 데이터 변경 작업은 반드시 트랜잭션 안에서 수행되어야 한다.

  • DriverManager.getConnection(...):
    • DB와 TCP 연결을 맺고 Connection 인터페이스의 구현체를 반환 (null이 아니면 TCP 연결 성공).

요약 및 핵심 동작 정리

  1. EntityManagerFactory vs EntityManager
    • EntityManagerFactory: 애플리케이션 전체에서 하나만 생성해서 공유한다. (persistence.xml 기반)
    • EntityManager: 쓰레드 간 공유 금지 (요청 시마다 만들고, 사용 후 반드시 폐기).
  2. em.persist() 와 커밋 과정
    • em.persist(entity) 호출 시 즉각 DB로 SQL을 쏘는 것이 아니라, 내부 영속성 컨텍스트(쓰기 지연 버퍼)에 저장해 둔다.
    • tx.commit()이 호출되는 순간 실제 INSERT 쿼리가 DB로 전송 및 반영된다.
  3. Spring Boot와의 차이점
    • 순수 Java 환경에서는 EntityManagerFactory 생성, EntityManager 생성 및 종료, EntityTransaction의 begin/commit/rollback을 개발자가 직접 제어해야 한다.
    • Spring Boot 환경에서는 트랜잭션 관리 및 EntityManager 생성을 프레임워크가 자동으로 주입 및 처리해 줌.
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.EntityTransaction;
import jakarta.persistence.Persistence;

public class Main {
    public static void main(String[] args) {
        // 1. EntityManagerFactory 생성 (persistence.xml의 "hello" 식별자 사용)
        // ➡️ 팩토리가 생성되는 시점에 @Entity 클래스를 감지하고 ddl.auto 설정에 맞춰 DDL 실행
        EntityManagerFactory ef = Persistence.createEntityManagerFactory("hello");

        // 2. 고객의 요청이 올 때마다 EntityManager 생성
        EntityManager em = ef.createEntityManager();

        // 3. 트랜잭션 획득 및 시작
        EntityTransaction et = em.getTransaction();

        try {
            et.begin(); // 트랜잭션 시작

            // 엔티티 객체 생성 및 값 추가
            Student student = new Student();
            student.setId(1L);
            student.setName("Hong-gil-dong");

            // 영속성 컨텍스트(1차 캐시)에 저장 
            // ➡️ 이 시점엔 DB로 INSERT 쿼리가 바로 나가지 않고 메모리에 쿼리를 준비함
            em.persist(student);

            // 커밋 시점에 실제 INSERT SQL 쿼리가 실행됨
            et.commit(); 
        } catch (Exception e) {
            et.rollback(); // 예외 발생 시 트랜잭션 롤백
            e.printStackTrace();
        } finally {
            em.close(); // 자원 반납
        }

        ef.close(); // 애플리케이션 종료 시 팩토리 닫기
    }
}