---
description: 데이터 접근과 ORM
---

# ORM & Data Access

**ORM과 JPA**

## ORM(Object-Relational Mapping)이란 무엇인가요?

"관계형 데이터베이스를 OOP 언어도 변환해주는 기술입니다. 비즈니스 코드가 DB 테이블에 바로 접근하게 도와줍니다."

* 객체와 관계형 데이터베이스의 테이블 간의 불일치를 해소하기 위한 기술
* SQL을 직접 작성하지 않고, 객체와 데이터베이스 간의 매핑을 통해 데이터를 조작
* **데이터베이스 독립성**: 특정 DBMS에 종속되지 않고, ORM을 통해 여러 데이터베이스에서 동일한 코드로 작업



## JPA(Java Persistence API)란 무엇이며, 어떤 장점이 있나요?

"자바에서 ORM(Object-Relational Mapping) 표준을 정의한 인터페이스. JPA는 자바 객체와 관계형 데이터베이스 간의 매핑을 제공하며, 데이터베이스에 접근하고 조작하는 방법을 정의. 구현체로는 Hibernate가 있습니다."

* 표준화된 API: 특정 ORM 구현체에 종속되지 않습니다.
* 생산성 향상: 복잡한 SQL을 직접 작성하지 않고, 객체 지향적인 방식으로 DB 작업 처리
* 지연 로딩 및 캐싱: 지연 로딩을 통해 필요한 시점에 데이터를 로드하거나 캐싱을 통해 DB 접근을 최소화



## JPA와 Hibernate의 관계와 차이점을 설명해주세요.

**JPA는 ORM을 위한 표준 인터페이스**이고, **Hibernate는 JPA의 구체적인 구현체** 중 하나

JPA&#x20;

* 자바 애플리케이션에서 객체와 관계형 데이터베이스 간의 매핑을 표준화한 API
* JPA의 목적은 ORM을 위한 공통 인터페이스를 제공하여, 특정 구현체에 종속되지 않도록 하는 것



Hibernate

* **JPA의 구현체 중 하나**로, 가장 많이 사용되는 ORM 프레임워크
* JPA에서 정의된 표준 인터페이스를 구현하고, 추가적으로 다양한 기능을 제공



## Spring Data JPA란 무엇인가요?

Spring 프레임워크에서 JPA를 더 편리하게 사용할 수 있도록 도와주는 모듈

JPA를 사용하기 위해서는 기본적으로 EntityManager를 설정하고, 여러 메서드를 작성해야 하는 과정을 작성해야하는데, Spring Data JPA는 이러한 과정을 자동화.





**Entity와 영속성 컨텍스트**

## Entity란 무엇이며, 어떻게 설계해야 하나요?

**JPA에서 데이터베이스의 테이블과 매핑되는 자바 객체**를 의미

* Entity 클래스는 데이터베이스 테이블의 구조를 반영하며, 각 필드는 테이블의 컬럼에 대응
* Entity를 통해 데이터베이스와의 연동을 객체지향적으로 처리하고 JPA는 Entity 객체의 상태를 자동으로 데이터베이스와 동기화



## 영속성 컨텍스트란 무엇이며, 어떤 역할을 하나요?

JPA의 핵심 개념으로, 엔티티(Entity) 객체들을 관리하는 일종의 **'가상 데이터베이스'**&#xC785;니다.

* 영속성 컨텍스트는 엔티티를 **영속성 상태**로 관리 (비영속, 영속, 준영속, 삭제 4가지 상태)
* 더티 체킹: 영속성 컨텍스트는 엔티티의 **스냅샷**을 유지하여, 트랜잭션이 끝나기 전까지 엔티티 객체의 변경 사항을 감지하여 변경된 부분만 데이터베이스에 반영
* 변경 감지: 필요할 때 자동으로 flush를 호출하여, 메모리 상의 상태를 데이터베이스와 동기화



## 1차 캐시와 동일성(identity) 보장에 대해 설명해주세요.

1차 캐시:

* **영속성 컨텍스트 내부의 메모리 공간**으로, JPA가 관리하는 **영속성 컨텍스트 내에 저장된 엔티티를 캐싱**하는 기능
* 동일한 트랜잭션 내에서는 이미 조회된 엔티티를 다시 데이터베이스에서 읽어오지 않고 **1차 캐시**에서 반환

동일성:

* **"== 연산자"**&#xB97C; 사용하여 객체의 동일성을 보장할 수 있음을 의미
* 동일한 트랜잭션 내에서 동일한 객체가 반환





**트랜잭션 관리**

## 트랜잭션이란 무엇이며, 왜 중요한가요?

데이터베이스에서 여러 작업(쿼리)을 하나의 작업 단위로 묶는 개념

* ACID 특성을 통해 데이터 무결성과 일관성 보장.
* 원자성
* 일관성: 트랜잭션 실행 전후의 데이터 상태는 항상 정의된 규칙(제약 조건 등)을 만족
* 격리성
* 지속성



## 트랜잭션을 추상화해서 사용하는 이유는 무엇인가요?

트랜잭션을 **추상화**한다는 것은, 트랜잭션을 **구체적인 구현 기술이나 환경에 의존하지 않고, 일관되게 관리할 수 있도록 처리하는 것**을 의미 (데이터베이스나 기술 스택에 상관없이 동일한 방식으로 트랜잭션을 처리할 수 있도록합니다.)

* 일관된 트랜잭션 관리: 트랜잭션을 처리하는 방식이 기술마다 다른데, 여러 환경에서 일관된 방식으로 관리
* 기술 종속성 제거:  특정 DB나 ORM 프레임워크에 종속X
* 코드 간소화: commit/rollback 등 명시적 처리가 불필요.
* 선언적으로 유연하게 트랜잭션 관리. (@Transactional 어노테이션 등을 사용하여 간단하게 메서드에 적용)



## Spring에서 트랜잭션을 적용하는 방법을 설명해주세요.

**`@Transactional`** 어노테이션을 사용

트랜잭션 전파 속성, 격리 수준, 롤백 조건 등을 설정하여 유연하게 트랜잭션을 제어



## 트랜잭션 전파 옵션(Propagation)에 대해 설명해주세요.

트랜잭션이 실행되는 동안 기존에 실행 중인 트랜잭션이 있을 때, 새로운 트랜잭션을 어떻게 처리할지 결정하는 방식 (**`@Transactional`** 어노테이션을 통해 트랜잭션 전파 속성을 설정)

* 하나의 트랜잭션 안에서 또 다른 트랜잭션을 호출할 때, 기존 트랜잭션을 유지할 것인지, 새로운 트랜잭션을 생성할 것인지 등의 정책을 정의하는 것
* REQUIRED(기본값): 현재 트랜잭션이 존재하면 그 트랜잭션에 참여하고, 없으면 새로운 트랜잭션을 시작
* REQUIRES\_NEW: 항상 **새로운 트랜잭션**을 시작
* SUPPORTS: **있으면 참여하고, 없으면 트랜잭션 없이** 메서드를 실행
* NOT\_SUPPORTED: 트랜잭션을 **사용하지 않고** 메서드를 실행
* MANDATORY: **반드시 트랜잭션이 있어야** 합니다. 만약 현재 트랜잭션이 없으면 예외가 발생
* NEVER: **트랜잭션이 있으면 예외**를 발생
* NESTED: 현재 트랜잭션이 있으면 **중첩된 트랜잭션**을 시작합니다. 중첩된 트랜잭션은 부모 트랜잭션에 종속적이지만, 독립적으로 롤백



## 트랜잭션 지연이란 무엇인가요?

**즉시 커밋되거나 롤백되지 않고, 특정 시점까지 지연되어 처리되는 것**을 의미

데이터베이스 성능을 최적화하고 불필요한 데이터베이스 호출을 줄이는 데 유용

* 쓰기지연: JPA에서 **쓰기 지연**은 실제로 데이터베이스에 변경 사항이 반영되기 전에 트랜잭션 내에서 변경된 엔티티의 상태를 **일시적으로 캐싱**하거나 지연시키는 방식
* 지연로딩: **지연 로딩**은 JPA에서 **트랜잭션 내에서 엔티티 간의 관계 데이터 로딩을 지연**시키는 방식입니다. 기본적으로 JPA는 `@OneToMany`, `@ManyToOne`과 같은 관계 데이터를 설정할 때, 즉시 로딩(Eager Loading) 또는 지연 로딩(Lazy Loading)을 선택할 수 있습니다.
* 배치 처리: 배치 처리(Batch Processing)는 대량의 데이터를 **한꺼번에 처리**하는 방식으로, 주로 데이터베이스에서 대량의 트랜잭션을 한 번에 처리할 때 사용됩니다. 배치 처리는 보통 실시간으로 처리하지 않아도 되는 작업을 **주기적으로** 또는 **일괄적으로** 처리하는 데 적합합니다.





**지연 로딩과 즉시 로딩**

## 지연 로딩(LAZY)과 즉시 로딩(EAGER)의 차이점을 설명해주세요.

**"JPA에서 엔티티 간의 관계를 매핑할 때, 연관된 데이터를 언제 로드할지를 결정하는 방식"**

지연 로딩: (fetch = FetchType.LAZY)

* 관련된 엔티티나 컬렉션을 **실제로 필요할 때까지 데이터베이스에서 조회하지 않는 방식**

즉시 로딩: (fetch = FetchType.EAGER)

* 연관된 엔티티나 컬렉션을 **즉시 함께 로드하는 방식**입니다. 엔티티를 조회할 때, 연관된 모든 데이터도 즉시 데이터베이스에서 조회





**N+1 문제와 해결 방법**

## N+1 문제란 무엇이며, 왜 발생하나요?

**N+1 문제**는 JPA에서 **지연 로딩(LAZY)** 전략을 사용할 때 발생하는 성능 이슈 중 하나입니다. 한 번의 쿼리로 부모 엔티티를 조회한 후, **연관된 자식 엔티티를 지연 로딩 방식으로 반복적으로 조회**할 때, 추가적으로 **N개의 쿼리**가 발생하는 현상

예시)

1. 먼저, 부모 엔티티 목록을 조회하는 **1개의 쿼리**가 실행됩니다.
2. 조회된 부모 엔티티 각각에 대해 **N번의 자식 엔티티 조회 쿼리**가 실행됩니다.

결과적으로, 부모 엔티티 1개와 자식 엔티티 N개를 조회할 때 **총 N+1개의 쿼리**가 발생하게 됩니다.



## N+1 문제를 해결 하는 방법을 설명해주세요.

연관된 데이터를 한번에 불러오면 N+1 문제를 해결할 수 있습니다.

1. FETCH JOIN 사용: 한 번의 쿼리로 부모 엔티티와 연관된 자식 엔티티를 **동시에 가져오는 방식**
2. 즉시 로딩: 연관된 데이터를 **즉시 함께 로드**하는 방식으로, 부모 엔티티를 조회할 때 자식 엔티티도 한꺼번에 조회. 연관된 데이터가 많을 경우에는 성능 문제 발생



**DTO와 VO**

## DTO(Data Transfer Object)와 VO(Value Object)의 차이점을 설명하고, DTO를 사용하는 이유는 무엇인가요?

DTO: **데이터 전달 객체**라는 뜻으로, **계층 간 데이터를 전달할 때 사용하는 객체**

* 데이터 전송에 사용.
* 변경 가능.
* 비즈니스 로직X
* 클라이언트-서버 간 데이터 이동

VO: **값 객체**라는 뜻으로, **불변(immutable)** 특성을 가지는 객체

* 값을 표현
* 불변
* 간단한 로직 포함
* 좌표, 통화, 날짜 같은 값 객체



## DAO, DTO, BO, VO의 역할과 차이점을 설명해주세요.

DAO: 데이터베이스와의 상호작용을 담당하는 객체

DTO: **계층 간 데이터 전달**을 위한 객체

BO: 비즈니스 로직을 처리하는 객체

VO: 값 자체를 나타내는 객체



**객체 상속과 데이터베이스**

## 객체 간의 상속 관계를 데이터베이스에 매핑하는 방법을 설명해주세요.

JPA에서는 **객체 상속 관계**를 데이터베이스 테이블로 매핑하는 세 가지 주요 전략을 제공, **단일 테이블 전략, 조인 전략, 구체 클래스별 테이블 전략**

단일 테이블 전략: 부모 클래스와 자식 클래스의 모든 속성을 **하나의 테이블에 저장**하는 방식

* 단점: 불필요한 컬럼이 생길 수 있고, 테이블 크기가 커짐

조인 전략: **부모 클래스의 속성은 부모 테이블에**, **자식 클래스의 속성은 자식 테이블에** 저장하는 방식

* 단점: JOIN 연산이 많이 발생하여 복잡한 쿼리일수록 성능 저하

구체 클래스별 테이블 전략: 각 자식 클래스에 해당하는 테이블에는 부모 클래스의 속성과 자식 클래스의 속성이 모두 저장

* 부모 클래스의 속성이 자식 테이블에 중복 저장되어서, 데이터 중복 발생 가능



참고: 개발자 전공 면접-6. 스프링

[https://youtu.be/VHZ2i4cuwb8?si=KA7UDzroSafKzgBT](https://youtu.be/VHZ2i4cuwb8?si=KA7UDzroSafKzgBT)
