본문 바로가기

JAVA/Spring Boot

Spring Data JPA

반응형

Spring Data JPA


스프링 프레임워크를 이용했을 때 얻을 수 잇는 장점 중에 하나는 기존의 다른 프레임워크들과의 통합이 가능하다는 점이다.

스프링 프레임워크는 기본적으로 다른 프레임워크들과의 대립이 아닌 융합을 선택했기 때문에 각종 프레임워크들과의 통합을 위한 '어댑터(Adaptor)'들을 지원한다. 따라서 개발의 편의를 도와주는 추가 기능들이 많다.


과거 JDBC에서 ORM(Object Relational Mapping)까지 'Spring Data'라는 하위 프로젝트를 통해 다양한 방식의 개발을 지원하고 있다.


Spring Data JPA는 JPA(Java Persistence API)라는 기술을 스프링에서 개발할 수 있도록 돕는 라이브러리이다.

이를 이용하면 다양한 데이터 베이스에서 종족적인 SQL문없이도 개발이 가능하기 때문에 개발의 생산성을 높일 수 있다.


JPA소개

JPA는 java Persistence API의 약자로 Java 관련 기술 스펙의 하나이다.

간단히 설명하면 Java를 이용해 데이터를 관리(유지)하는 기법을 하나의 스펙으로 정리한 표준이라고 할 수 있다.

데이터베이스와 관련된 기술과 스펙은 오랫동안 이슈가 되어왔었고, Java 진영에서는 EJB라는 기술 스펙에서 엔티티 빈(Entity Bean)이라는 데이터를 처리하는 스펙을 정한 것이 JPA의 시초라고 할수 있다.


JPA를 이해하기 위해서는 먼저 ORM(Object Relational Mapping)에 대한 얘기부터 시작할 필요가 있다.

ORM은 객체지향에서 말하는 객체와 데이터베이스에서 말하는 개체가 상당히 유사하다는 입장에서 시작한다.

예) 회원정보


@Entity

@Table(name="tbl_members")

@Data

public class Member {

@Id

private String mid;


private String mpw;


private String mname;


private String nickname;


private String rolename;


@CreateTimestamp

private Data regdate;

@UpdateTimestamp

private Data updatedate;


}

 

tbl_members

mid VARCHAR(255)

mname VARCHAR(255)

mpw VARCHAR(255)

nickname VARCHAR(255)

regdate DATETIME

updatedate DATETIME



객체지향에서 클래스로 설계하는 모습과 데이터베이스의 테이블 구조가 거의 유사하다.

이러한 유사점들이 ORM에서는 '데이터베이스와 객체지향을 한번에 처리할 수 있지 않을까'라는 생각으로 시작하게 된다.


ORM은 특정한 언어에 종속적인 개념이 아니라 즉, 다른 언어에서도 ORM 관련 프레임워크들이 많이 존재하듯이 ORM 자체는 객체지향과 관계형 데이터베이스를 매핑시킨다는 추상화된 개념이다.


JPA는 ORM의 개념을 Java 언어에서 구현하기 위한 스펙이다.

ORM이 일종의 비전(vision)에 불과했다면 JPA는 Java에서 이를 구현하기 위한 상세화한 통과 기준이라고 볼 수 있다.


JPA를 좀 더 쉽게 설명하자면 기존의 JDBC 등을 이용해서 직접 구현했던 데이터베이스 관련 작업을 대신 처리해주는 추상화된 계층의 구현 스펙이라고 할 수 있다.

JPA를 이용하면 데이터베이스에 대한 처리를 JPA 계층에서 처리하기 떄문에 좀 더 추상화된 형태의 코드를 제작하는 것만으로 개발이 가능하다.


JPA는 그 자체로는 스펙에 불과하기 때문에 실제로 구현한 제품이나 프레임워크들의 존재가 필수적이다.

예) Servlet이라는 기술 스펙을 Tomcat에서 구현한 것처럼, JPA를 구현한 구현체 중에서 스프링 부트 프로젝트에서는 Hibernate라는 것을 이용하게 된다.


Hibernate, EclipseLink, DataNucleus 등이 있다.


장점

-데이터베이스 관련 코드에 대해 유연함을 얻을 수 있다.

데이터베이스 변경은 기존의 소스 코드에 치명적인 영향을 미친다.

데이터베이스가 변경되면 이를 사용하는 SQL이 변경되고, DAO나 서비스, 화면까지 영향을 미치게 된다.

반면에 JPA를 이용하면 테이블 생성 등과 같은 작업부터 변경되는 DB 설계와 JAVA 설계를 한번에 처리할 수 있어서 익숙해진다면 빠른 생산성을 얻을 수 있다.

-데이터베이스와 독립적인 관계이다.

JPA는 특정 벤터(회사)의 데이터베이스에 종속적이지 않기 때문에 개바발자들은 데이터베이스 제품이 변경되거나 버전이 변경되는 것과 같은 골치 아픈 일에서 자유로워질 수 있다.

물론 각 데이터베이스 제품에 따라 지원하는 기능에 차이가 있긴 하지만, 설계 당시에 이러한 점을 고려해서 설계할 수 있는 방법을 지원한다.


단점

-학습곡선 크다.

기존 데이터베이스 위주 학습에 비해서 새롭게 배워야하는 기능들이 많다.

따라서 새로운 개념과 기술을 익히는 학습곡선이 크기 때문에 선뜻 적요하기 어렵다.

-근본적인 객체지향 설계 사상이 반영되어야 한다.

JPA는 어떻게 적합한 객체들의 관계를 작성할 것인가? 가 프로젝트이 성패를 좌우한다.

이 과정에서는 충분한 설계와 검토 과정을 거쳐야하는데 현실적으로 바쁜 일정이나 개발 숙련도 등의 당야한 문제들을 국복해야만 한다.

-특정데이터베이스의 강력함을 활용할 수 없다는 문제

JPA를 이요하면 SQL튜닝 등의 작업에 제약이 생길 수 도 있다.

JPA는 native SQL이라는 기능을 지원해서 기존의 SQL을 재사용할수 있는 방법도 있지만, 이경우 데이터베이스에 독립적인 개발이 불가능 하기 때문에 JPA의 장점을 잃는 한계를 가지게 된다.


JPA의 구조

JPA를 이용하면 Java로 작성된 클래스, 객체들과 데이터베이스상에 테이블, 레코드들을 자동으로 관리하게 된다.

개발자는 별도의 SQL을 작성할 필요 없이, 원하는 객체지향의 구조를 설계하는 것만으로도 모든 개발을 끝낼수도 있다.

물론 이렇게 되기 위해서는 중간에 놓여있는 JPA의 역할이 중요하다.

Java 쪽의 메모리 상태와 데이터베이스의 상태를 관리해야 하기 때문에 이에 대한 상태 등에서 대해서 별도의 용어들을 이용해서 표현한다.


엔티티(Entity), 엔티티 매니저(EntityManager)

엔티티라는 용어는 데이터베이스상에서 데이터로 관리하는 대상을 의미한다.

예) '상품', '회사', '직원' 등과 같이 명사이면서 업무와 관련된 데이터를 엔티티로 규정한다.


데이터베이스에서는 엔티티를 위해서 일반적으로 테이블을 설계하고, 데이터를 추가한다.

이렇게 추가된 데이터를 '인스턴스' 혹은 '레코드'라는 용어를 호칭한다.


JPA에서는 Java를 이용해서 이러한 엔티티들을 관리하기 때문에 엔티티 타입의 존재는 클래스가 된다.

예) JPA에서 '하나의 엔티티 타입을 생성한다'라는 의미는 '하나의 클래스'를 작성한다는 의미


JPA를 하면서 주의할 점은 '엔티티'라는 용어가 때로는 클래스를 의미할 경우도 있지만, 인스턴스를 의미하는 경우도 있다.

회원 엔티티가 회원클래스를 의미하는 경우도 있고, 회원 클래스에 생성된 인스턴스를 의미하는 경우도 있다.

물론 회원 엔티티 클래스와 회원 엔티티 인스턴스 혹은 회원 엔티티 객체라는 표현이 정확하지만 혼용되는 경우가 많다.


엔티티 매니저는 여러 엔티티 객체들을 관리하는 역할을 한다.

여기서 관리는 Life Cycle이라고 할수 있다.

엔티티 매니저는 자신이 관리해야 하는 엔티티 객체들을 '영속 컨텍스트(Persistence Context)'라는 곳에 넣어두고, 객체들의 생사를 관리하게 된다.

영속 컨텍스트(Persistence Cotnext)와 엔티티 객체

영속 컨텍스트는 JPA가 엔티티 객체들을 모아두는 '공간'이라고 이해할 수 있다.

컨텍스트 용어는 하나의 공간이나 울타리라는 개념으로 이해하는 것이 좋다.

New(비영속) Java 영역에 객체만 존재하고, 데이터베이스와 연동된 적이 없는 상태, 엔티티 매니저의 관리하에 있는 것이 아니기 때문에 순수한 Java 객체


Managed(영속) 데이터베이스에 저장되고, 메모리상에서도 같은 상태로 존재하는 상태, 객체는 영속컨텍스트 내에 들어가게 되고, id(PK)값을 통해서 필요한 엔티티 객체를 꺼내 사용할수 있게 된다.


Removed(삭제) 데이터베이스에서 삭제된 상태, 객체는 더 이상 영속 컨텍스트에 존재하지 않는다.


Detached(준영속) 영속컨텍스트에서 엔티티 객체를 꺼내서 사용하는 상태, 준영속 상태의 객체는 고유한 id(PK)를 가지고 있지만, 아직 데이터베이스와 동기화가 이루어지지 않는 상태


기존의 JPA 개발과 Spring Data JPA

JPA를 이요해서 개발하는 과정이 조금 복잡하다.

JPA에서는 EntityManager라는 존재를 이용해서 '영속성'이라는 것을 관리하게 된다.


예) 예외처리를 하지 않는 최소한의 코드

EntityManagerFactory emfactory = Persistence.createEntityManagerFactory("My_JPA");


EntityManager entitymanager = emfactory.createEntityManager();

entitymanager.getTransaction().begin();


Employee employee = ...


--생략--


entitymanager.persist(employee);

entitymanger.getTransaction().commit();


entitymanager.close();

emfactory.close();

EntityManager라는 것을 이용해서 객체를 보관(Persist())한다.

이때 트랜잭션에 대한 관리 역시 필요하고, close() 메서드를 이용해서 사용한 자원들을 정리해 주어야 한다.


Spring Data JPA의 경우

import org.springframework.data.repository.CrudRepository;


public interface CustomerRepository extends CrudRepository<Customer, Long> {

List<Cutomer> findByLastName(String name);

}



Java에서 인터페이스를 설계하고, 이를 구현하는 클래스를 만드는 것이 일반적이지만, Spring Data JPA는 동적으로 인터페이스를 구현하는 클래스를 만들어 내는 방식(동적 프록시, Dynamic Proxy)을 이용해서 실제 클래스를 작성하지 않아도 자동으로 만들어지기 때문에 별도의 코드를 작성할 필요가 없다.


-스타트 스프링 부트 저자구멍가게 코딩단-

반응형

'JAVA > Spring Boot' 카테고리의 다른 글

스프링 부트 보안 (예제)  (0) 2018.04.07
스프링부트 웹 개발 (샘플)  (0) 2018.04.06
스프링 부트 데이터 액세스  (0) 2018.02.12
스프링 부트 테스트  (0) 2018.02.09
스프링부트에서 스프링  (0) 2018.02.09