Spring, CS 공부 내용 1

김정용·2025년 1월 17일

기술면접 공부

목록 보기
1/15
post-thumbnail

이전 포스트에서 말한대로 해당 제목으로 Spring, CS에 관련된 내용들을 다룬다.

Spring Data JPA에서 새로운 Entity인지 판단하는 방법은?

Spring Data?

우선 Spring Data와 JPA가 무엇인지 알아야할 것 이다.

Spring Data는 Spring 프레임워크에서 제공해주는 Data에 접근할때 사용되는 방법이다.

어플리케이션을 만들게되면 여러가지 데이터들이 나온다.

예시

도서를 찾는 서비스를 예시로 들면

  1. 도서명
  2. 도서 번호
  3. 도서 장르
  4. 대출 유무
  5. 사용자 정보
  6. 등등

우리는 서비스를 사용하면서 알게모르게 계속해서 정보를 생성 및 수정, 삭제하는 과정을 거치게되고 이 모든 동작들은 이 서비스에 달려있는 DB에서 데이터를 가져오고 적재하면서 이루어지게 된다.

이 DB에서 데이터를 사용하게 접근시켜주는 방법이 SpringData이고, 여기서 제공해주는 하위 기술중 하나가 Spring Data JPA 이다.

JPA

Java Persistence API의 약자로, 자바에서 객체에 대한 정보를 저장하고 관리하기 위해 제공해주는 API들이다.

데이터에 접근하기위해 ORM(Object Relational Mapping)이라는 기술을 사용하게 되는데 이 ORM 기술을 통해 DB에 접근하는 방법이 JPA이다.

비슷한 내용으로 Mybatis가 있다. DB에 접근한다는 점은 JPA와 동일하지만, ORM을 사용하는 JPA와 달리 Mybatis는 SQL Mapper라는 기술을 사용해 DB에 접근한다.

isNew(T entity)

해당 내용을 다 기술하기에는 글이 너무 길어질 것 같아 다시 질문으로 돌아오겠다.

새로운 Entity임을 어떻게 DB에 알릴 수 있을까?

JPA 내부 JpaEntityInformation의 isNew(T entity) 메소드를 통해 알 수 있다.

public boolean isNew(T entity) {

    Id id = getId(entity);
    Class<ID> idType = getIdType();

    if (!idType.isPrimitive()) {
        return id == null;
    }

    if (id instanceof Number) {
        return ((Number) id).longValue() == 0L;
    }

    throw new IllegalArgumentException(String.format("Unsupported primitive id type %s", idType));
}

키 생성전략 사용

보통 Enitity를 생성할때, 다양한 키 생성전략 중 @GenerateValue를 통해 키를 생성한다면 DB에 저장할때 id를 할당된다.

DB에 저장하기 전에 메모리에서 생성된 객체는 id가 비어있으므로 isNew() 메소드가 이를 새로운 entity로 판단하게 된다.

키 생성전략을 사용하지 않는 경우

그렇다면 키생성 어노테이션을 사용하지 않고 직접 id를 할당하는 경우에는 어떻게 동작하는가?

위의 방식을 따르면 직접 id를 할당하는 경우 새로운 entity로 판단하지 않는다.

이때는 따로 Persistable<T> 인터페이스를 구현해 isNew() 메소드를 동작시켜야한다.

위에서는 JpaMetamodelEntityInformaiton 클래스의 isNew()가 실행되었다면, 인터페이스 구현시에는 JpaPersistableEntityInformation의 isNew()를 동작시켜야 한다.

신규 Entity 확인의 중요성

그렇다면 왜 신규 Entity를 확인해야하나?

SimpleJpaRepository 내부의 save()라는 메소드를 통해 persist, merge 중 한 가지 동작을 수행하게 되는데, 이때 isNew()의 return으로 두 동작 중 한가지 동작을 선택한다.

@Override
@Transactional
public <S extends T> S save(S entity) {

    Assert.notNull(entity, "Entity must not be null");

	if (entityInformation.isNew(entity)) {
		entityManager.persist(entity);
		return entity;
	} else {
		return entityManager.merge(entity);
	}
}

persist와 merge의 동작은 아래와 같이 동작한다.

  • persist
    - 새로운 entity를 영속성 컨텍스트에 추가
    - persist된 엔티티는 managed 상태
    - 이미 영속성 컨텍스트에 존재하는 entity와 동일한 식별자인 entity persist 시도 시 예외 발생

  • merge
    - 비영속 상태 또는 새로운 엔티티를 영속성 컨텍스트로 갱신
    - 수정시 사용

위에서 말한 케이스대로 키 생성전략을 사용하지 않고 직접 id를 할당 한 후 isNew()를 호출하지 않은 경우 생성된 entity가 새로운 entity인대도 신규 entity로 판단하지 않아 merge 동작을 수행하게 된다.

성능 손해

DB에 없는 entity 이지만 DB에서 해당 entity를 조회하는 동작을 불필요하게 선행하기 때문에 성능상 비효율적으로 동작하게된다.

성능상 손해를 보지 않기위해 직접 id 할당 시 Persistable인터페이스를 구현해야한다.

참고

면접 질문 내용과 답변의 일부는 기술 면접 구독 서비스 - 매일메일 에 있다.
흥미로웠다면 구독해보는 것도 추천한다!

profile
누군가의 롤모델이 될 때까지😇

0개의 댓글