SpringBoot 환경에서의 JPA

StrayCat·2026년 2월 15일

Spring Boot에서 JPA를 사용할 때 알아야 할 핵심 개념들을 정리합니다. EntityManager 자동 구성, @Transactional의 동작 원리, 영속성 컨텍스트와 트랜잭션의 생명주기, 그리고 트랜잭션 전파까지 다룹니다.


1. Spring Boot JPA 설정

의존성 추가

// build.gradle
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

Hibernate 설정 (application.properties)

spring.jpa.hibernate.ddl-auto=update

spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true

ddl-auto 옵션 정리

옵션설명
create기존 테이블 DROP 후 다시 CREATE
create-dropcreate와 동일하나, 애플리케이션 종료 시 테이블 DROP
update변경된 부분만 반영
validateEntity와 테이블 매핑이 정상인지 확인만 수행
none아무것도 하지 않음

‼️주의 : 운영 환경에서는 validate 또는 none을 사용하는 것이 안전. create, update 등은 개발 환경에서만 사용할 것


2. Entity 클래스 작성

@Entity
@Getter @Setter
@Table(name = "memo")
@NoArgsConstructor
public class Memo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "username", nullable = false)
    private String username;

    @Column(name = "contents", nullable = false, length = 500)
    private String contents;
}

핵심 annotation :

  • @Entity -> JPA가 관리하는 엔티티 클래스로 지정
  • @Table -> 매핑할 DB 테이블명 지정
  • @Id + @GenaratedValue -> 기본 키 및 자동 생성 전략 설정
  • @Column -> 컬럼 매핑 및 제약조건 설정

3. SpringBoot의 EntityManager 자동 구성

  • 순수 JPA에서는 EntityManagerFactoryEntityManager를 직접 생성해야 했지만, SpringBoot에서는 자동 생성
  • application.properties에 DB 정보를 설정하면, 이를 기반으로 EntityManagerFactory가 자동 생성되고, @PersistenceContext를 통해 EntityManager를 주입받아 사용 가능
@PersistenceContext
EntityManager em;

4. @Transactional - 트랜잭션 관리

핵심 동작 원리

@Transactional을 클래스나 메서드에 붙이면, 해당 범위의 모든 DB연산이 하나의 트랜잭션으로 묶입니다.

  • 메서드가 정상 완료 -> commit
  • 예외 발생시 -> rollback

트랜잭션이 없으면 어떻게 되는가?

// ❌ @Transactional 없음 → 실패!
@Test
void test2() {
    Memo memo = new Memo();
    memo.setUsername("Tom");
    memo.setContents("테스트");
    em.persist(memo); // 영속성 컨텍스트가 유지되지 않아 오류 발생
}
  • JPA에서 데이터를 저장·수정·삭제하려면 트랜잭션이 반드시 필요함
  • 조회는 필수는 아니지만, 영속성 컨텍스트의 기능 (지연 로딩 등)을 활용하려면 트랜잭션 환경을 필요로 할 수 있음

readOnly 옵션

@Transactional(readOnly = true)
  • 읽기 전용 트랜잭션으로 최적화 수행
  • 데이터 수정 시도 시 예외 발생
  • 조회만 하는 메서드에 적용시 성능상 이점 있음

클래스 레벨 vs 메서드 레벨

@Transactional(readOnly = true)  // 클래스 전체: 읽기 전용
public class SimpleJpaRepository<T, ID> {

    @Transactional  // 이 메서드만 readOnly = false로 덮어쓰기
    public <S extends T> S save(S entity) { ... }
}

메서드의 선언된 @Transactional이 클래스 레벨의 설정을 오버라이드 할 수 있음


5. 영속성 컨텍스트와 트랜잭션의 생명주기

스프링 컨테이너 환경에서는 영속성 컨텍스트와 트랜잭션의 생명주기가 일치합니다.

이것이 의미하는 바는 다음과 같습니다 :

  • 트랜잭션이 시작되면 -> 영속성 컨텍스트가 생성됨
  • 트랜잭션이 유지되는 동안 -> 영속성 컨텍스트의 기능 (1차 캐시, 변경 감지 등) 사용 가능
  • 트랜잭션이 종료되면 -> 영속성 컨텍스트도 함께 종료

앞선 test2()가 실패한 이유도 이와 같습니다. 트랜잭션이 없으므로 영속성 컨텍스트가 유지되지 않은 것입니다.


6. 트랜잭션 전파 (Transaction Propagation)

개념

Service -> Repository 호출 시, 트랜잭션이 어떻게 이어지는 걸까요? Spring은 트랜잭션 전파 기능을 통해 이를 제어합니다.

기본 옵션 : REQUIRED

@Transactional의 기본 전파 옵션은 REQUIRED입니다.

  • 부모 메서드에 트랜잭션이 있으면 -> 자식 메서드가 부모 트랜잭션에 합류
  • 부모 메서드에 트랜잭션이 없으면 -> 자식 메서드가 자체적인 트랜잭션 생성

동작 확인

// 부모 메서드 (테스트)
@Test
@Transactional
@Rollback(value = false)
void test3() {
    memoRepository.createMemo(em);
    System.out.println("테스트 test3 메서드 종료");
}

// 자식 메서드 (Repository)
@Transactional
public Memo createMemo(EntityManager em) {
    Memo memo = em.find(Memo.class, 1);
    memo.setUsername("홍길동");
    memo.setContents("@Transactional 전파 테스트 중!");
    System.out.println("createMemo 메서드 종료");
    return memo;
}

**부모 트랜잭션이 있는 경우:**

createMemo 메서드 종료
테스트 test3 메서드 종료
→ UPDATE 실행 (부모 메서드 종료 시점에 커밋)


**부모 트랜잭션이 없는 경우:**

createMemo 메서드 종료
→ UPDATE 실행 (자식 메서드 종료 시점에 자체 커밋)
테스트 test3 메서드 종료

7. 정리 및 요약

개념핵심 포인트
Spring Boot JPA 설정starter-data-jpa의존성 + application.properties 설정으로 자동 구성
EntityManager@PersistenceContext로 자동 주입, 직접 생성 불필요
@TransactionalCUD작업에 필수, 조회는 readOnly = true 권장
생명주기트랜잭션 = 영속성 컨텍스트 생명주기 (스프링 컨테이너 환경)
트랜잭션 전파기본 REQUIRED - 부모 트랜잭션이 있으면 합류, 없으면 자체 생성
profile
알면 좋은 것보단 잊어버리기 싫은 것들을 기록합니다.

0개의 댓글