JPA가 필요한 이유와 문서화

bw1611·2023년 8월 28일

📕 JPA 란?


프레임 워크를 통해서 DB에 쉽게 접근할 수 있는 통로 ( 인터페이스 )
기존의 마이바티스와 같은 ORM이랑 근본적인 차이는 한번 데이터가 바인딩된 이후 추가적인 쿼리 부분이 없더라도 테이블 데이터에 접근이 가능하다는 점이다.
JPA는 성능 이슈 때문에 필요한 데이터를 효과적으로 가져오는 것이 필요하다.

ㅇ JPA의 구현체 Hibernate

  • hql이라는 강력한 쿼리 언어를 포함
  • 객체 지향적이며 객체를 통한 데이터 바인딩을 쉽게 데이터를 다룬다.
  • EntityManagerFactory, EntityManager, EntityTransaction 등을 상속받아 구현

장점

  • 객체 지향적이라 객체에 집중하여 개발 가능
  • 유지보수 및 생산성이 좋음
  • DB교체가 쉽고 빠름

단점

  • 초기 진입장벽이 존재함

ㅇ JPA의 구현체 OpenJPA

  • 아파치에서 만든 도구
  • JAVA EE 5 사양에서 가능한 100% 오픈 소스 구현

장점

  • 좋은 문서 풀을 제공
  • 사용하기 용이

단점

  • 약간의 버그가 있음

ㅇ JPA 인터페이스의 계층 구조

ㅇ findAll() : 해당 엔티티 테이블에 있는 모든 데이터를 조회
ㅇ save() : 대상 엔티티를 DB에 저장
ㅇ saveAll() : Iterable 가능한 객체를 저장
ㅇ delete() : 데이터베이스에서 대상 엔티티 삭제

JPA Repository는 위와 같은 다양한 기능이 정의된 인터페이스를 상속 받게 된다. 이 인터페이스를 통해 우리는 단순 CRUD 외에 다양한 기능을 수행할 수 있으며 Paging 이나 Sorting 같은 역할도 수행할 수 있다.

ㅇ JPA 관련 어노테이션
1, @Modifying

  • @Query 어노테이션을 통해 작성된 Insert, Update, Delete 쿼리에서 사용되는 어노테이션
  • clearAutomatically, flushAutomatically 속성을 변경할 수 있으며 주로 벌크 연산과 같이 이용

벌크연산이란?
단건 Update, Delete 연산을 제외한 다건의 Update, Delete 연산을 하나의 쿼리로 하는 것을 의미

2, @Query

  • 일반 SQL 및 JPQL로 쿼리를 작성 가능

3, @Repository

  • repository를 사용하겠다고 명시하는 어노테이션

4, @Enumerated

  • 자바에서 Enum 타입을 매핑해주기 위하여 빠르게 orderBy에 추가해주는 기능

5, @Builder

  • 빌더 패턴을 자동으로 생성해주는 어노테이션이다. 객체 생성자의 인자 개수가 많아지는 경우 코드를 작성하기 힘들어지는 문제를 해결하기 위해 사용되는 패턴 중 하나이다.
    생성자 대신 빌더를 이용하여 객체를 생성할 수 있다.

6, @Data

  • @Getter / @Setter / @RequiredArgsConstructor / @ToString / @EqualsAndHashCode / @Value 가 포함되어 있는 어노테이션이다. 하지만 @Data에는 단점이 존재하는데 @Setter 어노테이션이 포함되어 있다는 것이다. Setter의 단점을 보기 위해서는 위에 있는 @Setter를 확인해보자.

7, @Entity

  • DB에 테이블로 선언되기 위한 어노테이션

8, @Transactional

  • 클래스 또는 메서드에 붙을 때, Spring은 해당 메서드에 대한 프록시를 만든다.
  • 수행하는 작업에 대해 트랜잭션 원칙이 지켜지도록 보장해주는 것으로 직접 객체를 만들지 않고, 선언만 해도 이 과정이 적용되는 선언적 트랜잭션이라고 불린다.

9, @EnableJpaRepositories

  • JpaRepository에 대한 설정저보를 자동적으로 로딩하고 이 정보를 토대로 Repository 빈을 등록하는 역할을 한다.
  • @SpringBootApplication 어노테이션 안에 이미 등록되어 있어 스프링 부트에서는 따로 어노테이션을 추가할 필요는 없다.

10, @Configuration

  • 수동으로 스프링 컨테이너에 빈을 등록하는 방법
  • 직접 제어가 불가능한 라이브러리를 빈으로 등록할 때 불가피하게 사용한다.
  • 1개 이상의 @Bean 을 제공하는 클래스의 경우 반드시 @Configuration을 명시해 주어야 싱글톤이 보장된다.

11, @PersistenceContext

  • EntityManager를 빈으로 주입할 때 사용하는 어노테이션이다.
  • EntityManager는 여러 쓰레드가 동시에 접근하면 동시성 문제가 발생하기 때문에 공유해서는 안된다. 하지만 @PersistenceContext으로 EntityManager를 주입받아도 동시성 문제가 발생하지 않는다.

Hibernate와 Spring Data JPA의 차이


Hibernate는 JPA 구현체이며 Spring Data JPA는 사용하기 편리하게 한 모듈이라고 생각하면 편하다.

ㅇ Spring Data JPA의 쿼리 메서드

public interface ReviewJPARepository extends JpaRepository<Review, String>{
	List<Review> findByTitle(String title);
}

위의 findByTitle은 sql "select u from Review u where u.title =?" 와 같은 문법이라고 보면 된다.
이렇게 JPA 쿼리 메서드는 규칙이 존재하는데 이 규직은 공식문서 또는 검색을 하면 쉽게 찾아볼 수 있다.

ㅇ JPQL

String jpql = "select c from review c";
List<Review> result = em.cretaeQuery(jpql, Review.class).getResultList();
  • jpql은 명칭은 대소문자를 구별하며 엔티티 이름을 설정한 명칭을 설정해주어야 한다.. jpql에서 별칭(c)은 필수이다. 즉 review와 Review는 다른 것으로 판단한다. select, from 같은 예약어는 구별하지 않는다.

ㅇ TypedQuery

public static void typedQuery(EntityManager em) {
	String jpql = "SELECT b FROM Book b ";
	TypedQuery<Book> query = em.createQuery(jpql, Book.class);
	
	List<Book> bookList = query.getResultList();
	for( Book book : bookList) {
		System.out.println(book.getTitle());
	}
}

모든 책 리스트를 조회하는 쿼리이다. EntityManager 객체에서 createQuery() 메서드를 호출하면 쿼리가 생성된다.

  • TypedQuery는 반환되는 엔티티가 정해져 있을 때 사용하는 타입이다.
  • TypedQuery 객체의 getResultList() 메서드를 호출하면 작성한 JPQL에 의해 데이터를 검색하며, List 타입으로 반환합니다.

ㅇ QueryDsl
기존에 쿼리들은 문자열이기 때문에 문법 오류를 발견하기가 쉽지 않다는 단점이 있었다. 하지만 Query DSL은 컴파일 시점에서 문법 오류가 발견이 가능하며 코드는 JPQL과 많이 유사하다, 또한 동적 쿼리를 작성 가능하다.

  • gradle
	implementation "com.querydsl:querydsl-jpa:${queryDslVersion}"
	annotationProcessor "com.querydsl:querydsl-apt:${queryDslVersion}"
JPAFactoryQuery query = new JPAQueryFactory(em);
QReview m - QReview.review;

List<Review> list = query.selectFrom(m)
		.where(m.cnt.gt(10))
        .orderBy(m.cnt.desc())
        .fetch()l

위의 Query DSL 쿼리는 select m from Review m where cnt > 10 이랑 동일한 코드이다.

ㅇ JPA 쿼리에 대한 성능 최적화에 대해서
1, 느린 쿼리 개선

  • DB
    2, Fetch 타입의 정확한 선택
  • 매핑 관계에 있어서 Lazy, Eager를 잘못선택한다면 수행되는 쿼리수가 늘어남
  • DB 튜닝에 있어서 쿼리의 숫자를 줄이는 방식이랑 동일한 개념
    3, Join 대신 Fetch Join 사용
    - 조인은 두가지 테이블을 읽기 때문에 성능이 느려질 수 있다. 따라서 특정한 영역 데이터를 먼저 가져와서 조인하는 방식이 유리함
    4, 데이터 베이스가 어려운 일 작업하기
    - 간혹 서비스를 구현함에 로직 및 구현 부분에서 데이터를 가져와서 처리하는 경우가 있는데 DB가 할 수 있는 영역들은 DB의 쿼리를 활용해서 처리하는 것이 더 빠르다.
    5, 최대 절전 모드 활용
    - 하이버네이트 세션의 1단계 세션 캐시 활용, 2단계 캐시의 경우 공유 캐시 모드를 설정해야 활용이 가능

📗 Spring REST Docs와 Swagger


ㅇ API
프로토콜 집합을 사용하여 두 소프트웨어 구성 요소가 서로 통신할 수 있게 하는 메커니즘

ㅇ API 문서를 만드는 이유?

  • 제공자와 사용자의 불필요한 커뮤니케이션을 줄이기 위하여 API를 만들어 사용방법을 공유하고 협의할 수 있다.

ㅇ Spring REST Docs

  • RestFul 서비스에 대한 정확하고 읽기 쉬운 문서를 생성하도록 돕는 것이 목적
  • 테스트를 통하여 API의 문서 생성
  • 스니펫의 조합으로 API 문서 커스터마이징
  • 간결한 적요으 다양한 생성 방법

장점

  • 별도의 HTML, PDF 파일로 API 문서 자동 생성이 가능
  • Request/Response 테스트를 통하여 API 문서의 신뢰도 상승
  • API 변경에 따른 API 문서 최신화 보장

ㅇ Swagger

  • API 테스트 UI 제공
  • 어노테이션을 통한 간단한 작업이 가능
  • 테스트 코드 없이 문서화가 가능하다
  • UI가 알아보기 쉽게 되어있음

ㅇ OpenAPI Spec

  • REST API에 대한 설명, 생성, 사용 및 시각화 하기 위한 인터페이스 파일의 사양
  • Swagger 프레임워크의 일부였지만 오픈소스로 전환
  • YAML 또는 JSON 으로 작성 가능
profile
Java BackEnd Developer

0개의 댓글