아래는 "JPA 생명주기와 영속성 컨텍스트"에 대해 설명하는 글입니다. 예시를 포함하되, 롬복은 사용하지 않고 명확한 이해를 돕기 위해 기본적인 코드 스타일을 유지했습니다.

---

### JPA 생명주기와 영속성 컨텍스트

JPA에서 엔티티는 특정한 생명주기를 거치며 관리됩니다. 이 생명주기는 영속성 컨텍스트(Persistence Context)라는 JPA의 핵심 개념과 밀접하게 연관되어 있습니다. 영속성 컨텍스트는 엔티티의 상태를 추적하고 관리하며, 데이터베이스와의 동기화를 담당하는 환경입니다. 이를 통해 JPA는 객체와 데이터베이스 간의 매핑을 효율적으로 처리합니다.

#### 영속성 컨텍스트란?
영속성 컨텍스트는 엔티티 매니저(EntityManager)가 엔티티를 관리하는 논리적인 공간입니다. 엔티티가 영속성 컨텍스트에 포함되면 JPA가 해당 엔티티의 상태를 추적하고, 트랜잭션이 커밋될 때 데이터베이스에 반영합니다. 주요 특징은 다음과 같습니다:
- **1차 캐시**: 조회한 엔티티를 메모리에 저장해 동일 트랜잭션 내에서 재사용 가능.
- **변경 감지(Dirty Checking)**: 엔티티의 변경 사항을 자동으로 감지해 SQL을 생성.
- **쓰기 지연(Write Behind)**: 트랜잭션 커밋 시점에 변경 사항을 한꺼번에 데이터베이스에 반영.

#### 엔티티 생명주기
엔티티는 네 가지 상태를 거칩니다:
1. **비영속(Transient)**  
   - 엔티티 객체가 생성되었지만, 영속성 컨텍스트나 데이터베이스와 연결되지 않은 상태.
   - JPA가 전혀 관리하지 않음.
2. **영속(Managed)**  
   - 영속성 컨텍스트에 의해 관리되는 상태.
   - `persist()`나 `find()` 메서드로 엔티티가 영속성 컨텍스트에 포함됨.
3. **준영속(Detached)**  
   - 영속성 컨텍스트에서 분리된 상태.
   - `detach()`나 `close()`로 인해 더 이상 관리되지 않음.
4. **삭제(Removed)**  
   - 영속성 컨텍스트와 데이터베이스에서 삭제되도록 예약된 상태.
   - `remove()` 호출 후 트랜잭션 커밋 시 삭제됨.

#### 생명주기 예시
아래는 `Book` 엔티티를 통해 생명주기를 설명하는 코드입니다.

```java
import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class Book {
    @Id
    private Long id;
    private String title;

    public Book() {} // JPA 기본 생성자 요구

    public Book(Long id, String title) {
        this.id = id;
        this.title = title;
    }

    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getTitle() { return title; }
    public void setTitle(String title) { this.title = title; }
}
```

```java
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Persistence;

public class JpaLifecycleExample {
    public static void main(String[] args) {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaExample");
        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        // 1. 비영속 상태
        Book book = new Book(1L, "JPA 기초");
        System.out.println("상태: 비영속");

        // 2. 영속 상태
        em.persist(book);
        System.out.println("상태: 영속");

        // 영속성 컨텍스트에서 동일 객체 재사용 (1차 캐시)
        Book foundBook = em.find(Book.class, 1L);
        System.out.println("동일 객체: " + (book == foundBook)); // true

        // 변경 감지
        book.setTitle("JPA 심화"); // 별도 update 호출 없이 변경 감지됨

        // 3. 삭제 상태
        em.remove(book);
        System.out.println("상태: 삭제 예약");

        // 트랜잭션 커밋 - 데이터베이스 반영
        em.getTransaction().commit();
        System.out.println("커밋 완료");

        // 4. 준영속 상태
        em.detach(book); // 이미 삭제되었으므로 효과 없음
        em.close();

        // 새로운 트랜잭션에서 준영속 상태 확인
        EntityManager em2 = emf.createEntityManager();
        em2.getTransaction().begin();
        book.setTitle("JPA 고급"); // 영속성 컨텍스트가 없으므로 반영 안 됨
        em2.getTransaction().commit();
        em2.close();

        emf.close();
    }
}
```

#### 코드 설명
1. **비영속 상태**  
   - `Book book = new Book(1L, "JPA 기초");`: 객체는 생성되었지만 JPA와 무관합니다.

2. **영속 상태**  
   - `em.persist(book)`: 영속성 컨텍스트에 포함되며, 1차 캐시에 저장됩니다.
   - `em.find(Book.class, 1L)`: 데이터베이스 조회 없이 캐시에서 반환됩니다.

3. **변경 감지**  
   - `book.setTitle("JPA 심화")`: 영속 상태의 엔티티는 변경이 감지되어 커밋 시 자동으로 `UPDATE` 쿼리가 실행됩니다.

4. **삭제 상태**  
   - `em.remove(book)`: 엔티티가 삭제 예약되며, 커밋 시 `DELETE` 쿼리가 실행됩니다.

5. **준영속 상태**  
   - `em.detach(book)` 또는 `em.close()`: 영속성 컨텍스트에서 분리되어 더 이상 관리되지 않습니다.

#### 영속성 컨텍스트의 이점
- **성능 향상**: 1차 캐시로 동일 트랜잭션 내 반복 조회를 줄임.
- **자동 동기화**: 변경 감지로 개발자가 직접 SQL을 작성할 필요 없음.
- **트랜잭션 보장**: 쓰기 지연으로 트랜잭션 내 변경을 일괄 처리.

#### 주의사항
- 영속성 컨텍스트는 트랜잭션 범위에 따라 생명주기가 달라집니다. 트랜잭션이 끝나면 컨텍스트도 종료됩니다(기본적으로).
- 준영속 상태의 엔티티는 변경 감지가 적용되지 않으므로, 필요 시 `merge()`로 다시 영속 상태로 전환해야 합니다.

---

JPA의 생명주기와 영속성 컨텍스트는 엔티티 관리의 핵심입니다. 이를 이해하면 데이터베이스 작업을 더 효율적으로 처리할 수 있습니다. 다음 장에서는 트랜잭션 관리와 실무 활용을 다뤄보겠습니다.

---

책의 흐름에 맞는지, 추가 예시나 설명이 필요하면 말씀해 주세요!