나를 기록하다
article thumbnail
반응형

JPA

지금 프로젝트에 JPA를 사용하면서 문득 나는 JPA를 정말 알고 사용하고 있을까라는 의문이 들었다. 기한에 쫓겨가며 코드를 작성하는데 내가 처음에 생각했던 내 코드에 대해 완벽히 이해하고 설명할 수 있는 코드를 쓰자는 생각과 거리가 멀어진 느낌을 받았다. 그렇기 때문에 다시 초심을 찾고 조금 더디더라도 이해하고 누군가 나에게 코드에 대해 질문하면 설명할 수 있는 내가 되기 위해 면접 답변 형식으로 개념을 정리하고자 한다. 시작하겠다.

 

JPA란 무엇인가?

답변
Java Persistence API의 약자로 자바 진영의 ORM 기술 표준입니다.
관계형 데이터베이스는 어떻게 데이터를 저장할지에 초점이 맞춰진 기술이고, 객체지향 프로그래밍 언어는 메시지를 기반으로 기능과 속성을 한 곳에서 관리하는 데 초점이 맞춰진 기술입니다. 패러다임이 서로 다른데 객체를 데이터베이스에 저장하려 하니 문제가 발생하고 이것을 패러다임 불일치라고 합니다.
JPA는 영역의 중간에서 패러다임을 일치시켜 주기 위한 기술입니다. 개발자는 객체지향적으로 프로그래밍을 하고 JPA가 이를 관계형 데이터베이스에 맞게 SQL을 대신 생성해서 실행합니다. 즉 개발자는 SQL에 종속적인 개발을 하지 않아도 됩니다.

저장(insert)

insert

조회(select)

select

 

JPA를 사용해야 하는 이유를 설명하라

답변
SQL 중심적인 개발에서 객체 중심으로 개발할 수 있고,
단순 반복적인 SQL 구문을 작성하지 않아도 되므로 생산성이 향상되며,
객체를 수정하면 SQL 구문도 함께 수정되므로 유지 보수성 또한 증가합니다.
JPA가 중간에서 객체지향 프로그래밍 언어와 관계형 데이터베이스 사이에서 패러다임의 불일치 문제를 해결해주고,
1차 캐시, 지연 로딩, 배치 처리, 변경 감지 등의 기능으로 인해 성능이 증가합니다.
위와 같은 장점들이 있기에 JPA를 사용해야 합니다.

 

ORM이란 무엇인가?

답변
Object Relational mapping의 약자로 객체 관계 매핑을 의미합니다.
객체지향 언어에서 객체와 관계형 데이터베이스(RDB)의 테이블을 자동으로 매핑해주는 기술로써, DB 테이블을 마치 객체처럼 다룰 수 있게 해주기 때문에 SQL문 대신 코드로 DB를 다룰 수 있게 도와주는 역할을 합니다.
대표적인 ORM으로 JPA, MyBatis, Hibernate 등이 있습니다.

 

ORM의 장점은 무엇인가?

답변
객체지향적으로 DB 쿼리를 조작할 수 있고, SQL을 직접 작성하지 않아도 되기 때문에 개발 비용이 줄어듭니다.
코드 가독성, 재사용성, 유지보수성이 좋아집니다.
또한 특정 DB에 대한 종속성이 줄어듭니다.

 

ORM, JPA, Spring Data JPA의 차이를 설명하라.

답변
JPA는 자바 진영에서 표준으로 된 ORM이고, JPA는 인터페이스의 집합입니다.
즉, Java에서 사용하는 ORM 표준은 JPA입니다.
Spring Data JPA는 라이브러리 중 하나입니다.
JPA는 인터페이스이고 JPA의 대표적인 구현체 중 하나인 Hibernate를 개발자가 사용하기 쉽게 모듈화한 게 Spring Data JPA입니다.

 

영속성 컨텍스트란?

답변
영속성 컨텍스트는 데이터를 영구 보관하는 환경이라는 뜻입니다.
애플리케이션과 DB 사이에서 객체를 보관하는 가상 데이터베이스의 역할을 합니다.
논리적인 개념으로, 눈에 보이진 않지만 EntityManager가 생성될 때 1대1로 영속성 컨텍스트가 생성됩니다.
EntityManager를 통해 영속성 컨텍스트에 접근하여 데이터를 핸들링할 수 있습니다.
또한 영속성 컨텍스트는 트랜잭션 단위로 동작하는데 트랜잭션이 시작될 때 EntityManager가 생성되고, 1대1로 영속성 컨텍스트가 생성됩니다. 트랜잭션이 커밋되면 EntityManager와 영속성 컨텍스트 모두 사라지게 됩니다.

 

JPA 영속성 컨텍스트를 사용 시 이점이 무엇인가?

답변
대표적인 5가지 장점으로 1차 캐시, 동일성 보장, 쓰기 지연, 변경 감지, 지연 로딩이 있습니다.

 

1차 캐시에 대해 설명하라

답변
1차 캐시는 영속성 컨텍스트 내에 위치하여 캐시와 같은 역할을 수행합니다.
데이터를 SELECT할 때 1차 캐시에서 해당 데이터를 찾아보고,
만약 1차 캐시에 해당 데이터가 있으면 1차 캐시에 있는 데이터를 반환,
없으면 DB에서 직접 SELECT하여 1차 캐시에 저장 후 1차 캐시에 저장된 데이터를 반환합니다.
마찬가지로 저장할 때도 1차 캐시에 우선 저장하고 트랜잭션 커밋 시에 실제 DB에 저장합니다.

 

동일성 보장에 대해 설명하라

답변
1차 캐시에 의해 엔티티는 영속성 컨텍스트에 의해 관리되고, SELECT를 할 때 1차 캐시에서 데이터를 불러오게 됩니다.
따라서 JPA로 같은 데이터를 두 번 조회하면 두 데이터는 주소까지 일치하게 되어 == 비교가 가능해집니다.

 

쓰기 지연에 대해 설명하라

답변
트랜잭션이 커밋되기 전까지 영속성 컨텍스트 내에 위치한 쓰기 지연 SQL 저장소에 SQL 쿼리를 저장해뒀다가 트랜잭션이 커밋되는 시점에 모든 SQL을 DB에 전달합니다.

 

 

변경 감지에 대해 설명하라

답변
엔티티가 변경되면 따로 저장하거나 수정하는 코드 또는 쿼리를 작성하지 않아도 자동으로 변경해줍니다.
처음 DB에서 데이터를 SELECT해서 1차 캐시에 데이터를 저장할 때 스냅샷을 저장해뒀다가 커밋이 일어날 때 이 스냅샷과 비교하여 UPDATE 쿼리를 자동으로 생성해서 DB에 전달합니다.

 

지연 로딩에 대해 설명하라

답변
연관관계가 있는 엔티티가 있을 때. 해당 엔티티를 실제 사용할 때 SELECT 쿼리를 날리는 기능입니다.
연관관계의 주인인 Entity를 조회할 때 연관관계 Entity까지 동시에 불러오게 되는 즉시로딩과 대비되는 개념입니다.

 

JPA N+1 문제에 대해 설명하라

답변
N+1 문제는 연관관계 설정된 필드가 있는 Entity를 findAll() 메서드를 이용해서 여러 건의 Entity를 한 번에 조회할 때 발생하는 문제로,
findAll()로 조회한 Entity의 개수만큼, 연관관계 Entity에 대한 단건 조회 쿼리가 나가게 됩니다.
즉, findAll()로 n개의 데이터를 조회했을 때, 연관관계 Entity에 대한 단건 조회 쿼리가 n번 나가게 되어 총 n+1개의 쿼리가 나가게 됩니다.

 

해결 방법은 무엇이 있을까?

답변
@Query 어노테이션을 이용해서 JPQL을 직접 작성해서 join fetch 구문을 추가하여 연관 관계 Entity까지 한 번에 조회하는 방법으로 해결할 수 있습니다.
@Query("SELECT distinct t FROM Team t join fetch t.members")
List<Team> findAll();

 

N+1은 지연 로딩에서 발생할까 아니면 즉시 로딩에서 발생할까?

답변
이 문제는 즉시 로딩과 지연 로딩 시 모두 발생합니다.
즉시 로딩 시에는 조회 메서드 사용 시 findAll()을 한 Entity를 불러오는 쿼리가 1번 나가고,
연관 관계 Entity에 대한 단건 조회 쿼리가 n번 나갑니다.

지연 로딩 시에는 findAll() 메서드 사용 시에는 1번의 쿼리만 나가지만 마찬가지로 조회한 메서드를 순회하며 연관관계 Entity를 사용한다면 연관관계 Entity에 대한 단건 조회 쿼리가 n번 나가게 됩니다.
지연 로딩 시 findAll()로 불러온 List 중 하나의 데이터의 연관관계 Entity만 조회한다면 1번만 추가로 쿼리가 나갑니다.

 

반응형

'CS > Interview' 카테고리의 다른 글

[Interview] Spring, DI, IoC, ORM, JPA, Hibernate  (0) 2023.09.09
profile

나를 기록하다

@prao

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

profile on loading

Loading...