luminous_dev 2025. 3. 3. 12:50

 

 

과거에는 데이터베이스에 객체를 저장하려면 복잡한 JDBC API와 SQL을 직접 작성했어야 함

MyBatis가 들어온 후에는 SQL을 직접 작성해야 했음 

JPA를 사용하면 SQL도 쓸 필요가 없음 

 

 

SQL 중심적인 개발의 문제점

 

만약 테이블을 변경할 일이 생기면 sql문을 다 바꿔야할 수 있음

 

 

관계형 DB에는 상속관계는 없음 

근데 방법은 있음 - JOIN해서 가져오는 법  => 슈퍼타입 서브타입 관계 

 

 

DB에서 SQL을 작성하고 하면 할 것이 많음

 

근데 자바 컬렉션에 저장한다고 해보자

 

한 줄로 가능

 

자바 컬렉션을 사용하는 이유

더보기

연관관계

 

객체 VS 테이블

  • 객체는 참조 사용
  • 테이블은 외래키 사용  

객체는 테이블에 맞춰 모델링 함 

Team에 대한 참조가 아닌 id를 가지고 있음 

나중에 insert 문 쓸 때 편리하기 위해 

 

 

근데 객체다운 모델링이 아닐 수 있음!!!

객체다운 모델링은 참조로 연관관계 맺음

Member는 Team이라는 참조를 가지고 있음!!

class Member{

String id;
Team team;
String username;
    Team getTeam(){
        return team;
    }
}


class Team{
	Long id;
    String name;
}

 

 

 

멤버 꺼내고 > 멤버에서 팀 꺼내고..

객체를 DB에서 관리할 때는 패러다임의 불일치 때문에 관리하기가 번거로움

그러나 객체 안에서는 Java Collection에 저장하기 때문에 어차피 객체 안에서 동작하는 거니까 복잡한 변환 과정이 필요 없음 

 



객체 그래프 탐색
객체는 자유롭게 객체 그래프를 탐색할 수 있어야 함 

 

DB에 객체를 보관하다보면 생기는 문제점

내가 어떤 sql을 실행해서 이 멤버 객체를 만들었냐에 따라서 탐색 범위가 결정됨 

예) Member이랑 Team 조회 -> Order을 객체로 검색하면 null이 뜸 (DB 조회를 안했으니까)

DAO나 레포지토리에 어떻게 이걸 어디까지 세팅 해놓느냐에 따라 탐색 범위가 결정이 되어버림

그럼 엔티티에 대한 신뢰문제가 생김 (계층의 아키텍처) 

 

 

DAO를 모두 조회해야 null이 안뜨게 가져올 수 있을 것임

그러나 모든 객체를 미리 다 로딩할 수 없음 

 

그래서 다음과 같이 진행함

1. getMember()로 모든 멤버만 조회

2. getMemberWithTeam(); Member와 Team 조회

 

근데 더 많아지면 복잡해짐

그렇다고 모든 객체를 미리 로딩할 수 없음

 

계층형 아키텍처는 진저한 계층 분할이 어려움

 

비교하기

1. DB

 

memberId 100을 두번 넣어서 member1과 member2를 꺼내고 있음 

이 member1과 member2 인스턴스는 데이터는 같지만 다르다고 나옴

 

2. 자바 컬렉션에서 조회

데이터를 DB가 아닌 JavaCollection에 보관하고

같은 인스턴스를 조회하면 같은 참조로 나옴

 

 

객체답게 모델링 할수록 매핑 작업만 늘어남 그래서 객체 지향적인 프로그래밍을 포기했었음

객체를 자바 컬렉션에 저장하듯이 DB에 저장할 수 없을까?

 

자바 영속성 API (JPA)

 

JPA 소개

JPA ( Java Persistence API )

: 자바 진영의 ORM 기술 표준 

 

ORM (객체 관계 매핑)

: Object- relational mapping

: 객체랑 관계형 데이터베이스랑 맵핑해준다는 뜻 

- 객체는 객체대로 설계 & 관계형 데이터베이스는 관계형 데이터베이스대로 설계

- ORM 프레임워크가 중간에서 뭔가 다른 부분들끼리 매핑해줌

 

 

JPA는 애플리케이션과 JDBC 사이에서 동작

 

 

 insert 

 

조회

 

회원 객체를 저장한다고 할 때 멤버 객체를 회원 DAO에 넘기고

회원 DAO가 멤버 회원 객체 (멤버 엔티티)를 저장해줘라고 JPA에게 던지기만 하면

JPA가 알아서 분석을 해서 insert SQL 다 만들어줌 > JDBC API를 사용해서 Insert Query 까지 다 날려줌 

 

★ 중요! 패러다임의 불일치도 해결

더보기

패러다임의 불일치(Paradigm Mismatch)란, 두 개 이상의 서로 다른 프로그래밍 패러다임(예: 객체 지향 프로그래밍, 함수형 프로그래밍 등)을 사용할 때 발생하는 문제를 말합니다. 각 패러다임은 특정 방식으로 문제를 해결하려고 하며, 그 방식들이 서로 다를 때 이를 일컫는 용어입니다.

상속에 있어서의 문제도 해결해줌

 

그런 후 entity object를 다 만들어서 반환해줌

 

 

" JPA는 표준 명세이다 "

  • JPA는 인터페이스 모음
  • JPA 2.1 표준 명세를 구현한 3가지 구현체
  • 하이버네이트, EclipseLink,DataNucleus (거의 구현체로는 하이버네이트를 쓸 것임) 
  • JPA 표준 인터페이스에 하이버네이트 구현체를 쓴다. 

 

 

JPA를 왜 사용해야하는가?

  • SQL 중심적인 개발에서 객체 중심으로 개발
  • 생산성
  • 유지보수
  • 패러다임의 불일치 해결
  • 성능
  • 데이터 접근 추상화와 벤더 독립성
  • 표준 

사용 이유 1. 생산성 

update()는 없음

 

조건) 트랜잭션 안에서 데이터를 조회한 다음에 데이터를 변경해주면

트랜잭션이 끝난 시점에 자동으로 업데이트 쿼리가 DB에 나감 

 

사용 이유 2. 유지보수

JPA 사용 시 필드 변경 때 필드만 추가하면 됨 

과거 

 

JPA 적용 후 

 

 

사용 이유3. JPA는 패러다임의 불일치를 해결

 

이전에는 슈퍼타입과 서브타입에 둘다 데이터를 insert -> 이제는 jpa에서 알아서 insert 구문 2번 날려줌

이전에는 join해야했다면 JPA가 알아서 해줌

 

 

 

 

 

데이터 가져올 때는 쿼리가 아닌 '지연 로딩'으로 가져옴 

 

동일한 트랜잭션 안에서 조회한 엔티티는 같음을 JPA가 보장 

 

 

사용 이유 4. 성능 최적화 보장 

 

JPA 사용 시 가지게 되는 이점

1. 모아서 보내는 게 가능해짐

2. 중간에 뭐가 있으면 버퍼로 라이팅이 가능함 

3. 캐싱, 조회할 때 이미 조회된 것은 멀리 안가고 중간에 있는 것을 다시 반환해줄 수 있는 기능들 제공할 수 있음 

 

 

jpa가 이미 날린 쿼리는 중간에 들고 있다가 캐싱으로 가져옴 

같은 트랜잭션의 DB에서만 가능

 

데이터를 버퍼로 모음 > 커밋할 때까지 쿼리를 모두 모을 수 있음 > JDBC 배치 SQL 기능을 사용해서 한번에 네트워크로 보냄 (네트워크 통신 비용이 줄어듦)  

 

강의 도중 설명 나올 것임

지연 로딩 vs 즉시 로딩 

 

DB를 끌고 오는 것은 상황마다 다르기 때문에 지연로딩, 즉시로딩 지원

 

지연로딩 예시)

처음 멤버를 불러올 때는 멤버만 조회하고 'String teamName = team.getName();'으로

실제로 team을 쓸 때 team도 조회해 옴 

 

즉시로딩 예시) (세팅해두면 됨) 

처음 멤버를 불러올 때 멤버랑 팀 모두 조회

 

 

JPA = ORM

(객체랑 관계형 데이터베이스를 중간에 맵핑해주는 기술 - 객체 지향 + 관계형 데이터베이스 둘다 잘 알아야 함 ) 

 

 

ORM : 객체와 RDB 두 기둥 위에 있는 기술