- Today
- Total
개발하는 고라니
[Spring Boot] JPA 관련 용어 본문
JPA(Java Persisitence API)를 이용해 개발을 진행하다 보면 여러가지 단어가 등장하는데, 접해본 것 중 잘 모르겠는 몇 가지를 알아보고자 한다.
# ORM (Obejct Relational Mapping)
ORM은 객체지향과 관련이 있다. '객체지향 패러다임을 관계형 데이터베이스에 보존하는 기술'이라고 할 수 있다. 패러다임 입장에서 보면 '객체지향 패러다임을 관계형 패러다임으로 매핑해주는 개념'이라고 볼 수 있다. 객체지향에서 클래스는 관계형 데이터베이스의 테이블과 유사한 형태를 가지고 있다. 하나의 클래스는 다양한 타입(Type)의 데이터를 갖을 수 있는 하나의 데이터 집합체이고, 데이터베이스의 테이블 또한 여러 타입의 데이터를 저장할 수 있는 구조이다.
클래스(Class)와 테이블이 유사하듯. '인스턴스'와 '레코드' 또한 유사하다. 이와 같이 객체지향과 관계형 데이터베이스는 유사한 특징을 갖고 있으며, 이런 특징에 기반하여 '객체지향을 자동으로 관계형 데이터베이스에 맞게' 처리해주는 기법에 대해 아이디어를 내기 시작했고, 그것이 ORM의 시작이었다.
ORM을 사용하면 SQL 쿼리가 아닌 직관적인 코드(메서드)로서 데이터를 조작할 수 잇다.
# JPA (Java Persistence API)
JPA는 Java를 통해 데이터베이스와 같은 영속 계층을 처리하고자 하는 스펙이다. 영속(Persistence)라는 단어는 데이터를 '영구 저장'한다는 의미로 사용하며, 프로그램이 종료된 이후에도 계속 유지되도록 저장하는 것을 '영속화'라고 한다. 즉 데이터베이스에 데이터를 저장하는 것이다. JPA는 RDBMS에만 적용되는 규격이다.
JPA는 ORM을 Java에 맞게 사용하는 Java EE의 스펙이다. 따라서 ORM이 좀 더 상위 개념이 되며 JPA는 Java에 국한된 개념으로 볼 수 있다. JPA는 단순한 스펙이기 때문에 이를 구현하는 구현체마다 회사의 이름이나 프레임워크의 이름이 다르게 된다. 다양한 프레임워크가 있으나 가장 유명한 것은 'Hibernate'이다.
ORM > JPA > Hibernate > JDBC > Database
Spring Boot는 JPA의 구현체 중 'Hibernate'라는 구현체를 사용한다. 오픈소스로 ORM을 지원하는 프레임워크이다.
* spring-data-jpa
spring-data 프로젝트는 다양한 데이터 관리 솔루션(MySQL, MongoDB, redis 등)을 동일한 방식의 인터페이스로 사용할 수 있게 해주는 프로젝트이다. 즉, 한 번 배우면 여러 데이터 관리 솔루션을 같은 방식으로 다룰 수 있게 되어 학습 비용이 줄어들 수 있다. spring-data-jpa는 spring-data의 인터페이스로 'JPA'를 다룰 수 있게 해주는 프로젝트이다.
# Entity Object
JPA를 통해 관리하게 되는 객체. Entity Class는 Spring Data JPA에서 반드시 @Entity 어노테이션을 추가해야한다. 이 어노테이션은 해당 클래스가 엔티티를 위한 클래스이며 해당 클래스의 인스턴스들이 JPA로 관리되는 엔티티 객체라는 것을 의미한다.
또한 @Entity가 부여된 Class는 옵션에 따라 자동으로 테이블을 생성할 수 있다.
# Querydsl
다양한 데이터베이스는 모두 자신만의 데이터 검색을 위한 Query 문법을 갖는다. 단적인 예로 Oracle에서 페이징을 위해 Rownum을 이용하는 반면, MySQL에서는 Limit을 이용한다. 이렇게 다양한 데이터 쿼리 솔루션들의 쿼리 문법을 모두 익히는 것은 쉽지 않은 일이다. Queyrdsl은 몇 가지 데이터 관리 엔진에 대해 하나의 통일된 문법으로 쿼리를 작성할 수 있게 해준다.
그리고 중요한 특징은 쿼리 작성을 'Java'로 하며 Type-Safe하게 작성할 수 있다는 점이다. MyBatis를 사용하다 JPA를 사용하면 SQL에서 Java로 쿼리를 작성한다는 것이 매우 어색하고 어렵게 느껴질 수 있으나, 빠른 개발과 쉬운 디버깅을 할 수 있다는 장점이 있다.
Querydsl은 정적 타입을 이용해 SQL과 같은 쿼리를 생성할 수 잇도록 하는 프레임워크이다. JPQL처럼 문자열로 작성하거나, MyBatis처럼 XML 파일에 쿼리를 작성하는 대신, Querydsl이 제공하는 Fluent API를 이용해 쿼리를 생성할 수 있다. 즉, JPA에서 사용햇던 JPQL조차 사용하지 않는다.
단순 문자열(JDBC, MyBatis, JPQL)과 비교하여 Fluent API(Querydsl)를 사용할 때의 장점
- IDE의 코드 자동 완성 기능 사용
- 문법적으로 잘못된 쿼리를 허용치 않음
- 도메인 타입과 Property를 안전하게 참조할 수 있음
- 도메인 타입의 리팩토링을 더 잘할 수 있음
Querydsl은 Type-Safe하게 쿼리를 실행하기 위해 만들어졌고, 비결은 문자열이 아닌 메서드 호출로 쿼리가 수행됨이다.
# Type-Safe(형식 안정성)
어떠한 Operation 혹은 연산도 정의되지 않은 결과를 내놓지 않는 것. 즉, 예측 불가능한 결과를 내지 않는 것을 뜻한다. 예를 들어
1 + "1"의 연산이 가능하거나, 문자열에 숫자 1을 할당하는 것이 가능하다거나 한다는 것을 알면 비논리적이라고 볼 수 있다.
Type-Safe란 위와 같이 연산이나 조작에 있어 논리적이지 않은 것에 대해 엄격히 체크하여 Runtime시 이로 인한 오류가 발생하지 않도록 하는 것이다.
Type-Safe하다고 알려진 언어에서는 보통 이를 컴파일 타임에 에러처리를 해주지만,
Type-Safe하지 않은 언어(예: Javascript)에서는 이를 적절히 처리한다.
일반적으로 C#, Java와 같은 언어를 일반적으로 Type-Safe하다고 한다.
소프트웨어의 요구사항은 계속해서 바뀌고 개발 도중에는 데이터베이스 스키마도 수시로 변경될 가능성이 있다. 그 때마다 관련 쿼리가 문제없는지 확인하는 과정은 실수하기가 쉽다. Querydsl을 사용한다면 Entity Domain 객체에 수정이 일어나면 관련된 쿼리 코드에 컴파일 에러가 발생하게 된다. 컴파일 에러가 발생하는 코드를 수정하고 컴파일 에러가 없어진다면 적어도 소프트웨어 동작 중 쿼리가 잘못되어 에러가 발생하는 경우는 없다고 봐도 무방하다. 이를 Type-Safe하다고 할 수 있다.
# JPQL (Java Persistence Query Language)
JPQL은 SQL과 비슷한 문법을 가진 객체지향 쿼리이다. JPQL의 탄생 배경은 JPA에서 제공하는 메서드 호출만으로 섬세한 쿼리 작성이 어렵다는 것에 있다. 따라서 여러 조건을 통해 검색을 하는 방법이 요구되었고, JPQL이 개발되었다.
- JPQL의 특징
- 테이블이 아닌 객체를 검색하는 객체지향 쿼리
- SQL을 추상화했기 때문에 특정 벤더(Vendor)에 종속적이지 않음
- JPA는 JPQL을 분석하여 SQL을 생성 후 데이터베이스에서 조회
Spring-data는 실행할 수 있는 쿼리를 정의하는 다양한 방법을 제공하는데, 이 중 하나는 @Query 어노테이션이다. 이 어노테이션을 이용하여 JPQL 및 Native SQL 쿼리를 모두 실행할 수 있다.
Spring Data Repository 메소드를 실행하기 위해 우리는 메서드에 @Query어노테이션을 달 수 있고, 이 때 어노테이션의 속성으로 JPQL 또는 SQL이 포함된다.
@Query 어노테이션에 들어갈 field 이름은 '테이블'이 아닌 Entity 클래스와 Entity의 속성 이름이다. 즉 엔티티 클래스 이름이 Location이고, Table명이 locations이면 Location을 사용해야 한다. field 이름도 Entity의 property가 들어가야지 Table의 Column이 들어가면 안된다.
# Query Method
쿼리 메서드는 메소드 이름만으로 쿼리를 생성하는 기술이다. 인터페이스에 메소드만 선언하면 해당 메소드의 이름으로 JPQL 쿼리를 생성해준다.
예)
Optional<A> findByName(String name);
리턴타입 접두어 {도입부} By 프로퍼티 {(And, Or) 조건식} {정렬조건}
- 리턴 타입 : List<Entity>, Entity, Optional<Entity>, Page<Entity>
- 접두어 : find, get, count, delete
- 도입부 : Distinct, First, Top
- 프로퍼티 : 해당 Entity의 프로퍼티
- 조건식 : IgnoreCase, Between, GreaterThan, LessThan, Like, Contains
- 정렬조건 : OrderBy(프로퍼티), Asc/Desc
# References
'Framework > Spring Boot' 카테고리의 다른 글
[Spring Boot] Security 로그인 커스터마이징 (0) | 2021.03.13 |
---|---|
[Spring Boot] Security 사용자 정보 출력 in Thymeleaf (0) | 2021.03.05 |
[Spring Boot] @MappedSuperClass (0) | 2021.01.14 |
[Spring Boot] JPA 동적 검색 (QueryDsl) (1) | 2021.01.13 |
[Spring Boot] Gradle의 Querydsl 설정 (1) | 2020.12.27 |