성장일기

내가 보려고 정리하는 공부기록

백엔드/JPA

[JPA] 강의 추가학습 기록(1) - 스프링부트와 JPA활용1

와나나나 2024. 2. 22. 00:48
728x90

인프런 김영한 강사님의 스프링부트와 JPA활용1 강의를 듣고 추가로 학습한 내용을 정리한 게시물입니다.

 

스프링 코어 기초만 듣고 일단 전체적인 개발 흐름을 보기 위해 이 강의를 선수강했다. 강의를 들으면서 코딩을 해보고, 그 후에 JPA, MVC등 개념강의를 들을 생각이다.

그래서 강의를 듣는동안 헷갈리거나 잘 모르는 개념이 많이 나와서 따로 정리해보려고 한다.

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-JPA-%ED%99%9C%EC%9A%A9-1/dashboard

 

실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발 강의 - 인프런

실무에 가까운 예제로, 스프링 부트와 JPA를 활용해서 웹 애플리케이션을 설계하고 개발합니다. 이 과정을 통해 스프링 부트와 JPA를 실무에서 어떻게 활용해야 하는지 이해할 수 있습니다., 스프

www.inflearn.com

 

추가학습 내용은 다음과 같다.

  1. 스프링의 애노테이션 - @Embedded, @Embeddable
  2. hibernate란 ?
  3. 즉시로딩과 지연로딩

1. 스프링의 애노테이션 - @Embedded, @Embeddable

이는 임베디드 타입에 붙는 애노테이션이다. JPA에서는 새로운 값 타입을 정의해 사용하는 것을 임베디드 타입이라고 부른다. 예를 들어보면 아래와 같다.

// import 생략
@Entity
@Getter @Setter
public class Delivery {
	@Id @GeneratedValue
    @Column(name = "delivery_id")
    private Long id;
    
    @OneToOne(mappedBy = "delivery", fetch = FetchType.LAZY)
    private Order order;
    
    @Embedded // 여기주목
    private Address address
    
    @Enumerated(EnumType.STRING)
    private DeliveryStatus status; // ENUM [READY, COMP]
}

 

배송에 대한 Entity를 생성할 때 회원 아이디, 주문정보, 주소, 배송상태가 들어가게 설계했었다. 이때 주소에는 도시, 도로명 등등 세부정보가 들어가야하는데, 이를 String으로 모두 표현하기에는 응집력이 떨어진다. 그래서 Address라는 엔터티를 만들어줘야한다. 이렇게 새로운 값 타입을 정의할 때 @Embedded를 사용한다.

 

// import 생략
@Embeddable
@Getter
public class Address {
	
    private String city;
    private String street;
    private String zipcode;
    
    protected Address() {}
    
    puoblic Address(String city, String street, String zipcode) {
       this.city = city;
       this.street = street;
       this.zipcode = zipcode;
    }
}

 

이렇게 생성한 Address에는 @Embeddable을 붙여준다. 정리하면 아래와 같다.

  • @Embeddable: 값 타입을 정의하는 곳에 표시
  • @Embedded: 값 타입을 사용하는 곳에 표시
  • 임베디드 타입은 기본 생성자가 필수

우리는 값 타입이 변경 불가능하게 설계해야한다. 그래서 @Setter 를 제거하고, 생성자에서 값을 모두 초기화해서 변경 불가능한 클래스를 만들어야 한다.

자바의 기본 생성자는 public 또는 protected로 두는게 좋다고 한다.

 


2. 하이버네이트 (hibernate) 란?

하이버네이트는 자바를 위한 ORM 프레임워크라고 한다. JPA가 하이버네이트를 기반으로 만들어졌다고 한다. 조사해보니까 잠깐 봤던 거 같기도 하고...  ORM 프레임워크 중에서 하이버네이트를 가장 많이 사용한다고 한다!

 

장점

생산성

  • SQL를 직접 사용하지 않고 메소드 호출만으로 쿼리가 수행된다.

유지보수

  • 테이블 칼럼이 변경됐을 때 관련 파라미터, 결과 등을 대신 수행해준다.

패러다임 불일치 해결

  • 상속, 연관관계 등 객체와 관계형DB와의 패러다임 불일치를 해결할 수 있다.

 

단점

성능

  • 메소드 호출만으로 쿼리를 수행하는 게 SQL 작성에 비해 성능 안 좋다.

조작 불편

  • 메소드 호출만으로 DB 데이터를 조작하기엔 한계 존재 (JPQL 지원되긴 함)

3. 즉시로딩 ? 지연로딩 ? 🌟 

JPA에서 데이터를 조회하는 방식에는 즉시로딩과 지연로딩이 있다. 연관관계를 설정하는 애노테이션인 @ManyToMany, @OneToMany, @OneToOne에 아래와 같이 써준다.

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parent_id")
private Category parent;

 

즉시로딩을 쓸 땐 FetchType.EAGER을 쓰고, 지연로딩을 쓸 땐 FetchType.LAZY를 사용한다. 그런데 모든 연관관계는 지연로딩을 설정해야 한다고 하셨다!

 

즉시로딩

연관관계를 맺은 엔터티까지 불러오는 쿼리를 날려 한번에 데이터를 가져온다. 그런데 연관관계가 많으면,, 추적이 어려워져 유지보수도 힘들어진다.

 

지연로딩

연관관계를 맺은 엔터티를 사용하게 될 때 쿼리가 나간다. 그 전까진 나가지 않는다.

 

 

정리하자면

  • 즉시로딩은 예측이 어렵고, 어떤 SQL이 실행될지 추적이 어려움
  • XToOne (OneToOne, ManyToOne)은 기본이 즉시로딩이므로 직접 지연로딩으로 설정해야한다.
    • XToMany는 기본이 지연로딩이라 그냥 둬도 된다.

 

🌟 실무에서는 꼭! 모든 연관관계를 지연로딩으로 설정하자 🌟

 


24.2.19 의 추가학습 끝!