스프링부트에서 데이터 관리를 위해 공부하면 영속성이란 단어를 들을 수 있다.
과연 영속성이란 무엇이며 어떤 역할을 하는지 알아봤다.
우선 자바에서 영속성이란 "프로그램이 종료되더라도 데이터가 유지되는 특성"을 의미한다.
일반적으로 데이터베이스나 파일 시스템에 데이터를 저장하고,
필요할 때 이를 다시 불러오는 방식으로 구현한다 .
영속성과 관련된 개념
(1) 영속 계층 (Persistence Layer)
- 애플리케이션의 데이터 저장과 관리를 담당하는 계층
- 데이터베이스, 파일, 클라우드 스토리지 등에 데이터를 저장
(2) 영속 객체 (Persistent Object)
- 데이터베이스에 저장되거나 저장될 수 있는 객체
- 일반적으로 Entity 클래스 또는 VO(Value Object) 형태
(3) 영속 컨텍스트 (Persistence Context)
- 엔티티 객체를 관리하는 공간
- JPA에서는 EntityManager가 영속 컨텍스트를 관리
자바에서 영속성을 관리하는 방법
(1) JDBC (Java Database Connectivity)
- 가장 기본적인 데이터베이스 연결 방식
- Connection, PreparedStatement 등을 사용하여 직접 SQL을 실행
- 낮은 추상화 수준 → 유지보수가 어려움
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password");
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users");
ResultSet rs = stmt.executeQuery();
// JDBC는 직접적인 쿼리문을 작성하여 전달
(2) JPA (Java Persistence API)
- 객체와 관계형 데이터베이스를 매핑하는 ORM(Object-Relational Mapping) 기술
- EntityManager를 통해 객체를 영속화
- SQL을 직접 작성할 필요 없이 객체 중심으로 데이터 조작 가능
EntityManager em = entityManagerFactory.createEntityManager();
em.getTransaction().begin();
User user = new User();
user.setName("홍길동");
em.persist(user); // 영속화
em.getTransaction().commit();
// EntityManager를 사용하여 영속성 관리
(3) Hibernate
- JPA의 구현체 중 하나로, 가장 널리 사용됨
- SessionFactory를 이용해 영속성 관리
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(new User("홍길동"));
session.getTransaction().commit();
(4) Spring Data JPA
- JPA를 더욱 쉽게 사용할 수 있도록 지원하는 Spring 프레임워크의 모듈
- JpaRepository 인터페이스를 상속받으면 기본적인 CRUD 기능을 자동 제공
// UserRepository.java
public interface UserRepository extends JpaRepository<User, Long> {
}
// 영속성 구현
@Autowired
private UserRepository userRepository;
User user = new User();
user.setName("홍길동");
userRepository.save(user);
JPA와 Spring Data JPA의 주요 차이?
일반적인 JPA는 EntityManager를 생성하고 트랜잭션을 관리 해줘야 한다.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("my-persistence-unit");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
User user = new User();
user.setName("홍길동");
em.persist(user);
em.getTransaction().commit();
em.close();
하지만 Spring Data JPA는 JpaRepository를 상속받는 인터페이스만 만들면
자동으로 CRUD 메소드를 제공한다.
// JpaRepository가 상속받는 CrudRepository 인터페이스
public interface CrudRepository<T, ID> extends Repository<T, ID> {
<S extends T> S save(S entity);
<S extends T> Iterable<S> saveAll(Iterable<S> entities);
Optional<T> findById(ID id);
boolean existsById(ID id);
Iterable<T> findAll();
Iterable<T> findAllById(Iterable<ID> ids);
long count();
void deleteById(ID id);
void delete(T entity);
void deleteAllById(Iterable<? extends ID> ids);
void deleteAll(Iterable<? extends T> entities);
void deleteAll();
}
// SimpleRepository.class
@Transactional
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null");
if (this.entityInformation.isNew(entity)) {
this.em.persist(entity);
return entity;
} else {
return (S)this.em.merge(entity);
}
}
SimpleRepository파일을 확인해보면 테이블에 데이터의 변화가 생기는 메소드의 경우
@Transactional이 같이 존재하는 것을 확인할 수 있다.
여기서 Transactional은 아래와 같이 동작한다.
1️⃣ 트랜잭션 시작
2️⃣ SQL 실행 (INSERT, UPDATE, DELETE 등)
3️⃣ 문제가 없으면 COMMIT (확정)
4️⃣ 문제가 발생하면 ROLLBACK (되돌리기)
트랜잭션이 중요한 이유
✅ 데이터 무결성 보장: 여러 작업을 하나의 단위로 처리하여 데이터 손상을 방지
✅ 예외 발생 시 자동 복구: 오류 발생 시 롤백하여 데이터 정합성 유지
✅ 동시성 문제 해결: 트랜잭션 격리 수준을 조절하여 동시 실행 문제 해결
영속성의 주요 특징
영속 상태 | 엔티티가 EntityManager에 의해 관리됨 |
준영속 상태 | detach()를 호출하면 관리에서 벗어남 |
삭제 상태 | remove()를 호출하면 삭제됨 |
트랜잭션 관리 | 영속성 관리는 보통 트랜잭션과 함께 사용됨 |
영속성 사용 시 주의점
✅ 트랜잭션을 꼭 사용해야 함: 데이터 변경 시 트랜잭션이 없으면 변경 사항이 반영되지 않을 수 있음
✅ 지연 로딩(Lazy Loading)과 즉시 로딩(Eager Loading) 이해 필요: 성능 최적화를 위해 전략을 적절히 선택해야 함
✅ 캐시 활용: JPA는 1차 캐시(영속 컨텍스트)를 제공하므로 같은 객체를 여러 번 조회해도 쿼리가 발생하지 않음
'Java > SpringBoot' 카테고리의 다른 글
Security Filter Chain (0) | 2025.01.31 |
---|---|
자바의 Filter에 대해서 (0) | 2025.01.31 |
인증과 인가 (0) | 2025.01.30 |
JWT 로그인 테스트-4 (0) | 2025.01.22 |
JWT 로그인 테스트-3 (0) | 2025.01.21 |