SpringBoot

ORM (Object Relational Mapping)

똑똑한망치 2024. 2. 8. 19:03
728x90
반응형

1. ORM (Object Relational Mapping)


  • ORM은 테이블을 객체지향적으로 사용하기 위한 기술이다.
  • 객체 관계 매핑을 의미한다. 즉, 객체와 DB 테이블이 매핑을 이루는 것을 의미한다.
  • 자바와 같은 객체지향 언어에서 의미하는 객체와 RDB(Relational Database)의 테이블을 자동으로 매핑하는 방법이다.
    • 이 게시글에서 객체지향 언어에서의 객체는 클래스를 의미한다.
  • 클래스는 데이터베이스의 테이블과 매핑하기 위해 만들어진 것이 아니기 때문에 RDB 테이블과 불일치가 존재한다. ORM은 이 둘의 불일치와 제약사항을 해결하는 역할이다.

 

ORM의 역할

 

 

(1) ORM의 장점

  • 데이터베이스 쿼리를 객체지향적으로 조작할 수 있다.
    • 쿼리문을 작성하는 양이 현저히 줄어 개발 비용이 줄어든다.
    • 객체지향적으로 데이터베이스에 접근할 수 있어 가독성이 높아진다.
  • 재사용 및 유지보수가 편리하다.
  • 데이터베이스에 대한 종속성이 줄어든다.
    • ORM을 통해 자동 생성된 SQL문은 객체를 기반으로 데이터베이스 테이블을 관리하기 때문에 데이터베이스에 종속적이지 않다.

 

(2) ORM의 단점

  • ORM만으로 온전한 서비스를 구현하기에 한계가 존재한다.
  • 애플리케이션의 객체 관점과 데이터베이스의 관계 관점의 불일치가 발생한다.
    • 세분성(Granularity) : ORM의 자동 설계 방법에 따라 데이터베이스에 있는 테이블의 수와 애플리케이션의 엔티티(Entity) 클래스의 수가 다른 경우가 생긴다.
    • 상속성(Inheritance) : RDBMS 에는 상속이라는 개념이 존재하지 않는다.
    • 식별성(Identity) : RDBMS는 기본키(primary key)로 동일성을 정의한다. 하지만 자바는 두 객체의 값이 같아도 다르다고 판단할 수 있다.
    • 연관성(Associations) : 객체지향 언어는 객체를 참조함으로써 연관성을 나타내지만 RDBMS에서는 외래키(foreign key)를 삽입하여 연관성을 표현한다. 

 

(3) ORM 프레임워크 종류

Java : JPA, Hibernate, EclipseLink, DataNucleus, Ebean 등

 

위의 사진을 보면 Data Access Layer들이 Service와 DB 사이를 연동해주고 있다. JPA, Hibernate는 Java의 ORM 프레임워크인 것이다. JDBC는 ORM이 아니다❌

 


2. JDBC(Java DataBase Connectivity)

JDBC는 ORM이 아닌, 데이터베이스에 연결 및 작업을 하기 위한 자바 표준 인터페이스다.

 

자바는 DBMS에 상관 없이 하나의 JDBC API를 이용해서 데이터베이스 작업을 처리한다. 이 JDBC는 DB에 접근해서 CRUD를 쉽고 효율적이게 할 수 있다.

 

JDBC API가 생겨나기 전에는 데이터베이스의 종류마다 (MySQL, Oracle ...) 각각의 SQL을 사용했다. 하지만 DB의 종류에 따라 SQL문의 작성 방법이 너무 달라서 불편했다. 이런 불편함으 해결하고자 메서드, 전역변수 등을 하나의 문법으로 통일시켰고 그것이 JDBC가 되었다.

 

JDBC의 핵심 : DBMS의 종류에 상관없이 하나의 JDBC API를 이용해서 하나의 문법으로 통일시켜 데이터베이스 작업을 처리한다.

 

JDBC 아키텍처

 

3. JPA (Java Persistence API)


  • JPA는 Hibernate 기반으로 자바 진영의 ORM 기술 표준으로 채택된 인터페이스의 모음이다.
  • 즉, 자바 애플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스이다.
  • ORM이 큰 개념이라면 JPA는 더 구체화된 스펙을 포함한다. 즉, JPA 또한 실제로 동작하는 것이 아니라 어떻게 동작해야 하는지 메커니즘을 정리한 표준 명세이다.

 

ORM의 더 구체화된 자바 표준 스펙인 JPA

 

 

대표적인 JPA 구현체

 

  • JPA 메커니즘은 내부적으로 JDBC를 사용한다. 즉, JPA는 애플리케이션과 JDBC 사이에서 동작한다는 의미이다. JPA는 개발자 대신 적절한 SQL을 생성하고 데이터베이스를 조작해서 객체를 자동 매칭하는 역할을 수행한다.
    • JPA는 데이터베이스와 객체를 매핑하는 기술일 뿐, 내부적으로는 데이터베이스와의 통신을 위해 JDBC를 사용한다.
    • 개발자가 JPA를 사용하면, JPA 내부에서 JDBC API를 사용하여 SQL을 호출하여 DB와 통신한다.

 

 

JPA 기반의 구현체는 대표적으로 하이버네이트(Hibernate), 이클립스 링크(EclipseLink), 데이터 뉴클리어스(DataNucleus)가 있다.

 

 

 

(1) 하이버네이트 (Hibernate)

하이버네이트는 자바의 ORM 프레임워크로, JPA가 정의하는 인터페이스를 구현하고 있는 JPA 구현체 중 하나이다.

 

 

Spring Data JPA

  • JPA를 편리하게 사용할 수 있도록 지원하는 스프링 하위 프로젝트 중 하나이다.
  • Spring Data JPA는 CRUD 처리에 필요한 인터페이스를 제공하고, 하이버네이트의 엔티티 매니저 (Entity Manager)를 직접 다루지 않고 Repository 를 정의해 사용함으로써 스프링이 적합한 쿼리를 능동적으로 생성하는 방식으로 데이터베이스를 조작한다.

Spring Data JPA 의 도식화

 

 

 

 

(2) 영속성 컨텍스트 (Persistence Context)

  • 영속성 컨텍스트는 애플리케이션과 데이터베이스 사이에서 엔티티와 레코드의 괴리를 해소하는 기능과 객체를 보관하는 기능을 수행한다.
    • 즉, 엔티티를 영구 저장하는 환경이다.
  • 엔티티 객체가 영속성 컨텍스트에 들어오면 JPA는 엔티티 객체의 매핑 정보를 데이터베이스에 반영하는 작업을 수행한다.
  • 엔티티 객체가 영속성 컨텍스트에 들어와 JPA의 관리 대상이 되는 시점부터는 해당 객체를 영속 객체(Persistence Object)라고 부른다.
  • 영속성 컨텍스트는 세션 단위의 생명주기를 가진다. 데이터베이스에 접근하기 위한 세션이 생성되면 영속성 컨텍스트가 만들어지고, 세션이 종료되면 영속성 컨텍스트도 없어진다.
  • 엔티티 매니저는 이러한 일련의 과정에서 영속성 컨텍스트에 접근하기 위한 수단으로 사용된다.
    • 엔티티 매니저(Entity Manager)
      • 엔티티를 관리하는 객체
      • 데이터베이스에 접근해서 CRUD 작업을 수행한다.

영속성 컨텍스트

 

 

 

 


 

 

 

스프링 부트 애플리케이션의 구조

 

 

 

 

3. 엔티티 설계


  • Spring Data JPA를 사용하면 데이터베이스에 테이블을 생성하기 위해 직접 쿼리를 작성할 필요가 없다. 이 기능을 하게 하는 것이 Entity 이다.
  • JPA에서 엔티티는 데이터베이스의 테이블에 대응하는 클래스이다.
  • 엔티티는 데이터베이스에 쓰일 테이블과 칼럼을 정의한다.

엔티티 클래스 설계 예시

 

 

 

(1) 엔티티 관련 기본 어노테이션

  • @Entity
    • 해당 클래스가 엔티티임을 명시하기 위한 어노테이션이다.
    • 클래스 자체는 테이블과 1:1로 매칭되며, 해당 클래스의 인스턴스는 매핑되는 테이블에서 하나의 레코드를 의미한다.
  • @Table
    • 엔티티 클래스는 테이블과 매핑되므로 특별한 경우가 아니면 생략해도 된다.
    • @Table 어노테이션을 사용할 때는 클래스의 이름과 테이블의 이름을 다르게 지정해야 하는 경우이다.
    • " @Table(name = 값) " 형태로 데이터베이스의 테이블명을 명시해야 한다.\
  • @Id
    • @Id 어노테이션이 선언된 필드는 테이블의 기본값 역할로 사용된다.
    • 필수적으로 선언해줘야 한다.
  • @GeneratedValue
    • 해당 필드 값을 어떤 방식으로 자동 생성할 지 결정할 때 사용한다.
      • GeneratedValue를 사용하지 않는 방식(직접 할당)
        • 애플리케이션에서 자체적으로 고유한 기본값을 생성할 경우
        • 내부에 정해진 규칙에 의해 기본값을 생성하고 식별자로 사용
      • AUTO
        • @GeneratedValue의 기본 설정값
      • IDENTITY
        • 기본값 생성을 데이터베이스에 위임하는 방식
        • 데이터베이스의 AUTO_INCREMENT를 사용해 기본값을 생성한다.
      • SEQUENCE
        • 식별자 생성기를 설정하고 이를 통해 값을 자동으로 주입받는다.
      • TABLE
        • 어떤 DBMS를 사용하더라도 동일하게 동작하기를 원하는 경우 사용한다.
        • 식별자로 사용할 숫자의 보관 테이블을 별도로 생성해서 엔티티를 생성할 때마다 값을 갱신하며 사용한다.
        • @TableGenerator 어노테이션으로 테이블 정보를 설정한다.
  • @Column
    • 엔티티 클래스의 필드는 자동으로 테이블 칼럼으로 매핑되므로 별도로 설정하지 않아도 된다.
  • @Transient
    • 엔티티 클래스에는 선언돼 있는 필드지만 데이터베이스에서 필요 없을 경우 이 어노테이션을 사용해 데이터베이스에서 이용하지 않게 할 수 있다.

 

 

 


 

 

 

4. 리포지토리 인터페이스 설계


Spring Data JPA는 JpaRepository를 기반으로 더욱 쉽게 데이터베이스를 사용할 수 있는 아키텍처를 제공한다. 스프링 부트로 JpaRepository를 상속하는 인터페이스를 생성하면 기존의 다양한 메서드를 쉽게 활용할 수 있다.

 

리포지토리 상속 구조
리포지토리 생성

 

 

 

 


 

 

 

 

5. DAO 설계


DAO (Data Access Object) 는 데이터베이스에 접근하기 위한 로직을 관리하기 위한 객체이다. JPA에서 DAO 의 개념은 리포지토리가 대체하고 있다.

 

★ DAO vs. Repository

  • 리포지토리는 Spring Data JPA에서 제공하는 기능이기 때문에 기존의 스프링 프레임워크나 스프링 MVC의 사용자는 리포지토리라는 개념을 사용하지 않고 DAO 객체로 데이터베이스에 접근했었다.

 

 

(1) DAO 클래스 생성

  • DAO 클래스는 일반적으로 '인터페이스-구현체' 구성으로 생성한다.
  • DAO 클래스는 의존성 결합을 낮추기 위한 디자인 패턴이며, 서비스 레이어에 DAO 객체를 주입받을 때 인터페이스를 선언하는 방식으로 구성할 수 있다.

DAO 인터페이스 예시

 

인터페이스 구현체 예시

 

 

 

 


 

 

6. 롬복 (Lombok)


롬복(Lombok)은 데이터(모델) 클래스를 생성할 때 반복적으로 사용하는 getter/setter 같은 메서드를 어노테이션으로 대체하는 기능을 제공하는 라이브러리이다.

 

(1) 롬복의 주요 어노테이션

  • @Getter / @Setter 
    • 클래스에 선언된 getter / setter 메서드를 생성한다.
  • 생성자 자동 생성 어노테이션
    • NoArgsConstructor : 매개변수가 없는 생성자를 자동 생성
    • AllArgsConstructor : 모든 필드를 매개변수로 갖는 생성자를 자동 생성
    • RequiredArgsConstructor : 필드 중 final 이나 @NotNull 이 설정된 변수를 매개변수로 갖는 생성자를 자동 생성
  • @ToString
    • toString( ) 메서드를 생성하는 어노테이션
  • @EqualsAndHashCode
    • 객체의 동등성(Equality)와 동일성(Identity)을 비교하는 연산 메서드를 생성
  • @Data
    • @Getter / @Setter, @RequiredArgsConstructor, @ToString, @EqualsAndHashCode 를 모두 포괄하는 어노테이션
  • @Configuration
    • Spring에서 Bean을 수동으로 등록하기 위한 어노테이션
    • @Bean 어노테이션을 메서드에 추가해주어야 한다.
  • @Build
    • 생성자를 커스터마이징 할 수 있다.
  • @Autowired 
    • 의존성 주입을 할 때 사용하는 어노테이션
    • 의존 객체의 타입에 해당하는 bean을 찾아 주입하는 역할을 한다.
반응형

'SpringBoot' 카테고리의 다른 글

JPA Auditing  (0) 2024.02.14
Spring Data JPA 활용  (0) 2024.02.13
REST API 명세를 문서화하기  (0) 2024.02.02
API 작성 방법 (Delete API)  (0) 2024.02.02
API 작성 방법 (PUT API)  (0) 2024.02.02