[Spring Database] JPA
JPA를 사용하기에 앞서 JPA가 도입된 배경에 대해 살펴보자.
애플리케이션을 개발할 때는 Java와 같이 객체지향언어를 사용한다.
또, 데이터베이스는 Oracle / MySQL 과 같은 관계형 데이터베이스를 사용한다.
즉 애플리케이션은 객체로 관리하고, 데이터는 관계형 데이터베이스에 저장한다.
그런데, 데이터베이스는 SQL만 받아들이고 실행할 수 있는데.. 여기서 문제가 발생한다.
SQL 반환값을 자바 객체로 변환해야 하고.무엇을 개발하든 SQL에 의존 할 수 밖에 없다.
객체에 멤버 변수가 추가된다면? SQL도 추가된 변수에 따라 모두 수정 해 줘야 한다.
또, 객체지향과 관계형 데이터베이스의 패러다임이 다르다는 문제가 있다.
객체에는 상속이라는 개념이 있어 설계할 때 유용하게 사용할 수 있지만, 테이블에는 상속이 없다.
(슈퍼타입과 서브타입이라는 개념이 있지만, 상속과는 다르다)
위에서 ALBUM 데이터를 insert 할 때는 ALBUM과 ITEM 데이터에 각각 insert 해 줘야 한다.
ALBUM 데이터를 조회 할 때도 연관된 테이블을 join시키고 각각의 객체를 생성하고... 너무 복잡하다.
따라서 데이터베이스에 저장하는 객체에는 상속 개념을 사용하지 않는다.
그냥 자바 코드만 사용해서 객체를 조회하거나 입력하는 작업은 매우 쉬운데, 이 작업을 SQL로 바꿔서 수행하려니 복잡해진다.
이 외에도 객체지향을 적절하게 사용한 자바 코드만 사용하면 쉽게 처리 할 수 있는 작업을 관계형 데이터베이스와 연계시키면 힘들어지는 경우가 많다. (객체 그래프 탐색, 모델링, 엔티티 신뢰 문제 , 값 비교 문제 등)
관계형 데이터베이스를 객체답게 모델링 할 수록 귀찮은 매핑 작업만 늘어나는데.. 객체를 자바 컬렉션에 다루듯 데이터베이스에도 간단하게 저장 할 수는 없을까?
라는 생각에서 나온 기술이 JPA (Java Persistence API) 이다.
JPA는 자바 진영의 ORM 기술 표준으로 사용된다. (JPA가 인터페이스로 제공되고, 여러 가지 구현체가 있다는 뜻이다)
ORM (Object - Relational - Mapping)
지금까지 계속 문제됐던 객체와 관계형 데이터베이스를 매핑하는 기술이다.
객체는 객체처럼 설계하고, 관계형 데이터베이스는 관계형 데이터베이스대로 각각의 장점을 살려서 설계하고, ORM 프레임워크가 중간에서 둘을 매핑해주는 개념이다.
JPA는 애플리케이션과 JDBC 사이에 위치한다.
애플리케이션은 JPA를 사용하고, JPA는 내부에서 JDBC API를 사용해 SQL을 보내고 결과를 반환받는 방식으로 동작한다.
JPA를 사용해서 저장하는 예시를 살펴보자.
여기서 MemberDAO는 Repository로 생각하면 된다.
리포지토리에서 JPA에 멤버 객체를 넘겨주면 JPA가 멤버 객체를 분석하고 SQL을 생성해서 JDBC API에게 전달한다.
여기서 패러다임의 불일치가 해결되는데, 이 부분은 조금 뒤에 살펴보자.
JPA를 사용하면 자바 컬렉션을 사용하듯 데이터베이스를 다룰 수 있다.
JPA는 인터페이스의 모음으로, 오픈소스 진영에서 JPA 를 구현해서 사용한다. (대부분 Hibernate)
JPA를 사용하면 SQL을 JPA가 대신 만들어주기 때문에 SQL 중심적인 개발에서 벗어나 객체 중심적인 개발을 할 수 있고, 이에 따라 생산성을 높이고 유지보수도 쉬워지는 등 여러 가지 이점이 있다.
가장 큰 이점은 패러다임의 불일치를 해결하는 부분이다.
다시 앨범 예시로 돌아가보자.
앨범을 저장하려면 SQL을 앨범에 한 번, 아이템에 한 번. 총 2번 날려야 한다.
개발자가 jpa.persist(album) 으로 저장을 요청하면, JPA는 INSERT INTO ITEM .. / INSERT INTO ALBUM ... 으로 적절하게 SQL을 만들어서 처리해준다.
저장 외에도 조회, 객체 그래프 탐색, 엔티티 신뢰 등 앞에서 살펴본 모든 문제를 JPA가 해결해준다.
JPA는 자바 컬렉션과 같다고 생각하면 된다. 개발자가 JPA를 자바 컬렉션처럼 사용하면, JPA 내부에서 관련 문제를 모두 해결해준다.
추가로, JPA의 위치. 애플리케이션과 JDBC 사이에 있는 그 위치 덕분에 여러 가지 성능 최적화를 진행할 수 있다.
1. 캐시
둘 사이에 새로운 계층으로 존재하기 때문에 캐시를 통해 데이터를 저장 해 놓고 이미 저장된 데이터에 대해서는 빠르게 응답할 수 있다.
처음에 jpa.find를 실행하면 SQL을 보내지만, 두 번째에 같은 식별자로 jpa.find를 실행하면 캐시가 적용된다.
2. 쓰기 지연
여기서 세 개의 SQL을 모았다가 트랜잭션을 커밋하는 순간 한 번에 보낸다.
네트워크 통신이 한 번만 이루어져서 성능이 향상된다.
3. 지연 로딩과 즉시 로딩
지연 로딩은 객체가 사용 될 때 로딩하는 작업을 말한다.
find(memberId) 로 멤버만 가져왔기 때문에 아직 team은 불러올 수 없다.
team을 사용할 때 JPA는 내부에서 team을 불러서 넣어준다.
실제로 team객체를 사용 할 때 까지 로딩을 미룬다고 해서 지연 로딩이라고 부른다.
멤버를 사용할 때 team도 같이 사용한다면 SQL을 한 번에 보내는 편이 합리적이다.
맨 처음에 객체를 가져올 때 필요한 객체를 싹 다 가져온다고 해서 즉시 로딩이라고 부른다.
기본적으로 지연 로딩을 사용하고, 최적화가 필요하다고 생각되는 부분을 즉시 로딩으로 바꿔서 처리하면 된다.
JPA가 SQL을 작성해주지만.. 그래도 핵심은 데이터베이스 시스템과 SQL이다.
통계 작업을 수행하거나 성능에 민감한 애플리케이션 개발 시 데이터베이스 시스템에 입각해 SQL을 튜닝해야 하니
JPA만 공부하고 SQL은 공부하지 않겠다는 생각은 버리자.
'Spring > Spring Database' 카테고리의 다른 글
[Spring Database] Spring Data JPA (0) | 2022.09.11 |
---|---|
[Spring Database] JPA 적용 (0) | 2022.09.10 |
[Spring Database] MyBatis (0) | 2022.09.09 |
[Spring Database] 데이터베이스 테스트 (2) | 2022.09.07 |
[Spring Database] JdbcTemplate (0) | 2022.09.06 |
댓글
이 글 공유하기
다른 글
-
[Spring Database] Spring Data JPA
[Spring Database] Spring Data JPA
2022.09.11 -
[Spring Database] JPA 적용
[Spring Database] JPA 적용
2022.09.10 -
[Spring Database] MyBatis
[Spring Database] MyBatis
2022.09.09 -
[Spring Database] 데이터베이스 테스트
[Spring Database] 데이터베이스 테스트
2022.09.07