| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 개발자
- 백준
- 핵심가이드
- JWT
- 컴퓨터 공학
- 컴퓨터 구조
- 스프링부트
- actuator
- Java
- 제로베이스
- 자료구조
- 프로그래머스
- 백엔드
- 서버
- LinkedList
- 백엔드공부
- restTemplate
- TestCode
- array
- spring
- spring boot
- JPA
- ORM
- error
- 연관관계
- QueryDSL
- queue
- 백엔드스쿨
- SpringSecurity
- SpringBoot
- Today
- Total
be_better
[Springboot] 데이터베이스 연동 - ORM, JPA 본문
목차
ORM
ORM은 Object Relational Mapping의 줄임말로 객체 관계 매핑을 의미한다. 자바와 같은 객체지향 언어에서 의미하는 객체와 RDB(Relational Database)의 테이블을 자동으로 매핑하는 방법이다.
객체지향 언어에서의 클래스는 데이터베이스의 테이블과 매핑하기 위해 만들어진 것이 아니기 때문에 RDB 테이블과 어쩔 수 없는 불일치가 존재한다. ORM은 이 둘의 불일치와 제약사항을 해결하는 역할이다.

ORM을 이용하면 쿼리문 작성이 아닌 코드(메서드)로 데이터를 조작할 수 있다.
ORM의 장점
- ORM을 사용하면서 데이터베이스 쿼리를 객체지향적으로 조작할 수 있다.
- 쿼리문을 작성하는 양이 현저히 줄어 개발 비용이 줄어든다.
- 객체지향적으로 데이터베이스에 접근할 수 있어 코드의 가독성을 높인다.
- 재사용 및 유지보수가 편리
- ORM을 통해 매핑된 객체는 모두 독립적으로 작성되어 있어 재사용이 용이
- 객체들은 각 클래스로 나뉘어 있어 유지보수가 수월하다.
- 데이터베이스에 대한 종속성이 줄어든다.
- ORM을 통해 자동 생성된 SQL문은 객체를 기반으로 데이터베이스 테이블을 관리하기 때문에 데이터베이스에 종속적이지 않다.
- 데이터베이스를 교체하는 상황에서도 비교적 적은 리스크를 부담한다.
ORM의 단점
- ORM만으로 온전한 서비스를 구현하기에는 한계가 있다.
- 복잡한 서비스의 경우 직접 쿼리를 구현하지 않고 코드로 구현하기 어렵다
- 복잡한 쿼리를 정확한 설계 없이 ORM만으로 구성하게 되면 속도 저하 등의 성능 문제가 발생할 수 있다.
- 애플리케이션의 객체 관점과 데이터베이스의 관계 관점의 불일치가 발생한다.
- 세분성(Granularity): ORM의 자동 설계 방법에 따라 데이터베이스에 있는 테이블의 수와 애플리케이션의 엔티티(Entity) 클래스의 수가 다른 경우가 생긴다. (클래스가 테이블의 수보다 많아질 수 있음)
- 상속성(Inheritance): RDBMS에는 상속이라는 개념이 없다.
- 식별성(Identity): RDBMS는 기본키(primary key)로 동일성을 정의한다. 하지만 자바는 두 객체의 값이 같아도 다르다고 판단할 수 있다. 식별과 동일성의 문제
- 연관성(Associations): 객체지향 언어는 객체를 참조함으로써 연관성을 나타내지만 RDBMS에서는 외래키(foreign key)를 삽입함으로써 연관성을 표현한다. 또한 객체지향 언어에서 객체를 참조할 때는 방향성이 존재하지만 RDBMS에서 외래키를 삽입하는 것은 양방향의 관계를 가지기 때문에 방향성이 없다.
- 탐색(Navigation): 자바와 RDBMS는 어떤 값(객체)에 접근하는 방식이 다르다. 자바에서는 특정 값에 접근하기 위해 객체 참조 같은 연결 수단을 활용한다. 이 방식은 객체를 연결하고 또 연결해서 접근하는 그래프 형태의 접근 방식이다. (예: 어떤 멤버의 회사 주소 -> member.getOrganization().getAddress() 로 접근) 반면 RDBMS에서는 쿼리를 최소화하고 조인을 통해 여러 테이블을 로드하고 값을 추출하는 접근 방식을 채택하고 있다.
JPA
JPA(Java Persistence API)는 자바 진영의 ORM 기술 표준으로 채택된 인터페이스의 모음이다. ORM이 큰 개념이라면 JPA는 더 구체화된 스펙을 포함한다. 즉, 어떻게 동작해야 하는지 메커니즘을 정리한 표준 명세이다.

JPA의 메커니즘을 보면 내부적으로 JDBC를 사용한다. 개발자가 직접 JDBC를 구현하면 SQL에 의존하게 되는 문제 등이 있어 개발의 효율성이 떨어지는데, JPA는 이 같은 문제점을 보완해서 개발자 대신 적절한 SQL을 생성하고 데이터베이스를 조작해서 객체를 자동 매핑하는 역할을 수행한다.
대표적인 JPA 기반의 구현체 세가지로는 가장 많이 사용하는 하이버네이트(Hibernate), 이클립스 링크(EclipseLink), 데이터 뉴클리어스(DataNucleus)가 있다.

하이버네이트
하이버네이트는 자바의 ORM 프레임워크로, JPA가 정의하는 인터페이스를 구현하고 있는 JPA 구현체 중 하나이다.
Spring Data JPA
Spring Data JPA는 JPA를 편리하게 사용할 수 있도록 지원하는 스프링 하위 프로젝트 중 하나이다. 하이버네이트의 엔티티 매니저(EntityManager)를 직접 다루지 않고 리포지토리를 정의해 사용함으로써 스프링이 적합한 쿼리를 동적으로 생성하는 방식으로 데이터베이스를 조작한다.

영속성 컨텍스트
영속성 컨텍스트(Persistence Context)는 애플리케이션과 데이터베이스 사이에서 엔티티와 레코드의 괴리를 해소하는 기능과 객체를 보관하는 기능을 수행한다. 엔티티 객체가 영속성 컨텍스트에 들어와 JPA의 관리 대상이 되는 시점부터는 해당 객체를 영속 객체(Persistence Object)라고 부른다.

영속성 컨텍스트는 세션 단위의 생명주기를 갖는다. 데이터베이스에 접근하기 위한 세션이 생성되면 영속성 컨텍스트가 만들어지고, 세션이 종료되면 영속성 컨텍스트도 없어진다.
엔티티 매니저
엔티티 메니저(EntityManager)는 이름 그대로 엔티티를 관리하는 객체이다. 엔티티 매니저는 데이터베이스에 접근해서 CRUD 작업을 수행한다. 실제 내부 구현체인 SimpleRepository가 리포지토리에서 엔티티 매니저를 사용하는 것을 알 수 있다.
SimplaJpaRepository의 EntityManager 의존성 주입 코드
public SimpleJpaRepository(JpaEntityInformation<T, ?> entityInformation,
EntityManager entityManager) {
Assert.notNull(entityInformation, "JpaEntityInformation must not be null!");
Assert.notNull(entityManager, "EntityManager must not be null!");
this.entityInformation = entityInformation;
this.em = entityManager;
this.provider = PersistenceProvider.fromEntityManger(entityManager);
}
엔티티 매니저는 엔티티 매니저 팩토리(EntityManagerFactory)가 만든다. 엔티티 매니저 팩토리는 application.properties에서 작성한 최소한의 설정만으로도 동작하지만 JPA의 구현체 중 하나인 하이버네이트에서는 persistence.xml이라는 설정 파일을 구성하고 사용해야 하는 객체이다.
엔티티 매니저 팩토리 사용을 위한 persistence.xml 파일 설정
<?xml version="1.0" encoding="UTF-8" ?>
<persistence version="3.0" xmlns="https://jakarta.ee/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/persistence
https://jakarta.ee/xml/ns/persistence/persistence_3_0.xsd">
<persistence-unit name="entity_manager_factory" transaction-type="RESOURCE_LOCAL">
<properties>
<property name="javax.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="password"/>
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/hello"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
</properties>
</persistence-unit>
</persistence>
persistence-unit을 설정하면 해당 유닛의 이름을 가진 엔티티 매니저 팩토리가 생성된다. 엔티티 매니저 팩토리는 애플리케이션에서 단 하나만 생성되며, 모든 엔티티가 공유해서 사용한다.
엔티티 매니저 팩토리로 생성된 엔티티 매니저는 영속성 컨텍스트와 데이터베이스를 비교하면서 실제 데이터베이스를 대상으로 작업을 수행한다.
엔티티의 생명주기
- 비영속(New)
- 영속성 컨텍스트에 추가되지 않은 엔티티 객체의 상태
- 영속(Managed)
- 영속성 컨텍스트에 의해 엔티티 객체가 관리되는 상태
- 준영속(Detached)
- 영속성 컨텍스트에 의해 관리되던 엔티티 객체가 컨텍스트와 분리된 상태
- 삭제(Removed)
- 데이터베이스에서 레코드를 삭제하기 위해 영속성 컨텍스트에 삭제 요청을 한 상태
'Springboot > 이론' 카테고리의 다른 글
| [Springboot] Spring Data JPA 활용 - JPQL (0) | 2023.11.10 |
|---|---|
| [Springboot] 데이터베이스 연동 - 프로젝트 적용 (0) | 2023.11.05 |
| [Springboot] API를 작성하는 다양한 방법 (0) | 2023.10.29 |
| [Springboot] 스프링 부트 애플리케이션 개발하기 (0) | 2023.10.29 |
| [Springboot] 개발 환경 구성 (0) | 2023.10.22 |