Notice
Recent Posts
Recent Comments
Link
250x250
반응형
«   2025/10   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

백고등어 개발 블로그

JPA / Hibernate 면접 질문 정리 - 완벽 대비 가이드 본문

면접

JPA / Hibernate 면접 질문 정리 - 완벽 대비 가이드

백고등어 2025. 9. 16. 16:35
728x90
반응형

JPA와 Hibernate는 자바 백엔드 개발에서 데이터베이스를 다룰 때 가장 널리 사용되는 기술입니다. 객체와 관계형 데이터베이스 사이의 불일치를 해결해주는 ORM 기술이죠. 면접에서도 자주 나오는 주제이므로 핵심 개념들을 확실히 정리해보겠습니다.

1. JPA와 Hibernate의 관계는 무엇인가요?

**JPA(Java Persistence API)**는 자바에서 ORM을 사용하기 위한 표준 명세입니다. 인터페이스와 애노테이션들을 정의해놓은 규약이라고 생각하면 돼요.

Hibernate는 JPA 명세를 구현한 실제 라이브러리입니다. JPA를 구현한 다른 라이브러리로는 EclipseLink, OpenJPA 등이 있지만, Hibernate가 가장 널리 사용됩니다.

자동차로 비유하면, JPA는 자동차의 설계도이고 Hibernate는 실제로 만들어진 자동차라고 할 수 있어요. Spring Data JPA는 이런 자동차를 더 쉽게 운전할 수 있게 해주는 자동 운전 시스템 같은 역할입니다.

2. 영속성 컨텍스트(Persistence Context)란 무엇인가요?

영속성 컨텍스트는 엔티티를 영구 저장하는 환경입니다. 애플리케이션과 데이터베이스 사이에서 엔티티를 관리하는 논리적인 공간이에요.

주요 기능:

  • 1차 캐시: 같은 트랜잭션 내에서 같은 엔티티 조회 시 캐시에서 반환
  • 동일성 보장: 같은 식별자로 조회한 엔티티는 동일한 인스턴스 보장
  • 변경 감지: 엔티티 변경사항을 자동으로 감지해서 UPDATE 쿼리 생성
  • 지연 로딩: 필요한 시점에 연관된 엔티티를 조회
@Transactional
public void example() {
    User user1 = userRepository.findById(1L); // DB 조회
    User user2 = userRepository.findById(1L); // 1차 캐시에서 조회
    
    user1.setName("변경된 이름"); // 더티 체킹으로 자동 UPDATE
} // 트랜잭션 종료 시 변경사항이 DB에 반영

3. 엔티티의 생명주기를 설명해주세요.

JPA 엔티티는 4가지 상태를 가집니다.

비영속(New/Transient): 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태

User user = new User(); // 비영속 상태

영속(Managed): 영속성 컨텍스트에 관리되는 상태

entityManager.persist(user); // 영속 상태
User foundUser = entityManager.find(User.class, 1L); // 영속 상태

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

entityManager.detach(user); // 준영속 상태
entityManager.clear(); // 모든 엔티티를 준영속 상태로

삭제(Removed): 삭제하기로 결정된 상태

entityManager.remove(user); // 삭제 상태

4. N+1 문제가 무엇이고 어떻게 해결하나요?

N+1 문제는 연관된 엔티티를 조회할 때 발생하는 성능 문제입니다. 1개의 쿼리로 N개의 데이터를 가져온 후, 각각의 연관 데이터를 가져오기 위해 N개의 쿼리가 추가로 실행되는 현상이에요.

문제 상황:

// User와 Post는 1:N 관계
List<User> users = userRepository.findAll(); // 1개 쿼리

for (User user : users) {
    user.getPosts().size(); // 각 user마다 쿼리 실행 (N개 쿼리)
}

해결 방법:

1. Fetch Join 사용:

@Query("SELECT u FROM User u JOIN FETCH u.posts")
List<User> findAllWithPosts();

2. EntityGraph 사용:

@EntityGraph(attributePaths = "posts")
@Query("SELECT u FROM User u")
List<User> findAllWithPosts();

3. Batch Size 설정:

@BatchSize(size = 10)
@OneToMany
private List<Post> posts;

5. 지연 로딩과 즉시 로딩의 차이점은 무엇인가요?

지연 로딩(Lazy Loading): 연관된 엔티티를 실제 사용하는 시점에 조회 즉시 로딩(Eager Loading): 엔티티를 조회할 때 연관된 엔티티도 함께 조회

@Entity
public class User {
    @OneToMany(fetch = FetchType.LAZY) // 지연 로딩 (기본값)
    private List<Post> posts;
    
    @ManyToOne(fetch = FetchType.EAGER) // 즉시 로딧
    private Team team;
}

권장사항:

  • @OneToOne, @ManyToOne: 기본이 EAGER이지만 LAZY로 변경 권장
  • @OneToMany, @ManyToMany: 기본이 LAZY이며 그대로 사용 권장

지연 로딩은 필요한 시점에만 데이터를 가져오므로 성능상 유리하지만, 트랜잭션 밖에서 접근 시 LazyInitializationException이 발생할 수 있어요.

6. 영속성 전이(Cascade)와 고아 객체 제거에 대해 설명해주세요.

영속성 전이(Cascade): 부모 엔티티의 변경사항이 자식 엔티티에도 전파되는 기능

@OneToMany(cascade = CascadeType.ALL)
private List<Post> posts;

// 사용 예시
User user = new User();
user.addPost(new Post("제목1"));
user.addPost(new Post("제목2"));

userRepository.save(user); // user와 post 모두 저장됨

Cascade 옵션:

  • PERSIST: 저장 시 전파
  • REMOVE: 삭제 시 전파
  • MERGE: 병합 시 전파
  • ALL: 모든 작업 전파

고아 객체 제거(Orphan Removal): 부모와의 관계가 끊어진 자식 엔티티를 자동으로 삭제

@OneToMany(orphanRemoval = true)
private List<Post> posts;

user.getPosts().remove(0); // 제거된 post가 DB에서도 삭제됨

7. JPQL과 Criteria API의 차이점은 무엇인가요?

JPQL(Java Persistence Query Language): SQL과 유사한 문법을 가진 객체 지향 쿼리 언어

@Query("SELECT u FROM User u WHERE u.age > :age")
List<User> findUsersByAge(@Param("age") int age);

@Query("SELECT u FROM User u JOIN u.posts p WHERE p.title LIKE %:keyword%")
List<User> findUsersByPostTitle(@Param("keyword") String keyword);

Criteria API: 자바 코드로 타입 안전한 쿼리를 작성하는 방법

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> query = cb.createQuery(User.class);
Root<User> user = query.from(User.class);

query.select(user)
     .where(cb.greaterThan(user.get("age"), 20));

List<User> users = entityManager.createQuery(query).getResultList();

비교:

  • JPQL: 간결하고 SQL에 익숙한 개발자가 사용하기 쉬움
  • Criteria API: 타입 안전하고 동적 쿼리 작성에 유리

8. Spring Data JPA의 쿼리 메소드는 어떻게 동작하나요?

Spring Data JPA는 메소드 이름을 분석해서 자동으로 JPQL을 생성합니다.

public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findByName(String name);
    List<User> findByAgeGreaterThan(int age);
    List<User> findByNameAndAge(String name, int age);
    List<User> findByNameContaining(String keyword);
    Page<User> findByAgeOrderByCreatedAtDesc(int age, Pageable pageable);
}

주요 키워드:

  • findBy, readBy, queryBy: 조회
  • countBy: 개수
  • deleteBy: 삭제
  • And, Or: 조건 연결
  • GreaterThan, LessThan: 비교
  • Like, Containing: 패턴 매칭
  • OrderBy: 정렬

9. 트랜잭션과 JPA의 관계는 무엇인가요?

JPA는 트랜잭션 안에서 동작해야 정상적으로 작동합니다. 영속성 컨텍스트는 트랜잭션과 생명주기를 함께 합니다.

@Transactional
public void updateUser(Long userId, String newName) {
    User user = userRepository.findById(userId).orElseThrow();
    user.setName(newName); // 더티 체킹으로 자동 UPDATE
    // 트랜잭션 종료 시 변경사항이 DB에 반영
}

트랜잭션 전파 속성:

  • REQUIRED: 기존 트랜잭션이 있으면 참여, 없으면 새로 생성 (기본값)
  • REQUIRES_NEW: 항상 새로운 트랜잭션 생성
  • SUPPORTS: 기존 트랜잭션이 있으면 참여, 없어도 실행
  • NEVER: 트랜잭션이 있으면 예외 발생

10. JPA 성능 최적화 방법을 설명해주세요.

1. 적절한 Fetch 전략 사용:

// 지연 로딩을 기본으로 하고 필요시 Fetch Join
@Query("SELECT u FROM User u JOIN FETCH u.posts WHERE u.id = :id")
Optional<User> findByIdWithPosts(@Param("id") Long id);

2. 배치 처리:

@Modifying
@Query("UPDATE User u SET u.status = :status WHERE u.id IN :ids")
int updateStatusByIds(@Param("status") Status status, @Param("ids") List<Long> ids);

3. 적절한 캐시 사용:

@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User {
    // ...
}

4. 불필요한 컬럼 조회 방지:

// DTO Projection 사용
@Query("SELECT new com.example.UserDto(u.id, u.name) FROM User u")
List<UserDto> findAllUserDto();

5. 배치 크기 설정:

spring.jpa.properties.hibernate.jdbc.batch_size=20
spring.jpa.properties.hibernate.order_inserts=true
spring.jpa.properties.hibernate.order_updates=true

핵심 정리

JPA/Hibernate는 단순히 SQL을 대신 작성해주는 도구가 아니라, 객체와 관계형 데이터베이스 사이의 패러다임 불일치를 해결해주는 복잡한 기술입니다. 영속성 컨텍스트의 동작 원리를 이해하고, N+1 문제 같은 성능 이슈를 해결할 수 있어야 실무에서 제대로 활용할 수 있어요.

면접에서는 단순히 사용법보다는 "왜 이렇게 동작하는가"에 대한 이해를 중요하게 봅니다. 실제 프로젝트에서 겪었던 문제와 해결 과정을 구체적으로 설명할 수 있도록 준비하세요.

728x90
반응형