hayu's 개발 일지

[TIL]240315 스프링 부트와 AWS로 혼자 구현하는 웹서비스: -3장 JPA 본문

스터디/spring

[TIL]240315 스프링 부트와 AWS로 혼자 구현하는 웹서비스: -3장 JPA

hayu00 2024. 3. 15. 21:03

테스트 코드

TDD(test-driven development)

  • 테스트가 주도하는 개발을 말한다. (선 테스트 → 후 개발)
  • 테스트 코드를 먼저 작성하는 것 부터 시작한다.
  • 항상 실패하는 테스트 작성 → 테스트가 통과하는 프로덕션 코드 작성 → 테스트가 통과하면 코드를 리팩토링

TDD의 장점

  • 객체 지향적인 코드 개발: 의존성과 종속성이 낮은 모듈로 조합된 소프트웨어 개발 가능
  • 설계 수정시간의 단축: 테스트 코드를 먼저 작성하기 때문에 설계의 구조적 문제를 바로 찾아낼 수 있다.
  • 유지보수(리펙토링)의 용이성: 추후 문제가 발생했을 때 모듈별로 테스트 진행하면 문제 지점을 찾기 쉽다.

TDD의 단점

  • 생산성 저하: 예외상황이 발생할 것이 예측되는 상황에도 테스트 코드 작성하고 통과 코드를 작성하는 것은 비효율적이다.
  • 사전준비 기간: TDD를 프로젝트에 도입하려면 사전에 필요한 지식 습득과 개발 환경 구축이 필요하다. TDD를 효과적으로 사용할 수 있게 교육하는 기간은 보통 6개월 ~ 1년이다.

+ DDD(Domain-Driven Design)

  • 도메인 주도 설계이다. 즉, 도메인 패턴을 중심에 놓고 설계하는 방식이다.

→ 비즈니스 도메인 별로 나눠 설계한다.

: 기존의 어플리케이션 설계가 비즈니스 도메인에 대한 이해가 부족한 상태에서 설계 및 개발되었다는 반성에서 출발되었다.

  • 핵심 목표: 소프트웨어의 복잡성을 최소화 하고 요구 사항을 쉽게 반영하고 소통이 원활하게 이루어질 수 있게 하는 것이다.

JPA

  • 객체 지향 프로그래밍 언어와 관계형 데이터 데이스를 중간에서 패러다임 일치 시켜주기 위한 기술이다.

패러다임 불일치의 예

User user = findUser();
Group group = user.getGroup();
  • User 와 Group 은 부모 - 자식 관계이지만 데이터 베이스에서는 각각 따로 조회하게 된다.

JPA 란?

  • 인터페이스로서 자바 표준 ORM이다.
  • ORM(Object-Relational Mapping) 기술 표준으로 사용되는 인터페이스의 모음이다.
  • JPA를 사용하면 객제와 관계형 데이터베이스 간의 매핑을 쉽게 처리할 수 있다.

Entity 클래스

  • 실제 DB와 매칭된 클래스를 말한다.
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter // lombok 어노테이션 : 클래스 내에 모든 필드에 Getter 메소드 자동생성한다.
@Entity //JPA 어노테이션 : 테이블과 링크될 클래스임을 나타냄
@NoArgsConstructor // lombok 어노테이션 : 기본 생성자 자동 추가 역할을 한다.
public class User {

    @Id //테이블의 PK 필드를 나타낸다. -> PK(PRIMARY KEY) : 행의 고유 식별 역할
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false) // 테이블의 칼럼을 나타낸다. 기본값 외에 추가로 변경하고 싶은 내용이 있을 때 사용한다.
    private String userName;

    @Column(nullable = false)
    private int userAge;

    @Column(nullable = false)
    private String userEmail;

    @Builder // lombok 어노테이션 : 해당 클래스의 빌더 클래스를 생성한다.
    // 생성자 상단에 선언하면 생성자에 포함된 필드만 메서드에 포함된다.
    public User(String userName, int userAge, String userEmail) {
        this.userName = userName;
        this.userAge = userAge;
        this.userEmail = userEmail;
    }

}

JPA를 사용했을 때 Entity 클래스에서 많이 쓰이는 에너테이션

@Entity

  • jpa의 어노테이션이다.
  • 테이블과 링크될 클래스임을 나타낸다.
  • 기본값으로 카멜케이스 이름을 언더스코어(_) 네이밍으로 테이블 이름을 매칭한다.

@Id

  • 테이블의 PK필드를 나타낸다.
  • PK(PRIMARY KEY) : 행의 고유 식별 역할

@Column

  • 테이블의 칼럼을 나타낸다. 기본값 외에 추가로 변경하고 싶은 내용이 있을 때 사용한다.

@NoArgsConstructor

  • 기본 생성자 자동 추가 역할을 한다.

@Getter

  • 클래스 내에 모든 필드에 Getter 메소드 자동생성한다.
  • Entity 클래스에서는 Setter 메소드를 만들지 않는다. - 해당 클래스의 인스턴스 값들이 언제 어디서 변해야 하는지 코드상으로 명확하게 구분이 안됨. 차후 기능 변경 시 복잡해짐.

→ 생성자를 통해 public 메소드 호출해서 사용. @Bulider 를 사용하여 대체 가능.

Repository

  • 엔티티 클래스로 DB를 접근하게 해주는 역할을 한다.
import org.springframework.data.jpa.repository.JpaRepository;

public interface Repository extends JpaRepository<User, Long> {
}
  • 인터페이스 생성 후, <Entity 클래스, pk 타입> 를 상속하면 기본적인 CRUD 메소드가 자동 생성된다.
  • Entity 클래스와 기본 Repository 는 함께 위치해야 한다. (프로젝트 규모가 커지면 헷갈릴 수 있음. 같은 패키지에서 관리)

영속성 컨텍스트

  • 엔티티를 영구저장하는 환경이다. (논리적 개념)
  • JPA의 핵심 내용은 엔티티가 영속성 컨텍스트에 포함되어있느냐 없느냐로 갈린다.
  • 엔티티 매지너가 활성화된 상태로 트랜잭션 안에서 데이터베이스를 가져오면 이 데이터는 영속성 컨텍스트가 유지된 상태이다. 이때 데이터 값을 변경하면 트랜젝션이 끝나는 시점에 해당 테이블에 변경분을 반영한다.

→ 엔티티 객체의 값을 변경하면 별도로 Update 쿼리를 날릴 필요가 없음. (더디 체킹)

  • 트랜잭션: 데이터 베이스의 상태를 변화시키는 작업이다. 여러 개의 데이터 베이스 조작 명령문(쿼리)이 모여서 한번에 실행되는 것을 말한다.

JPA Auditing

  • JPA에서 관계형 데이터 베이스 케이블을 매핑할 때 공통적으로 도메인들이 가지고 있는 필드나 컬럼들이 존재한다.
  • Spring Data JPA에서 데이터들의 시간에 대해서(생성일, 수정일) 자동으로 값을 넣어주는 기능이 JPA Auditing이다.
  • 영속성 컨텍스트에 저장하거나 조회를 수행한 후에 update를 하는 경우 매번 시간 데이터를 입력해줘야 하는데, 자동으로 시간을 매핑하여 데이터 베이스 테이블에 넣어준다.
@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseTimeEntity{

  // Entity가 생성되어 저장될 때 시간이 자동 저장된다.
    @CreatedDate
    private LocalDateTime createdDate;

  // 조회한 Entity의 값을 변경할 때 시간이 자동 저장된다.
    @LastModifiedDate
    private LocalDateTime modifiedDate;

}

BaseTimeEntity는 모든 Entity의 상위 클래스가 되어 Entity들의 createdDate, modifiedDate를 자동으로 관리한다.

@MappedSuperclass

  • JPA Entity 클래스들이 BaseTimeEntity를 상속할 경우 필드들(createdDate, modifiedDate)도 칼럼으로 인식하도록 한다.

@EntityListeners(AuditingEntityListener.class)

  • BaseTimeEntity 클래스에 Auditing 기능을 포함 시킨다.

@CreatedDate

  • Entity가 생성되어 저장될 때 시간이 자동 저장된다.

@LastModifiedDate

  • 조회한 Entity의 값을 변경할 때 시간이 자동 저장된다.

JPA Auditing 활성화하기

  • @EnableJpaAuditing 를 추가하여 JPA Auditing 어노테이션들을 모두 활성화할 수 있도록 한다.