Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

채채

03. 스프링 부트에서 JPA로 데이터베이스 다루기 본문

spring boot

03. 스프링 부트에서 JPA로 데이터베이스 다루기

HChaeEun 2022. 11. 7. 14:55
  1. JPA 소개
  2. 프로젝트에 Spring Data Jpa 적용하기
  3. Spring Data JPA 테스트 코드 작성하기
  4. 등록/수정/조회 API 만들기
  5. JPA Auditing으로 생성시간/수정시간 자동화하기
 

  1. JPA 소개

JPA를 왜 사용하는지에대해 먼저 알아보고자한다.

현대의 웹 애플리케이션에서 관계형 데이터베이스는 빠질 수 없는 요소가 되었다. 관계형 데이터베이스가 SQL만 인식할 수 있다보니 각 테이블마다 기본적인 CRUD(Create, Read, Update, Delete) SQL을 매번 생성하다보면 결국 프로젝트의 대부분은 애플리케이션 코드보다 SQL로 가득하게 된다.

따라서 관계형 데이터베이스를 이용하는 프로젝트에서 객체지향 프로그래밍을 하기위해 JPA라는 자바 표준 ORM(Object Relational Mapping)을 사용하는 것이다.

JAVA와 C++같은 객체 지향 언어는 메시지를 기반으로 기능과 속성을 한 곳에서 관리하는 기술이다. 반면 관계형 데이터베이스는 어떻게 데이터를 저장할지에 초점이 맞춰진 기술이므로 서로 다른 패러다임을 중간에서 JPA가 일치시켜주는 것이다.

즉 개발자는 객체지향언어로 프로그래밍을 하면, JPA가 관계형 데이터베이스에 맞게 SQL을 대신 생성해서 실행한다.

JPA는 인터페이스로서 자바 표준명세서이다. 인터페이스인 JPA를 사용하기 위해서는 구현체가 필요한데, Spring에서 JPA를 사용할 때는 구현체들을 좀 더 쉽게 사용하고자 추상화시킨 Spring Data JPA라는 모듈을 사용하여 JPA기술을 다룬다.

구현체의 종류에는 Hibernate, Eclipse, Link등이 있는데, 이들을 직접 사용하지 않는 이유는 구현체 '교체의 용이성'을 위함이다. Hibernate 외에 다른 구현체로 쉽게 교체하기 위함이며, 언젠가 구현체의 수명이 다했을 때 Spring Data JPA를 쓰는 중이라면 아주 쉽게 교체할 수 있다.

또한 '저장소 교체의 용이성'을 위함인데, 관계형 데이터베이스 외에 다른 저장소로 쉽게 교체하기 위함이다. 관계형 데이터베이스를 사용하다가 더 많은 저장공간이 필요할 때, Spring Data JPA에서 Spring Data MongoDB로 의존성만 교체하면 된다. 이는 Spring Data의 하위 프로젝트들은 기본적인 CRUD인터페이스가 같기 때문이다.

2. 프로젝트에 Spring Data Jpa 적용하기

앞으로 게시판 기능과 회원 기능이 포함된 프로젝트를 진행할 것인데, 가장 기초가되는 부분을 진행할 것이다.

첫 번째로 build.gradle에 다음과 같이 의존성들을 등록한다.

 
dependencies {
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('org.projectlombok:lombok')
// spring-boot-starter-data-jpa
    implementation('org.springframework.boot:spring-boot-starter-data-jpa')
// h2
    implementation('com.h2database:h2')
    testImplementation('org.springframework.boot:spring-boot-starter-test')
}

spring-boot-starter-data-jpa는 스프링 부트용 Spring Data Jpa 추상화 라이브러리이다. 스프링 부트 버전에 맞춰 자동으로 JPA관련 라이브러리들의 버전을 관리해준다.

h2는 인메모리 관계형 데이터베이스로, 별도의 설치가 필요 없이 프로젝트 의존성만으로 관리할 수 있다. 또한 메모리에서 실행되기 때문에 애플리케이션을 재시작할 때마다 초기화된다는 점을 이용하여 테스트 용도로 많이 사용된다.

* domain 패키지

domain 패키지는 도메인을 담을 패키지로 소프트웨어에 대한 요구사항 혹은 문제영역 <게시글, 댓글, 회원, 정산, 결제 등>이다.

domain 패키지에 posts 패키지와 Posts 클래스를 만든다.

Posts 클래스는 실제 DB의 테이블과 매칭될 클래스이며 보통 Entity 클래스라고도 한다.

[src/main/java/com/domain/posts/Posts]

import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Getter
@NoArgsConstructor
@Entity
public class Posts {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(length = 500, nullable = false)
    private String title;

    @Column(columnDefinition = "TEXT", nullable = false)
    private String content;

    private String author;

    @Builder
    public Posts(String title, String content, String author) {
        this.title = title;
        this.content = content;
        this.author = author;
    }
}

어노테이션은 사전적 의미로는 주석이라는 뜻이다. 자바에서 사용될 때의 어노테이션(@)은 코드 사이에 주석처럼 쓰여서 특별한 의미, 기능을 수행하도록 하는 기술이다. 즉, 프로그램에게 추가적인 정보를 제공해주는 메타데이터(meta data: 데이터를 위한 데이터)라고 볼 수 있다.

개발할 때 자주 사용하는 코드 Getter, Setter, 기본생성자, toString 등을 어노테이션으로 자동생성하는 롬북을 spring에서 사용한다.

@Entity는 JPA의 어노테이션이며, @Getter와 @NoArgsConstructor는 롬북의 어노테이션이다.(필수 어노테이션 아님)

다음은 JPA에서 제공하는 어노테이션들이다.

  1. @Entity
  • 테이블과 링크될 클래스임을 나타낸다
  • 기본값으로 클래스의 카멜케이스 이름을 언더스코어 네이밍(_)으로 테이블 이름을 매칭한다
  • ex)SalesManager.java -> sales_manager table

2. @Id

  • 해당 테이블의 PK필드를 나타낸다.

3. @GeneratedValue

  • PK의 생성 규칙을 나타낸다
  • 스프링 부트 2.0에서는 GenertationType.IDENTITY 옵션을 추가해야만 auto_increment가 된다.

4. @Column

  • 테이블의 칼럼을 나타내며 굳이 선언하지 않더라도 해당 클래스의 필드는 모두 칼럼이 된다.
  • 사용하는 이유는, 기본값 외에 추가로 변경이 필요한 옵션이 있으면 사용한다.
  • 문자열의 경우 VARCHAR(255)가 기본값인데, 사이즈를 500으로 늘리고 싶다거나(ex. title), 타입을 TEXT로 변경하고 싶다거나(ex. content)등의 경우에 사용된다.

5. @NoArgsConstructor

  • 기본 생성자 자동 추가
  • public Posts(){}와 같은 효과

6. @Getter

  • 클래스 내 모든 필드의 Getter 매소드를 자동 생성

7. @Builder

  • 해당 클래스의 빌더 패턴 클래스를 생성
  • 생성자 상단에 선언 시 생성자에 포함된 필드만 빌더에 포함

※ Entity 클래스에서는 절대 Setter 메소드를 만들지 않는다.

getter/setter을 무작정 생성하는 경우, 언제 어디서 변해야하는지 코드상으로 명확하게 구분하기 힘들기 때문에 필드의 값 변경이 필요하면. 정확히 그 목적과 의도를 나타낼 수 있는 메소드를 추가해야한다.

Posts 클래스로 Database를 접근하게 해줄 JpaRepository를 생성.

[src/main/java/com/domain/posts/PostsRepository]

import org.springframework.data.jpa.repository.JpaRepository;

public interface PostsRepository extends JpaRepository<Posts, Long>{}

DAO와 같은 DB Layer 접근자가 JPA에선 Repository라고 부르며 인터페이스로 생성한다. 단순히 인터페이스를 생성후, JpaRepository<Entity 클래스, PK타입>을 상속하면 기본적인 CRUD 메소드가 자동으로 생성된다.

주의 - Entity 클래스와 기본 Entity Repository는 함께 위치해야한다. 이는 Entity가 Entity Repository없이는 제대로 역할을 할 수가 없기때문이다. 따라서 도메인 패키지에서 함께 관리한다.