영속성 컨텍스트(Persistence Context) : 엔티티(Entity)를 영속적으로 저장하는 환경
JPA 영속성 컨텍스트 : 엔티티의 생명주기를 관리하고, 애플리케이션과 데이터베이스 사이에서 수많은 최적화 작업을 해주는 논리적인 공간(메모리 공간)
→ JPA는 이 공간에서 엔티티를 관리하다가, 트랜잭션이 끝나면 최종 결과물만 DB에 반영
영속성 컨텍스트를 사용하는 이유
1차 캐시와 동일성 보장
엔티티를 1차 캐시(임시 저장소)에 저장 → 이후에 동일한 id를 조회하면 DB를 조회하지 않고 캐시의 엔티티를 반환
→ 같은 트랜잭션에서 같은 id로 조회한 엔티티는 항상 동일한 메모리 주소의 인스턴스임을 보장
변경 감지(Dirty Checking) : 트랜잭션이 커밋되기 전 1차 캐시의 모든 엔티티를 최초 상태와 비교하고, 두 상태가 다르다면 자동으로 update SQL을 생성
쓰기 지연(Transactional Write-Behind) : SQL을 모아뒀다가 트랜잭션이 커밋되면 모든 SQL을 한 번에 DB로 보냄 → 네트워크 비용 감소, 성능 최적화
<aside> 💡
Flush : 영속성 컨텍스트의 변경 내용을 DB에 동기화하는 것 (컨텍스트의 상태와 DB 상태를 맞추는 작업)
→ 트랜잭션을 커밋하는 것은 아님! 여전히 한 트랜잭션으로 관리되기 때문에 트랜잭션 롤백 시 Flush한 데이터도 롤백됨.
</aside>
EntityManager : 애플리케이션과 데이터베이스 사이에서 엔티티 객체를 관리하고 실제 데이터베이스 작업을 수행하는 객체(모든 엔티티를 관리)
→ JPA Repository 내부에서 EntityManager를 사용하고 있음!

Persistence Unit(설계도) : JPA 설정 정보의 단위
→ 데이터베이스 연결 정보(URL, 사용자, 비밀번호), 어떤 엔티티 클래스를 관리할 것인지, JPA 구현체의 특정 설정 등을 포함하는 설정 파일
EntityManagerFactory(공장) : 설정 정보를 바탕으로 EntityManager를 생성하는 팩토리
→ 애플리케이션에서 단 하나만 생성되어 공유됨(최초 생성에 리소스가 많이 사용되기 때문)
→ 여러 쓰레드가 동시에 접근해도 안전함(Thread-Safe)
EntityManager(작업자) : 실제 데이터베이스 작업을 처리하는 작업자
→ 엔티티를 저장, 수정, 삭제, 조회하는 역할 수행 (내부적으로 SQL 실행)
@Transactional : 메서드를 트랜잭션 안에서 실행
→ propagation 옵션을 통해 트랜잭션 안에 트랜잭션을 생성하는 등의 전략을 설정할 수 있음
required(default) : 부모 트랜잭션이 있으면 그 트랜잭션에 참여, 없으면 새로운 트랜잭션 생성
requires_new : 무조건 새로운 트랜잭션을 생성
→ 기능의 성공 여부와 상관없이 반드시 기록되어야 하는 기능 (ex: 사용자의 행동 로그, 에러 로그, 통계 데이터)
nested : 부모 트랜잭션이 있으면 중첩된 트랜잭션 생성, 없으면 새 트랜잭션 생성
→ 하나의 큰 작업 중 실패할 가능성이 있는 부분을 분리할 때 유용 (ex: 여러 개 주문에 각각 쿠폰 처리)
<aside> 💡
requires_new vs. nested
requiires_new : 부모와 별개의 트랜잭션이기에 부모가 롤백되어도 자식은 커밋될 수 있음
nested : 부모 트랜잭션에 종속적이기에 자식만 롤백은 가능, 부모가 롤백되면 자식도 무조건 롤백
</aside>
supports : 부모 트랜잭션이 있으면 참여, 없으면 트랜잭션 없이 실행
→ 읽기 전용 메서드 처럼 트랜잭션이 있든 없든 로직 수행에 문제가 없고, 굳이 트랜잭션을 생성할 필요가 없을 때 적합(ex: 목록 조회)