본문 바로가기

항해 99/Spring

메서드 명 find와 get의 차이

네이밍 컨벤션 find vs get (JPA에서의 내부 동작 차이)

Repository 내 구현되는 메서드 명으로 find와 get을 선택함에는 다소 신중함이 필요함

메서드 명으로 find를 쓰느냐, get을 스느냐에 따라서 메서드 내부 구현이 어떻게 되어 있을지도 함께 전달할 수 있음

 

get vs find 기준

1. 값을 가져오는 시간 기준

  • get : 데이터를 가져오는 시간이 짧을 때 사용
  • find : 검색 프로세스나 연산 알고리즘을 사용하며, 데이터를 가져오는데 걸리는 시간이 좀 더 길다.

2. 데이터 가져오는 데 오류 여부

  • get : 데이터 가져오는데 오류가 발생하지 않는다. 비교적 간단한 로직
  • find : 데이터를 가져오는데 오류가 발생한다. 비교적 복잡한 로직

 

get을 사용하는 경우

  • 데이터를 가져오는 시간이 짧다.
  • 로직이 간단하다.
  • 데이터를 가져오는데 오류가 발생하지 않는다.
function getUser() {};
function getEmail() {};

 

 

find를 사용하는 경우

  • 검색 프로세스나 연산 알고리즘 사용하며, 데이터를 가져오는데 걸리는 시간이 좀 더 길다.
  • 로직이 복잡하다.
  • 데이터를 가져오는데 오류가 발생한다.
function findUserFromDB() {};
function findUserByEmail() {};
function findPostOrderByDate() {};

 

 

 

JPA에서의 내부 동작 차이

findById()

Optional<T> findById(ID id)
  • Optional<T> : 조회된 엔티티를 Optional로 감싼 반환 타입, Optional은 엔티티가 존재하지 않을 수도 있는 경우에 사용
  • ID : 조회할 엔티티의 식별자(ID) 타입
  • 조회된 엔티티 객체를 Optional로 감싸서 반환
  • CrudRepository와 JpaRepository 인터페이스에서 모두 제공되는 메서드

 

getReferenceById()

public T getReference(ID id)
  • T : 반환 타입으로 엔티티의 클래스 타입
  • ID : 조회할 엔티티의 식별자(ID) 타입
  • 엔티티가 영속성 컨텍스트에 없으면 EntityNotFoundException이 발생할 수 있음
  • JpaRepository 인터페이스에서만 제공됨
  • 데이터 가져오는 방식
    • 지연로딩(Lazy Loading) : 엔티티를 실제로 사용할 때까지 데이터베이스 조회를 지연함
    • 실제 엔티티 객체가 필요한 시점에서는 프록시 객체가 아닌 실제 엔티티를 반환(처음에는 Proxy 객체로 가지고 있음)

 

 

테스트 코드

findById()

@Test
public void testSelect(){
    Long member_no = 13L;
    Optional<Member> result = memberRepository.findById(member_no);
    System.out.println("=============================");
    if(result.isPresent()){
        Member member = result.get();
        System.out.println(member);
    }
}

 

테스트 결과 값

  select
        m1_0.member_no,
        m1_0.member_from_social,
        m1_0.member_id,
        m1_0.member_nickname,
        m1_0.member_password 
    from
        member m1_0 
    where
        m1_0.member_no=?
=============================
Member(member_no=5, member_id=user5, member_password=123123123, member_nickname=사용자5, member_from_social=false)

 

 

 

getReferenceById()

@Test
@Transactional
public void testSelect(){
    Long member_no = 5L;
    Member result_get = memberRepository.getReferenceById(member_no);
    System.out.println("=============================");
    System.out.println(result_get);
}

 

테스트 결과 값

=============================
Hibernate: 
    select
        m1_0.member_no,
        m1_0.member_from_social,
        m1_0.member_id,
        m1_0.member_nickname,
        m1_0.member_password 
    from
        member m1_0 
    where
        m1_0.member_no=?
Member(member_no=5, member_id=user5, member_password=123123123, member_nickname=사용자5, member_from_social=false)

 

 

 

결과 차이점

findById()

  • "=================="가 findById가 즉시 실행되고서 출력 됨
  • findById가 먼저 실행 됨

getReferenceId()

  • System.out.println(result_get);를 호출해야 member가 필요하다는 것을 알고서 proxy 객체가 select 문을 실행시킴
  • getReferenceId를 통해서 ID 값만 가져오는 경우 SQL이 실행되지 않는다.
  • 해당 데이터가 존재하지 않을 경우 EntityNotFoundException이 발생함

 

결론

findById()는 무조건 해당 SQL을 곧바로 실행하고, getReferenceById()는 함수를 호출하고, 실제로 그 데이터를 출력하거나 사용할 때 SQL이 실행됨. 단, ID값을 호출할 경우 SQL이 필요하지 않음

 

단순히, Entity의 ID 값만 필요한 상황이라면, getReferenceById를 통해 처리하는 것이 좋지만, EntityNotFoundException을 피하기 위해 반드시 DB에 해당 데이터가 있는 상황이라는 것을 고려해야 함

 

일반적인 상황에서는 FindById를 통해 Optional 값을 활용하여 예외처리를 진행하는 편이 좋음.

 

 

 

 

 

'항해 99 > Spring' 카테고리의 다른 글

lombok 주의 사항  (0) 2024.03.06
Controller, RestController 차이  (0) 2024.03.05
TDD(Test-Driven Development), JUnit  (0) 2024.03.03
Swagger 사용하기  (0) 2024.03.01
Spring - JPA Entity 연관 관계  (1) 2024.02.27