본문 바로가기

2023년/ETC💁‍♂️

요약 간단정리 spring data jpa, jpa, hibernate,orm, jdbc api, jdbc driver, dbms

비유는 정의를 설명하진 못한다. -궤도

안될과학 유튜브 시청하다 이런 멘트를 흘깃 들어서 좋은 말 같아 적어본다.

이 글에서도 이해를 위한 적절한 비유표현법을 사용할 것이며, 완벽한 정의는 아닌점 유의하고 읽어주시면 감사하겠습니다. 정확한 내용은 공식문서 참고 필수!

 

개요

spring boot 로 프로젝트를 하다보니 spring과 관련된 기술을 사용하는데 이게 뭐지 하고 넘어가던 부분들이 많았다.

userRepository 에서 User 엔티티를 찾는 모오오습
우리는 interface 에 메소드를 정의만 해서 사용했다.

프로젝트 안에서 repository 라는 인터페이스를 사용하면서 안에 메소드를 정의 해주는 것만으로 사용할 수 있었는데, 어떻게 이게 가능한 것일까에 대한 생각을 하진 못하고 아 그렇구나 하고 사용했었다.

하이버네이트?

application.yml 안에 버젓이 하이버네이트라고 정의해둔 내용이 있었다. 그럼 하이버네이트는 뭐고 JPA는 무엇일까

예전 프로젝트하면서 JDBC Template를 사용하면서 데이터베이스와 연결한 기억이 있다. 대충 소스가 커넥션 연결하고 예외처리하고 사용 다했으면 끊어주고 등등 많은 작업들이 동반되었었다. 이후에는 SpringBoot 를 통해서 Datasource를 연결하고 JpaRepository를 통한 메소드 쿼리문을 작성해서 사용했었는데, spring data jpa 를 사용하고 역시 개발자들은 편한걸로 만드는구나 생각이 들었다.

 

각설하고, 아래 그림을 보고 이해했던 과정을 정리해보겠습니다.

 

사진 한장으로 해결하기
이해하러 가보자!


Persistence Layer

실제 DB가 있는 계층

MySQL, Oracle, PostgreSQL 등등 실제 데이터가 있는 장소


JDBC Implementations

 

JDBC (Java DataBase Connectivity) 란

자바에서 데이터베이스 접속할 수 있도록 하는 자바 API
자바에서 데이터베이스 다루기위한 약속이락 생각하면 편하다.

JDBC API를 통해서 DB 에 접근해 데이터를 요리한다!

 JDBC 기본적인 사용에 관한 소스코드

더보기
package test;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class SelectTest {
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        try{
            // 1. 드라이버 로딩
            Class.forName("com.mysql.jdbc.Driver");

            // 2. 연결하기
            String url = "jdbc:mysql://localhost/dev";
            conn = DriverManager.getConnection(url, "dev", "dev");


            // 3. 쿼리 수행을 위한 Statement 객체 생성
            stmt = conn.createStatement();

            // 4. SQL 쿼리 작성
            // 주의사항
            // 1) JDBC에서 쿼리를 작성할 때는 세미콜론(;)을 빼고 작성한다.
            // 2) SELECT 할 때 * 으로 모든 칼럼을 가져오는 것보다
            //   가져와야 할 칼럼을 직접 명시해주는 것이 좋다.
            // 3) 원하는 결과는 쿼리로써 마무리 짓고, java 코드로 후작업 하는 것은 권하지 않음
            // 4) 쿼리를 한 줄로 쓰기 어려운 경우 들여쓰기를 사용해도 되지만 띄어쓰기에 유의 !!
            String sql = "SELECT name, owner, date_format(birth, '%Y년%m월%d일' date FROM pet";


            // 5. 쿼리 수행
            // 레코드들은 ResultSet 객체에 추가된다.
            rs = stmt.executeQuery(sql);

            // 6. 실행결과 출력하기
            while(rs.next()){
                // 레코드의 칼럼은 배열과 달리 0부터 시작하지 않고 1부터 시작한다.
                // 데이터베이스에서 가져오는 데이터의 타입에 맞게 getString 또는 getInt 등을 호출한다.
                String name = rs.getString(1);
                String owner = rs.getString(2);
                String date = rs.getString(3);

                System.out.println(name + " " + owner + " " + date);
            }
        }
        catch( ClassNotFoundException e){
            System.out.println("드라이버 로딩 실패");
        }
        catch( SQLException e){
            System.out.println("에러 " + e);
        }
        finally{
            try{
                if( conn != null && !conn.isClosed()){
                    conn.close();
                }
                if( stmt != null && !stmt.isClosed()){
                    stmt.close();
                }
                if( rs != null && !rs.isClosed()){
                    rs.close();
                }
            }
            catch( SQLException e){
                e.printStackTrace();
            }
        }
    }
}

회사별로 과정에 대한 내용들을 각자 만드십쇼

위 접은 글에 대한 코드를 보면 커넥션, 문장, 결과응답 등 일일히 개발자가 직접 작성하는 노고가 들어간다.

표준 interface에 대한 구현체를 각 회사별로 만들었다 보니 우리는 JDBC를 사용할 때 내가 사용한 DB 별로 드라이버만 교체해주면 된다.

 

 

JDBC 구현부로 JDBC 인터페이스를 각 회사별로(DBMS) 세부 데이터를 맞춘 구현체이다.

예를들어 MySQL DB 이면, MySQL JDBC 드라이버 / Oracle DB 이면, Oracle JDBC 드라이버

표준 인터페이스 기능(API) ( 1. 커넥션 연결, 2. SQL 전달, 3. 결과 응답 ) 에 대한 구체적인 내용이라 생각하면 된다.

  • Connection (DB 연결)
  • Statement (SQL 문장 실행)
  • PreparedStatement (동일 문장 여러번 반복수행 시 사용 객체)
  • ResultSet (쿼리의 결과값)

SpringBoot 에서 MySQL 드라이버로 설정
Oracle 드라이버

SpringBoot 에서도 다음과 같이 yml 파일을 수정해 드라이버만 교체해주면 JPA 에서 드라이버에 맞는 jdbc를 사용하게 된다.


JDBC Interfaces

JDBC Interfaces란

jdbc를 사용하기 위한 약속들을 의미하는데,

 

JDBC Basic APIS

공식문서를 참고해보면 java에서 명시한 인터페이스와 클래스를 참고할 수 있다.

https://www.javaguides.net/2018/10/java-jdbc-api-overview.html

 

Java JDBC API Overview

JDBC allows a Java application to connect to a relational database. The major databases are supported such as Oracle, Microsoft SQL Server, DB2 and many others. The database can be located on the same local machine as in the application. It can also be loc

www.javaguides.net

 

JDBC API는 두 부분으로 구성됩니다. 첫 번째 부분은 애플리케이션 프로그래머가 사용하는 JDBC API입니다. 두 번째 부분은 데이터베이스 서버(JDBC 드라이버)에 연결하기 위한 저수준 API입니다.

 JDBC API의 첫 번째 부분은 java.sql 패키지의 표준 Java 패키지의 일부입니다. Java 프로그래밍 언어를 사용하여 데이터 소스(일반적으로 관계형 데이터베이스)에 저장된 데이터에 액세스하고 처리하기 위해 java.sql 패키지 API를 사용합니다.
 두 번째 부분은 JDBC 드라이버(네 가지 유형의 JDBC 드라이버가 있음)입니다. JDBC 드라이버는 특정 데이터베이스를 대상으로 하는 JDBC 인터페이스를 구현하는 Java 클래스 집합입니다. JDBC 인터페이스는 표준 Java와 함께 제공되지만 이러한 인터페이스의 구현은 연결해야 하는 데이터베이스에 따라 다릅니다. 이러한 구현을 JDBC 드라이버라고 합니다.

Datasource를 알기 전

Connection Pool

커넥션 풀에서 DB Connection 에 관한 객체들을 다뤄준다.

커넥션 오브젝트

앞서 위에서 작성한 예문에서 커넥션에 관한 Object를 봤을 것이다.

CP(Connection Pool) 이 없었을땐 DB와 상호작용한 후 연결과 끊고를 반복했다.

연결과 끊고 는 작업시간의 길이가 좀 걸린다. (성능적으로 보았을때 매우 민감한 요소)

그래서,

객체를 미리 생성해서 그걸 가져다 사용하고, 반납하는 방식으로 사용하는 것이다.

이미 생성된 인스턴스를 사용하기 때문에 메모리도 효율적으로 쓸 수 있고, 속도도 더 빨라지게 된다.

 

이것에 대한 관리를 커넥션 풀에서 하게된다.

CP 의 선언은 아래와 같이 이루어진다. 데이터소스 구성과 비슷하다.

  • HikariCp: 스프링부트 2.0 이후에 표준이 된 DataSource. 오픈소스이고 안정적이며 빠르다.
  • SpringBoot 에서도 프로그램 동작간 히카리풀이 동작함을 확인할 수 있다.

프로젝트 내 CP동작

 

DataSource 란

DB 연결 정보를 저장하고, Connection을 생성하고, Connection Pool에 등록하고, 관리하는 역할을 하는 것이 바로 DataSource이다.

 

간단히 DataSource는 DB Connection 을 관리하는 인터페이스라고 생각하면 된다.

 

SpringBoot 에서 Datasource, yml 에서 쉽게 확인

데이터소스 빈을 구성할때 아래와 같은 내용으로 구성되며

@Bean 
public  DataSource dataSource() {
     final DriverManagerDataSource dataSource =  new  DriverManagerDataSource ();
    dataSource . setDriverClassName(env . getProperty( " jdbc.driverClassName " ));
    dataSource . setUrl(env . getProperty( " jdbc.url " ));
    dataSource . setUsername(env . getProperty( " jdbc.user " ));
    dataSource . setPassword(env . getProperty( " jdbc.pass " ));
    return dataSource ;
}

JDBC 내 getConnection() 호출에서 사용되게 되며, 이후 JDBC 드라이버에서 다루게된다.

 

아까 위에서 표준인터페이스에 대한 메소드들을 볼 수 있었고, 이런 jdbc기술을직접적으로 다루고 싶으면

Java JdbcTemplate을 찾아보자.

 


 

Object Relational Mapper (ORM)

ORM 이란? 

객체와 관계형데이터베이스의 데이터를 자동으로 매핑(연결) 해주는 것 ( 객체와 RDB 매핑 기술 )

객체지향 프로그래밍 - 클래스 ( Java )

관계형 데이터베이스 = 테이블 ( MySQL )

이 둘의 패러다임 불일치를 해결해주는 역할.

 

패러다임 불일치란 ( Java 와 MySQL 데이터 저장 시 문제 점)

1. 상속관계 

implements와 extends 는 DB 에서 어떻게 구현할 것인가?

2. 연관관계

class User {
    private Long id;
    private Team team;
	// 객체는 참조를 통해서 다른 객체와 연관 가능
}

User Table

Long id
Long team_id

Team Table

Long id
String name

DB는 외래키를 활용한 Join 사용

 

3. 그래프탐색

User.getTeam().getName() 

. 을 이용한 그래프 탐색이 가능함

DB는 Join을 활용해야됨 ( 실 사용은 지연로딩 )

4. 비교

객체 : 주소값 비교(==), 내부값 비교(equals())

DB : 기본키의 비교

 

 

이런 패러다임 불일치를 해결해주는 것이 바로 ORM 기술 중 JPA가 있다.

 

JPA란?

Java Persistence API 의 약자로, Java ORM 기술에 대한 표준 명세 라고 정의한다.

쉽게 말해 Java 에서 사용하는 ORM 기술

다음과 같은 특징이 있다

  • JPA가 제공하는 API 사용 시 객체를 DB를 관리할 때, 개발자가 SQL을 직접 작성하지 않아도 된다.
  • JPA가 개발자 대신 적절한 SQL을 생성해 DB 전달하고 객체를 자동 Mapping 해준다.
  • JPA는 내부적으로 JDBC API 를 사용하는데, 개발자가 직접 사용시 효율성이 떨어진다.

즉, JPA 사용시 개발자가 생각해야될 것을 덜어줌으로써, 생산성을 크게 높인다.

 

JPA를 정의한 javax.persistence 패키지안 내용을 보면 핵심이 EntityManager

EntityManager 를 통해서 데이터 영속성을 관리한다.

package javax.persistence;

import ...

public interface EntityManager {
    public void persist(Object entity);
    public <T> T merge(T entity);
    public void remove(Object entity);
    public <T> T find(Class<T> entityClass, Object primaryKey);
    // More interface methods...
}

 

JPA vs Hibernate

JPA는 이런 ORM 기술에 대한 인터페이스

Hibernate는 인터페이스에 대한 구현체

JPA 와 Hibernate 관계

우리는 SpringBoot 에서도 Hibernate를 JPA 구현체로 사용하고 있다.

JPA 구현체 중 다양한 것들이 있는데 대표적인것은 하이버네이트이다. (꼭 하이버네이트만 사용할 필요는 없음)

hibernate 사용했었네;

 

JPA vs Spring Data JPA 

JPA를 쉽고 편하게 사용하기 위해 제공하는 Spring 기술

위에서 JPA 같은 경우 EntityManager를 다룬다고 했는데, 직접 다뤄본적은 김영한님 스프링부트 ORM 강의 영상 초반에 직접 persist() 메소드와 transaction 관련해 다룰때 그때 말고 본적이 없다.

Spring Data JPA는 개발자가 JPA를 쉽게 다룰 수 있게 Repository 인터페이스를 제공함으로, 정해진 규칙대로 메소드를 입력하면 Spring이 알아서 적합한 쿼리를 날리는 구현체를 만들어 Bean으로 등록해준다.

 

즉, 알맞게 메소드를 짜면 쉽게 데이터를 다룰 수 있다는 뜻이다.

프로젝트에서 자주보던 녀석 repository

프로젝트 내에서 repository라는 인터페이스 내 정해진 규칙대로의 메소드를 입력하면 Spring에서 알아서 쿼리문을 만들어 개발자가 편하게 사용할 수 있다.

  • findById() - id를 통해서 User 에 대한 객체를 가져온다
  • save() - 데이터 영속화
  • remove() - 데이터 삭제

Spring Data JPA, JPA, Hibernate 관계

위 글을 읽고 이 사진을 참고하면 이해가 쏙쏙 될 것입니다! 이 3가지 개념을 꼭 유념하시면서 개발을 하시기 바랍니다.


Application Modules

우리가 직접적으로 사용하는 인텔리제이 안 프로젝트에서 SpringBoot 내 Repository를 사용해봤을 것이다.

JpaRepository 인터페이스를 만들어 Spring Data JPA 를 활용하거나 ( 쿼리 메서드 사용 )

Repository 인터페이스를 내 입맛에 맞게끔 구현할 수 있다. ( 좀더 세분화된 쿼리 사용 )

 


마치며

  • Repository Spring Data JPA, JPA, Hibernate, JDBC API, JDBC Driver, Datasource 에 대한 내용들을 알았다.
  • Spring Data JPA 와 JPA 차이점 에 대해 이해했다.
  • Hibernate와 JPA 차이점 에 대해 이해했다.
  • Datasource의 구성과 세부 내용에 대해 이해했다.
  • 프로젝트 내에서 JpaRepository와 customRepository의 차이점에 대해서 알게되었다.

참고자료

https://code-lab1.tistory.com/272

 

[Spring] JDBC(Java Database Connectivity)란? JDBC 드라이버란?

JDBC의 등장 배경 애플리케이션 서버에서 DB를 연결하기 위해선 어떤 동작이 필요할까? 1. 커넥션 연결 : 주로 TCP/IP를 사용해 애플리케이션 서버와 DB서버가 연결된다. 2. SQL 전달 : 애플리케이션 서

code-lab1.tistory.com

https://taler.tistory.com/12

 

[Spring DataSource] Connection Pool, DataSource 란?

웹 애플리케이션을 개발한다고 할 때 데이터베이스는 거의 필수적이다. 데이터베이스에 데이터를 넣고, 특정 데이터를 읽어오기 위해서는 먼저 데이터베이스에 연결되어있어야 한다. SpringBoot

taler.tistory.com

 

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-db-1

 

스프링 DB 1편 - 데이터 접근 핵심 원리 - 인프런 | 강의

백엔드 개발에 필요한 DB 데이터 접근 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 DB 접근 기술의 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., - 강의

www.inflearn.com

https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/

 

JPA, Hibernate, 그리고 Spring Data JPA의 차이점

개요 Spring 프레임워크는 어플리케이션을 개발할 때 필요한 수많은 강력하고 편리한 기능을 제공해준다. 하지만 많은 기술이 존재하는 만큼 Spring 프레임워크를 처음 사용하는 사람이 Spring 프레

suhwan.dev

https://jaime-note.tistory.com/58

 

스프링 데이터 JPA - Custom Repository Best Practice

사용자 정의 Repository Best Practice 사용자 정의 Repository를 만들 때 가장 좋은 방법을 소개합니다. 일반적으로 사용자 정의 Repository라고 함은, JpaRepository를 상속해서 쿼리 메서드를 이용하는 것이 아

jaime-note.tistory.com