멋쟁이사자처럼 13기/정기 세션

[멋사/Mac OS] 4주차 정기 세션 (Part 1. JPA)

개발자 지망생 리네 2025. 6. 17. 23:42

1. JPA

(1) JPA란?

- JAVA에서 ORM기술을 제공하는 표준 인터페이스

- ORM: 객체로 연결, 객체와 테이블을 자동으로 매핑시켜 RDB 테이블을 객체지향적으로 사용할 수 있도록 해줌

- 어플리케이션과 데이터베이스 연결 시 SQL 언어가 아닌 어플리케이션 개발 언어로 데이터베이스를 접근할 수 있게 함

<특징>

장점 단점
DBMS에 대한 종속성 감속 복잡한 쿼리 처리가 어려움
객체지향적 프로그래밍 성능 저하의 위험
생산성 향상 학습 비용 발생
재사용, 유지 보수 용이  

(2) 영속성 컨텍스트

- 영속성: 데이터들이 프로그램이 종료되어도 사라지지 않고 어떤 곳에 저장되는 개념 (캐시같은 건가...?)

- 영속성 컨텍스트: 데이터를 영구 저장하는 환경으로 애플리케이션과 DB 사이 객체를 보관하는 가상의 DB. (논리적 개념)

- EntityManager를 통해 영속성 컨텍스트에 접근이 가능함

- Entity Manager Factory가 Entity Manager를 생성하고, Entity Manager은 prersist(), remove(), find(), merge()같은 메소드가 내장되어 있음. Entity Manager은 이 메소드를 통해 내부의 Persistence Context(영속성 컨텍스트)에 엔티티를 저장하거나 조회함.

 

<메소드>

persist() remove() find() merge() flush() commit()
새로운 엔티티 객체를 영속성 컨텍스트에 저장 영속 상태의 엔티티를 삭제 DB에서 엔티티를 조회하고 1차 캐시에 저장 준영속 상태나 비영속 객체를 다시 영속성 컨텍스트에 복사해서 등록 지금까지 영속성 컨텍스트에 모아놓은 변경내용을 DB에 반영 (SQL 실행) 트랜잭션을 성공적으로 끝내고 DB에 최종 반영
commit하면 DB에 INSERT 쿼리 날아감 commit하면 DELETE 쿼리 날아감 1차 캐시에서 찾고 없으면 DB에서 SELECT 쿼리 날아감.
-> 조회된 엔티티는 1차 캐시에 등록
-> commit 필요 없음
1. DB에서 기존 영속 엔티티를 조회하거나 생성
2. 조회된 영속 객체에 새로운 값들을 복사
3. 새로운 영속 객체를 
트랜잭션이 끝난 것은 아님 내부적으로 자동으로 flush도 실행됨. DB에 모든 내용이 확정적으로 저장됨.
-> 이걸 하지 않으면 실제로는 DB에 아무 일도 생기지 않음
-> 트랜잭션 종료 및 확정

 

<flush랑 commit의 차이점>

구분 flush() commit()
목적 변경 내용을 DB에 쿼리로 미리 반영 트랜잭션을 끝내고 확정 저장
실행 시점 트랜잭션 도중에 수동으로 호출 가능 트랜잭션 마지막에 자동으로 호출됨
영속성 컨텍스트 상태 그대로 유지됨 (엔티티 여전히 살아있음) 트랜잭션 종료됨 (영속성 컨텍스트도 종료)
롤백 가능 가능 (변경 반영됐지만 확정은 아님) 보통 롤백 안 됨 (확정됨)
예시 상황 중간에 강제로 DB에 반영하고 싶을 때 최종적으로 저장 확정할 때

-> commit은 @Transactional이 붙은 메소드가 종료되면 트랜잭션이 끝났다고 판단하고 실행됨.

 

<persist와 merge의 차이점>

JPA 메소드 HTTP 메소드 비유 의미 상세
persist() POST 완전히 새로운 리소스 생성 중복 ID 금지
merge() PUT / PATCH 기존 리소스를 수정하거나 갱신 준영속 객체를 복구해 새 영속 객체로 대체하거나 병합

(3) 엔티티 생명 주기

https://hstory0208.tistory.com/entry/JPA-영속성-컨텍스트란

 

[JPA] 내부 동작 방식 (feat. 영속성 컨텍스트란?)

JPA를 사용하다보면 "영속성 컨텍스트"라는 단어를 많이 보게 된다. 하지만 대충 어떤방식인줄은 알지만, 정확히는 이해하지 못했다. 이번에 JPA에서 가장 중요하고 핵심 개념인 "영속성 컨텍스트

hstory0208.tistory.com

 

- 비영속(new/transient): 영속성 컨텍스트와 전혀 관계가 없는 상태

- 영속(managed): 영속성 컨텍스트에 저장된 상태

- 준영속(detached): 영속성 컨텍스트에 저장되었다가 분리된 상태

- 삭제(removed): 삭제된 상태

// 객체를 생성한 상태(비영속)
Member member = new Member();

// 객체를 저장한 상태(영속)
em.persist(member);

// 회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
em.detach(member);

// 객체를 삭제한 상태(삭제)
em.remove(member);

(4) 영속성 컨텍스트 사용 시 장점

- 1차 캐시

-> 영속 컨텍스트 안 1차 캐시에 id가 member1이 있다면, 캐시값을 조회하여 member을 반환함

-> 영속 컨텍스트 안 1차 캐시에 id가 member2이 없다면, DB에서 엔티티를 가져와 1차 캐시에 저장하고 member2 엔티티를 반환함.

 

- 동일성 보장

Member a = em.find(Member.class, 1L);
Member b = em.find(Member.class, 1L);

System.out.println(a == b); // 동일성 비교 true 반환

 

-> 1L : 기본 키 ID를 기준으로 엔티티를 조회

 

 

- 트랜잭션을 지원하는 쓰기 지연

-> persist 시 영속 컨텍스트에 등록이 됨.

-> 1차 캐시에 memberB를 저장하고 INSERT SQL을 생성하지만 아직 실행은 안 함

-> SQL은 쓰기 지연 SQL 저장소에 잠깐 보관됨

 

-> commit()를 호출하면 JPA가 먼저 flush()를 실행하여 쓰기 지연 SQL 저장소에 있던 SQL 쿼리를 DB로 보내서 실행. 트랜잭션을 commit 하여 작업들을 확정하고 DB에 진짜로 영구 저장됨.

 

- 변경 감지(Dirty Checking)

// 트랜잭션 시작
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();

// 영속 엔티티 조회
Member memberA = em.find(Member.class, "memberA");

// 영속 엔티티 데이터 수정
memberA.setUsername("hi")
memberA.setAge(10);

// 트랜잭션 커밋
transaction.commit();

 

https://leejaedoo.github.io/persistence/

 

자바 ORM 표준 JPA 프로그래밍 | D-log

3. 영속성 관리

leejaedoo.github.io

 


추가) 2차 캐시란?

- JPA에서 1차 캐시를 벗어나도 공유해서 사용하는 캐시

-> 여러 트랜잭션, 여러 EntityManager 간에 공유

<1차 캐시 vs 2차 캐시>

항목 1차 캐시 2차 캐시
위치 EntityManager 내부 EntityManagerFactory 수준 (애플리케이션 전체 공유)
범위 트랜잭션 단위 (짧음) 애플리케이션 단위 (길게 유지 가능)
자동 적용 여부 자동 (JPA 기본) 설정해야 작동함
목적 중복 조회 방지, 변경 감지 DB 부하 줄이기, 성능 최적화
유지 시간 트랜잭션 끝나면 사라짐 설정에 따라 오래 유지 가능
적합한 캐시 - 거의 바뀌지 않고 자주 조회되는 데이터 (국가 코드, 부서 정보, 인기 상품, 게시글)

- 1차 캐시는 트랜잭션이 끝나면 날아가기 때문에 다음 요청에서 다시 DB 쿼리를 날려서 성능이 낭비됨

- 2차 캐시 사용 시 자주 조회되는 데이터를 DB까지 가지 않고 캐시에서 바로 가져올 수 있음.