관리 메뉴

bright jazz music

[bootBoard] N:1(다대일) 연관관계: 6-2. @ManyToOne과 Lazy loading 본문

Framework/Spring

[bootBoard] N:1(다대일) 연관관계: 6-2. @ManyToOne과 Lazy loading

bright jazz music 2022. 9. 27. 21:54

이 포스팅에서는 Lazy Loading의 효과를 알아본다.

 

1. Board.java를 수정하여 Lazy Loading을 설정

우선 Board 클래스를 아래와 같이 수정한다.

//Board.java
package com.example.bootboard.entity;

import lombok.*;

import javax.persistence.*;

@Entity
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@ToString(exclude = "writer") //이렇게 해준 이유는 아래에서 설명함
public class Board extends BaseEntity{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long bno;

    private String title;

    private String content;

    @ManyToOne(fetch = FetchType.LAZY) //명시적으로 Lazy Loading 지정
    private Member writer; //FK 연관관계 지정

    //Board클래스는 Member클래스의 email(PK)를 FK로 참조하는 구조이다.

}

fetch는 데이터를 가져오는 방식을 의미한다. 여기서는 fetch를 이용해서 @ManyToOne의 파라미터를 조정해 주었다.

설정을 완료했으면 BoardRepositoryTests.java의 testRead1() 을 실행한다.

테스트를 실행하면 아래와 같은 오류가 출력된다.

 

세션이 없다는 것, 즉 연결되지 않은 상태라는 것이다. 이를 해결하기 위해선 DB와 추가적인 연결을 해야 한다.

System.out.println(board);까지는 오류가 발생하지 않는다.

System.out.println(board.getWriter());에서 오류가 발생하는 것이다. 이 값을 가져오려면 member 테이블을 로딩해야 하는데 그 전에 이미 DB 연결이 끊어졌기 때문이다. no Session 메시지는 이런 경우에 발생한다.

 

이 문제를 해결하려면 다시 한 번 DB가 연결되어야 한다. @Transactional 어노테이션을 사용하면 이를 해결할 수 있다.

@Transactional은 해당 메서드를 하나의 트랜젝션으로 처리하도록 만든다. 이 어노테이션을 해당 메서드 선언부 상단에 위치시킨다.

 

@Transactional을 메서드 선언부 위에 위치시키고 테스트 실행
board.getWriter() ==> Member(email=user100@aaa.com, password=11111, name=USER100)가 출력된 것을 볼 수 있다.

  • 먼저 board 테이블을 로딩하여 처리한다.
  • 연결이 끝나면 board.getWriter()를 처리하기 위해 member 테이블을 로딩한다.

 

Eager loading을 사용 시 조인하여 한 번에 가져오는 방식과는 다르다.

 

2. 연관관계에서의 @ToString

엔티티 간 연관관계를 지정하는 경우 @ToString()을 주의할 것.

@ToString은 해당 클래스의 모든 멤버 변수를 출력한다. Board 객체를 @ToString()하면 연관관계 설정을 위해 기입한 private Member member 역시 출력한다. 이 과정에서 Member의 ToString() 역시 호출된다. 이 때 DB 연결이 필요하게 된다.

 

이런 문제를 방지하기 위해서, 연관관계에 있는 엔티티 클래스의 경우 @ToString()을 할 때는 exclude 속성을 사용한느 것이 좋다. exclude는 해당 속성 값으로 지정된 변수는 toString()에서 제외하지 때문이다. 지연로딩 사용시 아래와 같이 지정해 주는 것이 좋다.

 

@ToString(exclude ="writer") : writer 변수는 toString에서 제외한다.

 

 

 

3. Lazy Loading의 장단점

 

장점

  • 지연로딩은 조인을 하지 않는다. 필요한 순간에 쿼리를 실행한다. 따라서 하나의 테이블을 이용하는 경우 즉시로딩보다 처리속도가 상대적으로 빠르다.

단점

  • 연관관계가 복잡한 경우 여러 번의 쿼리가 실행된다.

 

보편적으로는 지연로딩을 기본으로 사용한다. 상황에 따라 지연로딩이 아닌 다른 방법을 고려해야 하는 경우도 존재한다.

Comments